User Interface Coding Tools - Protecting Vulnerable Populations

User Interface Coding Tools
Background Check System
IT Technical Design Guide
Version 01
7/29/2017
Protecting Patients through Background Checks
Table of Contents
1
2
Model –View-Controller (MVC) ............................................................................................................ 3
1.1
MVC Solution Structure ................................................................................................................. 3
1.2
Bcs.Web.Mvc.Website.Bureaucrat ................................................................................................ 4
jQuery and Knockout.js ....................................................................................................................... 4
2.1
Knockout ........................................................................................................................................ 5
2.2
Knockout Mapping Plugin .............................................................................................................. 7
2.3
Knockout-delegatedEvents Plugin ................................................................................................ 8
3
AjaxPostUtils.js..................................................................................................................................... 9
4
Json Results Properties .................................................................................................................... 10
4.1
IsSuccessful ................................................................................................................................ 10
4.2
ErrorMessages and ErrorMessage ............................................................................................. 10
4.3
RedirectUrl ................................................................................................................................... 11
5
Script Minification and Combining ................................................................................................... 11
6
Bcs.Web.Mvc.Website.Bureaucrat.Controllers ............................................................................... 12
7
CSS and Branding .............................................................................................................................. 12
User Interface Coding Tools
Version 01 | 7/29/2017 | IT Technical Design Guide | Audience: State IT Staff
Page 2 of 12
Protecting Patients through Background Checks
1
Model –View-Controller (MVC)
The Background Check System (BCS) website is a model-view-controller (MVC) version 3 application.
The application uses the Razor View Engine to render client views. For Visual Studio 2010, MVC 3 is
an add-on found here: http://www.microsoft.com/en-us/download/details.aspx?id=1491. Visual Studio
2012 and above include support for MVC 3 and later versions.
1.1
MVC Solution Structure
The core of the website application consists of three projects:
Bcs.Web.Mvc.Website.Bureaucrat, highlighted in blue above, contains the Content and MVC Views.
This is the project that gets published. Bcs.Web.Mvc.Website.Bureaucrat.Controllers, highlighted just
below in yellow, contains the MVC Controllers. Bcs.Web.Mvc.Website.Bureaucrat.Models contains the
view model classes. The .Cjis projects include Controllers and Model classes used with CJIS encryption,
described in the “Database and Application Deployment” IT guide. Cjis Views are included in a Cjis folder
in the main Bcs.Web.Mvc.Website.Bureaucrat project.
User Interface Coding Tools
Version 01 | 7/29/2017 | IT Technical Design Guide | Audience: State IT Staff
Page 3 of 12
Protecting Patients through Background Checks
1.2
Bcs.Web.Mvc.Website.Bureaucrat
One thing to note about the organization of Views in this project is that they are contained in folders with
Views, and subfolders for Partials and Dialogs as show below.
This folder separation of Partials and Dialogs Views is provided by a custom MVC ViewEngine
(FindViewsViewEngine). The sole purpose of this ViewEngine subclass is to resolve MVC View search
by including the Dialogs and Partials path in the search paths.
2
jQuery and Knockout.js
Much of the functionality in this website project is provided by jQuery and Knockout. In addition, jQueryUI is used for dialogs and tabbed views. As of this writing, the version of jQuery used in the BCS is
1.11.1, jQuery-UI is 1.11.0, and Knockout is 3.2.0. Knockout.js was shipped with Visual Studio 2012,
and is also available at http://knockoutjs.com and via Nuget.
The BCS uses two additional plug-ins for Knockout. Knockout-mapping-latest.js is used to map view
model properties into Knockout observables. The knockout-delegatedEvents.js plug-in by Ryan
Niemeyer enables simple delegated event handling in Knockout views.
User Interface Coding Tools
Version 01 | 7/29/2017 | IT Technical Design Guide | Audience: State IT Staff
Page 4 of 12
Protecting Patients through Background Checks
2.1
Knockout
Knockout.js is a JavaScript two-way binding library that the BCS uses primarily for user interface grids.
The normal pattern is for the data from a C# class view model to be written to the MVC View. This data is
then mapped by the Knockout mapping plug-in into a JavaScript object. This JavaScript object is then
bound to an HTML <div> /<table> pair.
var DeterminationHiringDecisionModel = function () {
var self = this;
// Other functionality
}
var vm = new DeterminationHiringDecisionModel();
ko.mapping.fromJS(@Html.Raw(Json.Encode(Model)), '', vm);
Finally, inside the jQuery document ready function, the JavaScript object is bound to the appropriate
HTML element.
ko.applyBindings(vm, document.getElementById('fsDHDResults'));
An example of a grid (where this grid <div> would be inside the HTML element where the Knockout
view model was bound):
<div class="grid" data-bind="visible:
DeterminationHiringDecisionResults().length > 0">
<table id="applicationsTbl" class="sortableGrid" summary="List of
Determination Hiring Decisions Results">
<caption>Determination Hiring Decision Search Results</caption>
<thead>
<tr>
<th class="nosort">Locked</th>
<th class="ApplicationId" scope="col">App #</th>
<th class="ProviderName" scope="col" style="max-width:
16em;">Provider</th>
<th class="LastName" scope="col">Last</th>
<th class="FirstName" scope="col">First</th>
<th class="SsnLastFour" scope="col">SSN</th>
<th class="nosort" scope="col">Employment<br />Status</th>
<th class="nosort" scope="col" style="text-align:
center;">Action</th>
</tr>
</thead>
<tbody data-bind="foreach: DeterminationHiringDecisionResults,
delegatedHandler: 'click'">
<tr>
User Interface Coding Tools
Version 01 | 7/29/2017 | IT Technical Design Guide | Audience: State IT Staff
Page 5 of 12
Protecting Patients through Background Checks
<td><span class="lockDetail ui-icon ui-icon-locked" databind="visible: IsLocked(), attr:{title: 'Record is being
edited by another User'}"></span></td>
<td class="max6" data-bind="text: ApplicationId"></td>
<td style="white-space: normal"><span class="link" dataclick="viewProvider" data-bind="text:
ProviderName"></span></td>
<td class="max10" class="elipflow"><a
class="viewPersonSummary link" data-bind="attr: {title:
'view ' + FirstName() + ' ' + LastName() + ' Person
Summary'}, text: LastName"></a></td>
<td data-bind="text: FirstName" class="max5 elipflow"></td>
<td style="white-space: nowrap" data-bind="ssn: Ssn"></td>
<td databind="template:{name:'EmploymentStatusTemplate'}"></td>
<td data-bind="template:{name:'ActionsTemplate'}"></td>
</tr>
</tbody>
</table>
@{ Html.RenderPartial("Paging",
Model.DeterminationHiringDecisionResults); }
</div>
The ‘data-bind’ attributes tell Knockout what actions to take and what properties to bind. The databind="visible: DeterminationHiringDecisionResults().length > 0” attribute on the grid
<div> tells Knockout to only show this grid when there are DeterminationHiringDecisionResults. The
DeterminationHiringDecisionResults array is a Knockout observable, thus if there happens to be only
one result (one grid row) and that row is removed (by a ‘hiring’ action), the grid <div> will be hidden.
The data-bind ‘foreach’ attribute on the table body element (<tbody data-bind="foreach:
DeterminationHiringDecisionResults, delegatedHandler: 'click’”>) tells Knockout to
iterate through the DeterminationHiringDecisionResults array creating table rows from the <tr>
template inside the table body element. Most of the time, view model properties are displayed in grids
with the ‘text’ binding, like:
<td class="max6" data-bind="text: ApplicationId"></td>
The Knockout text binding outputs the property as text. Occasionally grids need to output a property as
HTML and use the Knockout HTML binding. In this case, the Address has been formatted with <br>
tags which need to be honored in the resulting display:
<td class="max10" data-bind="html: Address"></td>
User Interface Coding Tools
Version 01 | 7/29/2017 | IT Technical Design Guide | Audience: State IT Staff
Page 6 of 12
Protecting Patients through Background Checks
The BCS also uses a custom ‘yesno’ binding. This binding outputs a bool or nullable bool as either ‘Yes’,
‘No’, or blank if null.
<td data-bind="yesno: CanSubmitElectronically”></td>
The custom ‘date’ binding outputs a date formatted as mm/dd/yyyy, while the ‘datetime’ binding also
appends the time to the date. There is also a custom SSN binding that prepends a hyphen to a 4
character SSN and outputs as is a full SSN.
2.2
Knockout Mapping Plugin
The Knockout mapping plugin (knockout-mapping-lastest.js) by default maps all fields in a data model
into Knockout observables. This is simple, fast, and works well for our multi-page application. There are
occasions when we want to augment the resulting mapped object with observables or properties without
needing to include these properties in the original C# data model. In the following snippet, we add 3
observables to each Payment object as it is mapped:
In these cases, this mapping variable replaces the default empty string in the ko.mapping.fromJS
function:
User Interface Coding Tools
Version 01 | 7/29/2017 | IT Technical Design Guide | Audience: State IT Staff
Page 7 of 12
Protecting Patients through Background Checks
2.3
Knockout-delegatedEvents Plugin
The knockout-delegatedEvents plugin (knockout-delegatedEvents.js) provides a simple unobtrusive
mechanism for hooking up ‘click’ and ‘change’ events. To use knockout-delegatedEvents, include the
events you intend to catch in a Knockout data-bind attribute. The scope of this data bound element must
include the elements for which you are intending to catch events. It is typical to include a delegated
events data-bind attribute on some top-level <div> or fieldset element:
<fieldset id="fsAppeals" data-bind="delegatedHandler: ‘click’">
Or when you need to catch both ‘click’ and ‘change’ events:
<fieldset id="fsInfo" data-bind="delegatedHandler: ['click',
'change']">
User Interface Coding Tools
Version 01 | 7/29/2017 | IT Technical Design Guide | Audience: State IT Staff
Page 8 of 12
Protecting Patients through Background Checks
With this in place, adding a ‘data-click’ attribute on a button will cause the referenced function on a view
model to be invoked when the button is clicked:
<button data-click="AutoExtend">Extend Appeal Date</button>
The delegated events plugin helpfully includes a reference to both the data item (usually the array
element represented on the grid row) and the JavaScript event variable in the parameters to the view
model function.
3
AjaxPostUtils.js
Although most JavaScript is currently on-page JavaScript, Ajax functionality is contained in
AjaxPostUtils.js. This script provides several functions that are used throughout the BCS MVC
application.
Pages with search filters (Determination in Process, Ready for Determination, Not Yet Submitted, etc.)
use Ajax posts with callbacks (which could be easily changed to Promises) to avoid refreshing the whole
page when a changed filter criteria is applied. The typical search page posts the filter criteria and supplies
a <div> tag selector where the resulting PartialView should be rendered.
iaApp.PostFormForPartial(<mvc route>, <form id>, <selector>);
This action is often encapsulated in the helper function searchPartialHelper.setup (in bindings.helper.js),
which observes the Search button and automatically generates the search request (using
iaApp.PostFormForPartial) and places the resulting PartialView in the tag referenced in the passed
jQuery selector. When used like this, Search buttons should include a CSS class of ‘gridRefresher’.
A similar function in AjaxPostUtil is iaApp.PostFormWithSuccessHandler. This function posts a form,
but the callback is only executed if successful. Validation errors will be automatically appended to the
form’s validation message area and will not result in executing the passed callback. This
iaApp.PostFormWithSuccessHandler function is often used to post dialog form data.
User Interface Coding Tools
Version 01 | 7/29/2017 | IT Technical Design Guide | Audience: State IT Staff
Page 9 of 12
Protecting Patients through Background Checks
The example below is typical of displaying a dialog and then posting the dialog form with
iaApp.PostFormWithSuccessHandler. The ReviewExtensionRequestion function is called when a
user clicks the ‘Review Extension’ on a grid row. The function posts the AppealId to the controller, which
renders a partial view (the dialog). The partial view is written into the page in the extensionEditor <div>,
then the dialog is opened (bcsdlgs.Open). When the user clicks ‘Save’ on the dialog, the SaveApproval
function is called (shown below). SaveApproval uses iaApp.PostFormwithSuccessHandler to post the
form to the controller. Any validation errors will be displayed and the callback not executed. A successful
save executes the callback, which maps the return data to a Knockout object, and then replaces the
existing row (saved temporarily in self.activeItem) with this replacement object.
4
Json Results Properties
4.1
IsSuccessful
BCS JSON results generally return the property IsSuccessful. Looking at this flag, for example, is how
the iaApp.PostFormWithSuccessHandler determines whether to call the callback function.
4.2
ErrorMessages and ErrorMessage
When IsSuccessful is false, BCS JSON includes an array of error messages. This array is used by
iaApp.PostFormWithSuccessHandler to render validation messages. When there is no form involved
but there are error messages provided by the MVC Controller action, this array is concatenated into
ErrorMessage. This message is often displayed in these cases by calling iaApp.DisplayErrorMessage.
This call displays the message in a warning area below the main navigation menu.
User Interface Coding Tools
Version 01 | 7/29/2017 | IT Technical Design Guide | Audience: State IT Staff
Page 10 of 12
Protecting Patients through Background Checks
4.3
RedirectUrl
Some JSON results also include a RedirectUrl property. This is the URL for redirecting the browser.
An Ajax post to start an appeal, for example, might return IsSuccessful = true, and a RedirectUrl
to the appeals in process page with a query string to automatically select this new appeal.
5
Script Minification and Combining
Scripts are minified and combined using the Microsoft Ajax Minifier (http://ajaxmin.codeplex.com). The
build directives are specified in the Bureaucrat.ajaxmin file in the web project Build folder:
User Interface Coding Tools
Version 01 | 7/29/2017 | IT Technical Design Guide | Audience: State IT Staff
Page 11 of 12
Protecting Patients through Background Checks
6
Bcs.Web.Mvc.Website.Bureaucrat.Controllers
This project contains all of the MVC Controllers except for one Cjis encryption-specific controller
(OffensesController), which is in a separate project
(Bcs.Web.Mvc.Website.Bureaucrat.Controllers.Cjis), and a Dev/debugging controller in
Bcs.Web.Mvc.Website.Bureaucrat.Controllers.Dev.
The simplest flow from database to screen is: db -> DTO -> Controller view model -> JSON -> Knockout
client view model. DTOs are never rendered directly to views. (These controller view models are
contained in the Bcs.Web.Mvc.Website.Bureaucrat.Models project.)
In addition to simple DTOs that typically represent a single table, the BCS makes significant use of
custom DTOs (found in Dto/Custom folders in the appropriate middle-end module project). The
PersonProfile custom DTO contains fields from Person, Address, PersonAddress, and Alias.
MVC Controller actions that load Views (for example, a request for a partial view representing a grid)
typically call a middle-end search, which returns an IList of a search result DTO. These DTOs are
converted in view models and rendered to the Razor View. Much of this conversion effort is kept out of
the Controller code and instead handled by convenient constructor methods on the view models that take
a search result DTO as a parameter. These DTO-specific view model constructions often take advantage
of additional parameters that reflect the user’s Permissions.
This conversion of a list (in this case an IPagedList) of ReadyForDeterminationSearchResult custom
DTOs is typical:
IPagedList<ReadyForDeterminationModel> readyForDeterminations =
searchResults.ToConvertedList<ReadyForDeterminationSearchResult,
ReadyForDeterminationModel, bool, bool>
(
SessionState.UserInfo.HasPermission(
Permission.EDIT_CRIMINAL_HISTORY_DETERMINATION),
SessionState.UserInfo.HasPermission(Permission.REGISTRY_RESEARCH),
7
CSS and Branding
The primary CSS files are in Content > Common >Styles folder. These primary files (Theme.css and
jquery-ui.css) contain the bulk of the styles. CSS in these files can be augmented or overridden by the
Theme.css in the appropriate Content> [dept code] > Styles folder.
The banner branding for the site is contained in a department Views folder: Views > _Departments >
[dept code] > Partials/BrandingHead.cshtml.
User Interface Coding Tools
Version 01 | 7/29/2017 | IT Technical Design Guide | Audience: State IT Staff
Page 12 of 12