# Thunder Client The Thunder client is a single page application written entirely in javascript. The source files are located in the ``/client`` folder of the repository. ## Editing The application is packaged with Browserify using gulp. In order to make changes to the client, gulp needs to be running. Gulp will automatically re-bundle the application when changes are made. ``` npm i ``` from the root directory to install necessary dependencies, and then ``` npx gulp ``` will keep gulp running and watching the files for changes. ## Flow #### Index The entry point of the application is ``/client/js/index.js``. It creates and appends Main #### Main Bit of a mess. Main is in charge of: - kicking off the initial business logic - showing the login dialog - handling logout - Appending various UI divs (Console, Bar, Notification, Alert), - managing opening and closing cards and their layout #### Router A much bigger mess. Router is a singleton who's main function ``.route()`` receives a string and passes a card to Main for display. - establishes all of the routes, automatically adding ``/client/js/cards`` - passes the active inmate id to cards when appropriate, or parameters. e.g. ``edit user zeus`` passes ``"zeus"`` to the ``editUser.js`` card - provides routes for the directory card ## Cards Almost all functionality in thunder is presented to the user in a card. Unfortunately there is a lot of boilerplate for cards. An example card looks like this: ```javascript var Diver = require('diver'); var ViewHelper = require('viewHelper'); var Events = require('events'); var Remote = require('remote'); var Main = require('main'); module.exports = function(id){ var _this = this; Events.help(this); Diver .a('new-card') .b('body') .c('header') .d('title').html('New Card') .d('close') .c('content') .d('hello').html('Hello World') .c('bottom') .d('enter').html('Submit'); var d = _this.div = Diver.pop(); d.enter.on('click', function(){ Remote.post('/not/a/real/api/call', {}, function(){ Notification.success('Everything worked.'); Main.closeView(_this); }) }) _this.layout = function(){ var s = ViewHelper.style(_this); d.hello.style({ text_align: 'center' }) d.enter.style(s.button, { margin_left: s.secondLeft, margin_top: s.margin }) } ViewHelper.help(_this); } ``` - It's important that ``.div`` is set, otherwise nothing will be added to the screen - ``Remote`` is used to communicate with the API - ``ViewHelper.help`` will automatically add functionality to the X close button - ``ViewHelper.style`` gives everything the default style, and exposes values in the ``s`` style variable - ``Notification`` is a singleton for showing notifications at the top of the screen - ``Diver`` is for DOM expression. #### Automatically required and registered Any js file in the ``/client/js/cards`` folder will be automatically included in the application bundle and can be accessed by ``require('cards/cardName')``. It's important that a card is named in camelCase so that the in-application router registers it correctly. ``newCard.js`` will be available at the ``new card`` address when using the ``~`` console. ## Forms Forms exist as json objects served by the backend. They can be accessed and displayed with: ```javascript var Form = require('form'); var Remote = require('remote'); function(){ var _formInstance; Remote.getForm('form_title', function (form) { _formInstance = new Form.instance(form); _this.div.append(formInstance.div); _this.layout(); } //some time later setTimeout(function(){ var formValues = _formInstance.report(); // probably send the form data to the server }, 10000) _this.layout = function(){ _formInstance.layout(); } } ``` - The server first looks for a form as a .json file in ``/forms`` - If it doesn't find a file of that name, it looks in ``/forms/forms.json`` A simple form might look like this: ```javascript { "title": 'example_form', "columns": "1" "labels": "beside", "labelRatio": 0.4, //how wide the label column is "components": [ { "type": "input", "key": "key_in_database_eventually", "label": "Simple input" } ] } ``` Forms get complicated when they become nested (a form can exist as a component of another form).