mydigitalstructure

To build an organistional webapp, there are a number of standard steps that you need to go through to ensure the project and outcome (as designed) are as expected.

Now that you have your design complete and agreement to move ahead with the build, the following will guide you through some standard steps that will help deliver the webapp as expected.

In this guide we will use the same example organisation as used in the designing quick start.


Collaboration

Set up conversation in console.mydigitalstructure.cloud to manage all the team conversations and links to key documents etc.

Use GSuite to manage documents, including those with client - get them to use comments.

If working in team the divide the work up by User Role.

Use project check-in meetings (in-person or online) to communicate progress, discuss design and an issues.

Example Project Check-In Document Example Testing Tracking Sheet


Planning

Use Planning template (link below) to capture all the tasks required to complete the build based on the design document.

Take each of the user role processes and classifying by effort (Skill): Basic (1 hour), Standard (4 hours), Complex (8 hours) and units of work required.

This will result in a total hours for the project.

Example Planning Sheet


Agreement

Get agreement with the client on cost, timeframes and work required by them.

Example Agreement


The Build

Zones;

Zones

Using console.mydigitalstructure.cloud;

  • Create a lab space
  • Create User Roles to match design
  • Create a User for each of the User Roles

Create the form foundation of the webapp;

Using the project costing sheet as a reference (which was based on the design).

  • In the layout file (1901.layout...) set up the side menu.
  • Create the form (HTML) file for each of the user-roles.
    Use the filename format [siteid].[user-role]-[version number]-url_[user-role*].html
    eg 1901.customer-1.0.0-url_customer.html
    * if the role is more than one word then use a hyphen eg customer-service
    The url_ part makes it easier to update the webapp pages, which is covered later.
  • In each of the files create the base form using the process in the design and comment in the details for each process

You now have the form foundation done!

Create the function foundation of the webapp;

Again using the project costing sheet as a reference (which was based on the design);

  • Create a file for each of the user-role process groups (ie as per the menu items in side layout)
    Use the filename format [siteid].[user-role].[process-group]-[version number].js
    eg 1901.customer.view.menu-1.0.0.js
  • In each of the files add code to add the controllers to the webapp as per the processes above. [show image of example]

You now have the function foundation done!

Set up the app foundation;

In "app.js".

Item Description
Standard controllers
app-init
Initialise the app; invoke mydigitalstructure.init with options:
  • viewStarting: (formerly viewStarted) Controller that is invoked before authetication to mydigitalstructure.cloud.
  • viewStart: Controller that will be invoked once authetication to mydigitalstructure.cloud complete - typically 'app-start'.
  • viewUpdate: Controller that is invoked with a message based on mydigitalstructure SDK activity. See View update messages section below for more details.
  • viewNavigation: Controller that is invoked when user navigates to new view.
  • views: Collection of view definitions.
  • viewAssemblySupport: Add standard controllers to the app namespace. Default true.
app-starting Invoked before authentication on mydigitalstructure.cloud
app-start Invoked after authenication on mydigitalstructure.cloud, isLoggedOn: is passed to the controller.
app-updated Invoked with messages from the mydigitalstructure SDK (see below)
app-navigation Invoked when user navigates to new view can then update navigation elements based on data ie badges or system data like user roles ie update menu options.
options
httpsOnly: If request is http, webapp will automatically redirect to https. Optional.
container: The main container for the webapp. Used with views.
registerDocument:
The ID of a public document that will be used as email template sent to a user when they register. Optional.
Use mydigitalstructure.cloud template tags [[TEMPLATE_LOGONNAME]] & [[TEMPLATE_INITIALPASSWORD]] to send logonname and password.
startURI: eg /app
startURIContext: eg #dashboard
authURI: eg /auth
authURIContext: eg /#auth
authURIIsHome: If URI is / then act as though the authURI setting. Typically set to true. Optional.
spinner: HTML for spinner eg '/site/1789/1789.working.gif'. Optional.
working: eg. '<div class="m-a-md text-center"><img src="/site/1789/1789.working.gif" style="height:25px;"></div>' Optional.
rows: eg 50
namespace: eg 'app'
logonSuffix:
To ensure logon names are unique across the mydigitalstructure.cloud platform. Typically '@[site]', eg '@1234'.
To logon name is stored as say jane@smith.com@1234, but the user enters as jane@smith.com mydigitalstructure then manages the adding and removal of the logonSuffix.
styles: { button: , buttonDefault: }
password: eg { minimumLength: 7 }. It should manage the setting on mydigitalstructure.cloud.
routing: Routing rules that control which views (uri + uriContext) are available when page refreshed etc. See below for more details.
editor: Options to use with rich text editors eg tinyMCE.
dateFormats: Set of date formats for use by momentjs. If not set it defaults to ['DD MMM YYYY', 'D MMM YYYY', 'D/MM/YYYY', 'DD/MM/YYYY', 'DD MMM YYYY HH:mm:ss']
Routing rules
Item Description
toURI
A set of rules that determine if webapp can route (navigate) to a uri (view)
  • uri: eg '/website'
  • uriContext: Can be many eg ['#website-dashboard']
  • onlyApplyIfURIDataContextNotEmpty: Rule is only applied if data context (passed with URI) is set ie /website/#website-dashboard/1234 where 1234 is he data context.
  • applyEvenIfReload: Rule is only applied if reload ie user has clicked the web-browser refresh button.
toStart
A set of rules that determine if webapp routes back to the start uri & uri context, as set in options when mydigitalstructure.init invoked.
  • uri: eg '*'
  • uriContext: Can be many eg ['*']
View update messages
From Status Message
myds-reset error New passwords do not match
myds-reset error New password can not be blank
myds-retrieve error-internal No object
myds-init start
myds-init end
myds-init uri-changed # of the new location eg #app-actions
myds-logon-init start
myds-logon-init end
myds-logon-init need-code
myds-logon-init code-sent
myds-logon-init error There is an issue with your user account ([Error Notes])
myds-logon-init error There is an issue with your user account ([Error Notes])
myds-logon-send start
myds-logon-send request-start
myds-logon-send request-start
myds-logon-send end
myds-logon-send password-expired
myds-send start
myds-send end
myds-send error
Varies
myds-send notify
Varies
myds-auth error not-authenticated
myds-view-access context-changed {hide: elements, show: elementsShow}
myds-register-space start
myds-register-space end
myds-register-templates initialised
myds-register-app start
myds-register-app end
myds-user-password start
myds-user-password end
myds-util-location end
myds-util-attachments-upload start
myds-util-attachments-upload end
myds-util-attachments-upload error
mydigitalstructure.cloud error message
myds-auth error not-authenticated
myds-core error There is an error with this app
myds-core error
mydigitalstructure.cloud error message

User Interface/Experience;

Item Description
Design Template
Icons
Fontawesome
Dates/time
Use momentjs to work with dates and times.
Numerals
Use numeraljs to work with numbers.
Utility functions
Use lodash to add useful utility functions. eg _.each() to interate through and array.
PDF Creation
Use pdfmake to create PDFs within the browser.
Text editor tips
As per the quick start guide suggest using sublime, but can use what every you prefer eg VSCode.
Suggest using two vertical windows;
  • One for form (HTML) coding
  • One for function (JS) coding.

mydigitalstructure Util SDK;

Item Description
Data caching
app.set
Store data in the local app data store at three logical levels; scope, context (optional) & name (optional).
eg app.set({scope: 'myscope', context: 'mycontext', name: 'myname', value: 'myvalue'});
app.get
Retrieve data stored in the local app data store at three logical levels; scope, context (optional) & name (optional).
eg var myvalue = app.get({scope: 'myscope', context: 'mycontext', name: 'myname''});
app.find
Find data in local cache.
var data = app.find(
 {
  dataController: 'certification-body-suppliers',
  dataContext: 'all',
  controller: 'certification-body-supplier-edit',
  context: 'id'
 });
View updating
app.refresh
Merge form (HTML stored with id = "_[scope]" and class="d-none myds-view-template") template with data, hide/show elements, initiate date pickers.
eg app.refresh({scope: 'myscope', data: mydata, hide: '#myelement'});
app.show
Dynamical create form (HTML) within existing form (HTML).
eg app.show('#myelement', 'Some HTML');
View updating using the view queue (app.vq)
Overview
Use the view queue to manage more sophisticated changes to the view (ie form changes).
You can set up a template (via code or of as HTML (Form) templates) and merge it with data (JSON). ie if need to display rows of the same data.
Example Uses
  • No template;
  • Initialise queue with; app.vq.init('#mycontainerelement', {working: true, disableSelector: '#mybuttonelement'})
  • Add content; app.vq.add('<div>Hello</div>');
  • Add content; app.vq.add('<div>World!</div>');
  • Render content; app.vq.render('#mycontainerelement', enableSelector: '#mybuttonelement');
  • With template & single data object;
  • Initialise queue with; app.vq.init('#mycontainerelement', {working: true, disableSelector: '#mybuttonelement'})
  • Add content; app.vq.add('<div>Hello</div>');
  • Add template; app.vq.add('<div>{{name}}!</div>', {type: 'template'});
  • Add content; app.vq.add({useTemplate: true}, {"name": "Jane"});
  • Render content; app.vq.render('#mycontainerelement', enableSelector: '#mybuttonelement');
  • With template & array of data objects;
  • Initialise queue with; app.vq.init('#mycontainerelement', {working: true, disableSelector: '#mybuttonelement'})
  • Add content; app.vq.add('<div>Hello</div>');
  • Add template; app.vq.add('<div>{{name}}!</div>', {type: 'template'});
  • Data; var rows = [ {"name": "Jane"}, {"name": "John"} ]
  • Loop through data & add content; _.each(rows, function (row) {app.vq.add({useTemplate: true}, row)});
  • Render content; app.vq.render('#mycontainerelement', enableSelector: '#mybuttonelement');
app.vq.init(selector, options)
Initialise the queue ready to update the form of the view.
options:
  • clear: clear the view queue
  • disableSelector: elements that match the selector will have the disabled class added to them.
  • enableSelector: elements that match the selector will have the disabled class removed from them.
  • queue: which queue is it, can be left blank and default queue will be used. Use if building up multi-view form changes at the same time or sub view queues that will get merged into a main view queue.
  • setDefault: set this queue as the default queue.
  • selector: which elements to change the form for.
  • working: show the working image in elements that match the selector
eg app.vq.init({...});
app.vq.reset(options)
Reset the view queue include the default queue.
eg app.vq.reset({...});
app.vq.clear
Clear the view queue include the default queue.
  • type: 'content' or 'template'.
  • queue: which queue is it, can be left blank and default queue will be used. Use if building up multi-view form changes at the same time or sub view queues that will get merged into a main view queue.
  • clearDefault: clear the default queue setting.
  • preserve: default is false, set to true if just want to clear the default setting.
eg app.vq.clear({...});
app.vq.add(content, options)
Add to the view queue.
options:
  • type: 'content' or 'template'.
  • queue: which queue is it, can be left blank and default queue will be used. Use if building up multi-view form changes at the same time or sub view queues that will get merged into a main view queue.
  • clear: clear the queue before adding the content (default false). Adding a template type content always clears the queue of templates, as there can only be one template. If need another template then need another queue.
  • useTemplate: when adding content to the queue merge it with the queues template. ie when going through the an array of data returned from mydigitalstructure.cloud. Template uses {{ }} as placeholders for the field eg 'Name: {{name}}.' In this case the content is the JSON data.
  • ifNoneContent: set content to this, if it is undefined
  • selector: when adding template content, if content is blank then use the HTML based on this selector.
eg app.vq.add({...});
app.vq.render
Render a template.
  • type: 'content' or 'template'.
  • queue: which queue is it, can be left blank and default queue will be used. Use if building up multi-view form changes at the same time or sub view queues that will get merged into a main view queue.
  • template: when adding content to the queue merge it with the queues template. ie when going through the an array of data returned from mydigitalstructure.cloud. Template uses {{ }} as placeholders for the field eg 'Name: {{name}}.'
  • data: JSON data to be merged into the template.
  • selector: element(s) to have their form (HTML) updated.
eg app.vq.templateRender({...});
app.vq .templateRender
Helper function for simple one step template render.
Render a template.
  • type: 'content' or 'template'.
  • queue: which queue is it, can be left blank and default queue will be used. Use if building up multi-view form changes at the same time or sub view queues that will get merged into a main view queue.
  • template: when adding content to the queue merge it with the queues template. ie when going through the an array of data returned from mydigitalstructure.cloud. Template uses {{ }} as placeholders for the field eg 'Name: {{name}}.'
  • data: JSON data to be merged into the template.
  • selector: element(s) to have their form (HTML) updated.
eg app.vq.templateRender({...});
app.vq.focus
Set focus on a form element.
  • selector: container to set focus onto first input element or element with class myds-setfocus.
eg app.vq.render([selector]);
Handlers
Based on class or id
The handlers code is in mydigitalstructure.util.
#myds-logon Logs on to mydigitalstructure.cloud. It uses input elements with ids #myds-logonname, #myds-logoncode & #myds-logonpassword to get values. Then enter key also initiaties log on.
#myds-register Registers a useron to mydigitalstructure.cloud. It uses input elements with ids #myds-spacename, #myds-firstname, #myds-surname, #myds-email & #myds-notes.
myds-click Invoke a controller based on click. Set data-controller.
myds-navigate .myds-router; span.dropdown-text (BS4), set the URL hash based on scope (controller) or target
myds-text-select
myds-select change; controller, scope, context, clean; invoke controller;
myds-dropdown On dropdown list item; invokes the controller and sets the parent text on click of item in list; bootstrap dropdown
myds-show, myds-invoke
myds-close Close a pop over
myds-export Export a table, created using controller util-view-table; context, filename, container, scope
myds-list On item; when clicked set it to Active and others not. Invoke controller.
myds-check On item; when clicked set it to Active and others not. Invoke controller.
myds-text Key up; scope, context, enter="stop", clean; invoke controller if no key up for 500ms.
myds-date change and clear date; enter="stop", scope, context; invoke controller if no key up for 500ms.
myds-text-select focusout, change; set data and element data-id.
myds-focus focusout; scope, controller, context, clean; invoke controller.
myds-change change; scope, controller, context, clean; invoke controller.
myds-sort click; sort, sortDirection, scope, controller, context, clean; invoke controller.
myds-validate focusout, keyup; scope, validate-controller; invoke validate-controller. See Validation section
myds-menu a.click; metisMenu; set active; ; invoke controller;
myds-tab a.click, show, shown;bootstrap tab & pills; set active; invoke controller
myds-modal show, shown; bootstrap modal; set active; invoke controller
myds-collapse show, shown; bootstrap collapse; set active; invoke controller
myds-popover show, shown; bootstrap popover; set active; invoke controller
myds-carousel slide, slid; bootstrap carousel; set active; invoke controller
myds-more click; show more rows for table built using controller util-view-table.
myds-page click; show a page for table built using controller util-view-table.
Object schema
learn.mydigitalstructure.cloud/schema
Debugging
Use core_debug_log and console.mydigitalstructure.cloud > DEBUG LOGS
Object structures
You can add fields to existing objects or create your object structure. To access your own (private) fields start with any underscore eg _myfield. Use console.mydigitalstructure.cloud > STRUCTURES.
Validation
mydigitalstructure has some inbuilt validation functionality.
Assuming element already has data-scope & data-context set.
The first thing is to add the myds-validate class to the element.
Then add attributes to the element;
data-validate-mandatory Add to element if want error if no value
data-validate-minimum-length Set a validation error when length of text is below this value. eg data-validate-minimum-length="10"
data-validate-maximum-length="[number]" Set a validation error when length of text is above this value. eg data-validate-maximum-length="50"
data-validate-numeral Set a validation error if not a number. eg data-validate-numeral
data-validate-numeral-minimum="[number]" Set a validation error if number and is below this value. eg data-validate-numeral-minimum="20"
data-validate-numeral-maximum Set a validation error if number and is below this value. eg data-validate-numeral-maximum="100"
data-validate-date Set a validation error if not a valid date. eg data-validate-date
data-validate-email Set a validation error if not a valid email. eg data-validate-email
Set data-validate-controller to have it invoked on keyup & focusout. Validation status is passed to controller.
And use app.get[{scope; [scope]}] to get the latest validation status
Class myds-validate-error is added to the element mydigitalstructure.util-x.x.x.css has this styled as a red border for the element. You can set your own styling for this class. You can also use the validation controller to add other visual elements/

You can also manually invoke a validation check using the util-validate-check controller. ie before saving of a new record.
eg app.invoke('util-validate-check', {scope: 'contact-edit-'});
Options:
  • If you invoke it with no options it will check any visible element with class myds-validate
  • If want to restrict the selection then:
    • selector: ie \u0091#contact-edit-surname
    • scope: and/or context:
    • - this will automatically include the myds-validate class in the selector
Utility controllers
If mydigitalstructure.init option viewAssemblySupport: is set to true some useful controllers will be add to your app eg util-view-table.
util-view-table
Create a table based on data stored on mydigitalstructure.cloud using the options:
  • object: mydigitalstructure.cloud data object.
  • container: ID of HTML element to form the table.
  • context: Unique context of the table, eg action-dashboard.
  • onComplete: Controller to invoke when table has been formed.
  • filters: mydigitalstructure.cloud query language filter.
  • customOptions: mydigitalstructure.cloud query language custom options.
  • options: noDataText:, rows:, orientation:, progressive:, class:, deleteConfirm: { text: 'Are you sure you want to delete this auditor?', position: 'left' }
  • format: row: { class:, data:, controller: }, fields: { caption: field:/name:, sortBy:,defaultSortDirection:, class:, data:, exportName:, fieldsList:, html: }.
util-view-select
Create an advanced select element using select2 component.
util-on-complete
Invokes the controller named in parameters object as onCompleteController:.
eg app.invoke('my-controller', {onCompleteController: 'my-other-controller'});
If onCompleteController: is not present and onCompleteControllerWhenCan: is, then it will be invoked.
util-view-reset
Resets input elements in a view with classes; myds-text, myds-check, myds-data, myds-data-view.
  • If scope: of the container that contains the input elements.
  • If data: is true then data scope is also cleared.
util-attachment-check
Check attachment file sizes before uploading to mydigitalstructure.cloud.
util-user-switches
Show list of spaces that user can switch into.
util-user-switch-to
Switch into a space.
Drop downs
Use class myds-dropdown. Can also use autocomplete.
Creating form dynamically
Function creating form - working with static form driving function
Importing
controller: util-import-upload-attach
Deleting
Use popover as a confirm.
Saving
Use data scope; it only updates when it changes.
If new data, then need to set defaults.

bootstrap 4;

Item Description
Classes
Common classes used in webapps:
m- Used to set margins ie space around an element
p- Used to set padding ie space within an element

Next stage of building;

Item Description
Sequence
  • Do form (HTML) then function (JavaScript).
  • For form do the dashboards first
  • Do a first parse of form & function and use //TODOs as placeholders.
Use form templates
_[template name] and the .refresh() method to blend with data. app.view.refresh( { scope: 'certification-body-supplier-edit', selector: '#certification-body-supplier-edit', data: data });
Data getting
Is it in the first get and can be merged with template {{}} or in a secondary get and set later
Mindset tip
Where is the form, where is the function?
Updating the form (HTML)
If you include the -url_ directive in the name of your file the page you create using console.mydigitalstructure.cloud with the matching url will be automatically updated eg:
  • If you create a page with url /app.
  • And then set the file name as say [site].app-x.x.x-url_[url].html, eg 1234.app.1.0.0-url_app.html, the page with url /app will be updated.
Developing locally
You can develop on your device, i.e. without having to upload the HTML, CSS & JS to the cloud, by using mydigitalstructure-local.

Testing

Testing to ensure the webapp is as per the design.

Item Description
Initialise
Use the lab space to imitialise data and then give access to the client.
Types of testing
There two types of testing:
  • By you as the builder; as part of the building process and alignment with the design documentation.
  • By the client; to ensure it meets their expectaitons in regards to user experience ie the form is usable and it functions as expected. Based on the design document they need to work through the webapp and feedback into the issues sheet. Typically this is referred to as User Acceptance Testing (UAT)
Testing by you as the builder
Use the Developer Tools in Chrome (or equivalent in your preferred browser). mydigitalstructure SDK sends messages to the console ie if it can't find a controller that it has been requested to be invoked.
Issues can also been logged on mydigitalstructure.cloud and access used console.mydigitalstructure.cloud > LOGS.
Testing by the client
The client will use user accounts for each ofthe different user-roles to test form & functionality eg the user experience.
Testing tracking
There are some good online issues tracking apps or you can use this example issues tracking sheet.

Go Live

The webapp (or part of it) is now as per the design and client has agreed for it go live!

Item Description
Concepts
In addition to the lab site that has it's own space to contain it's test data there are two more sites set up in the production space:
  • Next; The next site is a production ready user interface based on the tested lab version. It uses the production data and is subject the same security zoning. It allows the client testers to experience the site before it goes live. A hard to guess URL should be used for this site. console.mydigitalstructure.cloud can help with this.
  • Live; The live site is the one that the general users access. eg https://clientabcapp.mydigitalstructure.cloud
This type of set up is referred to "Blue / Green" - it allows for seamless upgrading and continous incremental improvement, as it is a matter of simply switching the live URL and next URLs between the two sites. It results in zero downtime for updates, meaning they can be more frequent as the risk is reduced significantly.
Set up
Create the production space and set up security etc
Set up the two sites (as a copy of site lab), import system data and user data.
Set up URLs.
Access URLs
You can use a mydigitalstructure.cloud URL or use your own domain with SSL which support@mydigitalstructure.cloud will help with setting up for you.

Life after Go Live

Once a site "Goes Live", there will be incremental improves using continous incremental improvement - following the same process as the lead up to "Go Live":

  • Continue build & test work in the lab space.
  • Once tested OK and client test OK, move the lab code to the next site.
  • Once tested OK and client test OK in the next and client agrees, switch the live URL to this site and the next site URL to what was the live site.
  • Do not update the next site until you are sure the general users are operating OK on the new live, just in case you need to roll-back. If you want to preserve this site, you can simply create another site as the new next site with a unique URL.

Done!


What next?

Need help with any part of the build or costing it, then email us @ hello@mydigitalstructure.cloud