# 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).