Skip to main content

Posts

Showing posts from August, 2017

The Conversion: I see UI/X - Part 1

For as much development and blogging that's been happening, I haven't moved the project too far along. In fact, I am behind on my goal of being completed by the end of August.  That said, the new TRIPS application is almost at the top of the development hill - much of the ground work has been developed and the more I work on it, the clearer the vision becomes. This blog post will revolve around the user interface and experience for the landing and trip templates. Starting with the landing page, a New Trip button needs to be added which routes to the trip template with an id of 0. Remember, a 0 id will inform the saveTrip() code to insert a trip as opposed to updating it. The new trip button isn't something the user is going to use all the time, but it still needs to be obvious. I initially thought the right side of the filter would be a good place, but the filtering capability may be expanded in the near future with options. So I will start with putting the button o

The Conversion: Trips for Keeps - Part 3

With the core methodology set up in Part 2 to get the trip data from the AngularJS front end to the CF middle tier, we are ready to save to the database. All of our custom data is stored in Oracle, but the following will apply to most, if not all, relational databases. I try to steer away from doing anything overly fancy to minimize refactoring down the road if platforms should change. At the moment, the trip function only receives the trip data and breaks it down into a CF structure and then returns that structure back to the application. <cffunction name="saveTrip" returnformat="json" returntype="struct" access="remote"> <cfset _params = getHttpRequestData()> <cfset _content = deserializeJSON(_params.content)> <cfset _trip = deserializeJSON(_content.objectData)> <cfreturn _trip> </cffunction> Now I have a design decision to make. I can either create individual functions to save e

The Conversion: Trips for Keeps - Part 2

Ack! A few days off work and then updates to other applications that needed to be made has delayed more work on TRIPS. But we're back and ready to continue. In the last post , we started to build out the trip.html template and it's corresponding controller. The dataService was updated with an abstraction that would allow a CFC method to be called and data to be passed.  This post will focus on retrieving that data from the dataService to the CFC method. Before we get started, I thought it would be kind of cool to keep a count of the number of lines of code for the project.  I'm not sure if it will provide any insight, but it might be nice to compare the line count to the number of lines in the Flex application.  Rather than posting the counts on each blog post, I have created a separate post tracking the line count per post . In review, let's take a look at the dataService code that's going to call the Coldfusion function to save the trip information. this.p

The Conversion: Line Counts

The following chart is a list of blog posts and the corresponding line counts of the TRIPS application per post.  The blog series is a semi-detailed process of converting a Flex based application to AngularJS. Blog Controllers Templates Data Route Main trips landing trip landing trip Service CFC Trips for Keeps (P. 1) 3 23 12 45 23 32 94 8 9 Trips for Keeps (P. 2) 3 23 18 45 23 32 102 8 9 Trips for Keeps (P. 3) 3 23 28 45 27 32 175 8 9 I see UI/X 3 23 39 56 36 32 175 8 9 I see UI/X - Part 2 3 23 70 53 93 32 272 8 9

The Conversion: Trips for Keeps - Part 1

With the development of the landing page, we are ready to add the trip details page. This page will be used to edit the trip information, manage sponsors, activities, and waivers. Due to the amount of data displayed on the page, I think that the participants listing will get their own page. We've already, in the last post , added the trip route to the router.  But just as a refresher, it looks like the following: angular.module('core').config(function($stateProvider, $urlRouterProvider) { $urlRouterProvider.otherwise("/trips/landing"); $stateProvider .state('landing', {url: "/trips/landing", templateUrl: "apps/trips/templates/landing.html"}) .state('trip', {url: "/trips/trip/:id", templateUrl: "apps/trips/templates/trip.html"}) }); The next steps are to create the trip template and controller files.  Because a parameter is being passed to the trip controller, the $stateParams

The Conversion: Lay of the Landing Page - Part 3

In Part 1 of Lay of the Landing Page , the basic landing page framework was established.  In Part 2 , the table was added as well as some AngularJS filtering capability.  For Part 3, the participant count, column sorting and routing to the trip edit and detail page will be developed. The participant count is fairly straight forward to get as it is just a count of records in the trip_persons table. The more difficult part is determining who completed the required documentation.  Fortunately, because this is conversion project, the code already exists to get this data. Since college sponsored trips mostly revolve around the students, the participant count on the landing page will be the number of students on the trip. But when user drills down into a trip, a breakdown of all participants will be displayed. With the Students column (student participant count) added, we can see that the table is getting a little crowded. There are three options: reduce the number of columns; or co

The Conversion: Lay of the Landing Page - Part 2

In Part 1  of developing the landing page for the new travel application, we set up the landing controller and created the the CF function to get the trips relevant to the user. The next step is to begin developing the UI, the landing.html template, so we can actually see the trips. Just a quick refresher - the landing controller code is a follows: angular.module('core').controller('LandingController',['$scope','dataService', function($scope,dataService){ $scope.trips = []; dataService.call('getTrips').then(function(data){ $scope.trips = data.data; }) }]); And the landing template is empty at the moment. <div ng-controller="LandingController as ctrlLanding"> <h3>TRIPS</h3> </div> The first step for the landing template is to create the table. This includes setting up the columns and looping through the $scope.trips array and generating the rows. <div ng-controlle

The Conversion: Lay of the Landing Page - Part 1

In the last post  the groundwork has been laid for real development to begin. The data service, router, and landing pages have been created and are ready for code. The last thing to add for this part of the process is the Coldfusion component. A data folder has been added to store any cfcs relevant to the TRIPS application. The first is to write the CFFUNCTION that will return the list of trips. My development pattern for creating CF functions is fairly routine.  First, decide on a name, parameters and return type.  Sometimes the naming of a function is the hardest part.  I've settled on actionDataObject.  So in this case, the function will be named: getTrips.    At moment, the landing controller (landing.js) is empty. angular.module('core').controller('LandingController',['$scope','dataService', function($scope,dataService){ }]); The basic task of this controller is getting the list of trips.  First is the establishment of an empty trips

The Conversion: Take Off and Landing

The first step in my high level development process is to create the landing page and determine it's contents. In the prior post , it was decided that the new travel system landing page will display a list of trips relevant to the user.  These would be trips that they created and / or trips that other users shared with them. In the MAIN.CFM post, I outlined the folder structure that I generally use get a project off the ground.  For this post, we are going to add the following: routes/routes.js services/dataService.js controllers/landing.js templates/landing.html ROUTES.JS I don't use the native ngRoute for AngularJS, but instead settled on the AngularJS UI-Router .  To me, this router seems easier to implement and understand than ngRoute. The route.js file starts out as the following: Basically, this little bit of code is saying if the route doesn't match any of the $stateProvider.states, then route to the landing route.  The landing route itself is going

The Conversion: UI / UX Plan - Trip Creation

Application user interfaces usually design themselves. Instructional information goes at the top of the pages as well as any string filters. Distinctive filters are located along the left or right side.  Lists are displayed in a table with the most important columns on the left and least important on the right.  Remove and delete options are almost always on the far right such that the user will not accidentally click on the icon. User experience (UX) gets a bit more tricky. Should we always prompt before deleting something?  Should the columns be sortable? Do we save the filter information so the user doesn't have to enter it in again? After a user modifies data, what kind of feedback should they get? Lots of questions can be asked - but the answer to each one generally means more coding and more maintenance. My biggest consideration when creating the UX is the technical aptitude of the user. That said, over the past few years, especially with the near complete migration to work

The Conversion: Data Planning

Now that the basic coding is framework is set up, it's time to step back before any development and take a look at the existing data structures as well as the user interface. Data Structures The TRIPS application was developed and implemented back in 2010.  There have been minimal table updates and the data gathered seems to meet the need of the users.  That said, since a front end rewrite is being done, it's a good idea to take a look at the back end database as well.   There are 14 tables that support the application. Ten of those tables are geared around a "trip" while the other 4 are tables used to buttress the app. I think the best approach here is to simply go through each table and see if there are any design flaws and / or data elements that were captured but have no real use. This process is important to so because the outcome may save time in not developing unnecessary interfaces to capture unused data. DC_STRAVEL_TRIPS Each row in the DC_STRAV

The Conversion: MAIN.CFM

Within the current development pattern I have for our portal system, the main.cfm is the starting point for an application. For the most part, this is really boilerplate and serves to get the application off the ground. The way the portal works is that the user lands on the main menu page and provide with a menu of options. Each option is called a function and is assigned a unique id. When the user clicks on a menu option, the page is reloaded with the function id. The process checks to see if the user is actually allowed to have access to the function. It then accordingly looks up the path and displays the page via a . In the case of the TRIPS application, the included file is the main.cfm page for the application. So far the project looks like this: we have the folder structure defined with no files aside from the main.cfm. The main.cfm contains a few javascript includes, the overarching controller for the application as well as the route viewer. The next blog post will foc

The Conversion: Getting Started

So enough about me and my employer from the first two blog posts.  It's time to get some real work started.  This project is about converting the Adobe Flex based TRIPS application to and AngularJS front end.  Now, I have done some work in Angular 2.x (Typescript), but that was a separate deployment into a different (but similar) framework.  Because of the time frame I have to convert this application and it's overall complexity, I am going to stick with AngularJS. Before I get into details, just a quick note about the application framework.  In order to make the management applications easier, I built a small portal based on the concept of users, roles and functions.  All employees can be users of the system provided they accept the FERPA agreement. Access to functionality depends on the roles the user has and which functions are assigned that role. For example, our faculty users have access to class lists and course information via their FACULTY role.  But student accounts