2.8 KiB
#Architecture
Captures how the app is build and what happens where.
##Build
Vendor libraries are fetched through npm. For CSS libs we @import
them in LESS, for JS libs we require
them using Browserify. All app dependencies are in package.dependencies
rather than package.devDependencies
, so that David can see them and we get a nice icon if things go out of date.
##Code
###JavaScript
####Ractive
The app is written as a series of Ractive components. We use the library for both views and models. The important bit is that we can observe changes on them. So that these changes propagate, we use the ractive-ractive plugin. This means that one ractive can be passed another ractive as a data attribute. All ractive components have a name
attribute which makes it easier to debug them when things go wrong.
####Projects
The projects collection is a simple stack. When rendering it, we are actually working off an index. Index is a list of tuples where first value is an index of a project and the second is an index of a milestone. When sort order changes, we only change the index. models/projects
has a map of functions which handle the different sort orders.
####Mediator Pattern
Whenever something happens that other components on the page should know about, we use the mediator component. It is accessible by extending the utils/ractive/eventfull
class. You can then call @subscribe(message, fn)
or @publish(message, data...)
. Subscriptions are automatically cancelled on teardown.
####Config
All configuration lives in models/config
.
####Router
All routes are handled via modules/router
. There you can see that each route is prefixed with a context - name of the view which will handle it and a bunch of functions to execute. As an example, the project and milestone routes both add a project, behind the scenes, if it does not exist already.
####Icons
Icons are loaded on the page through views/icons
. This view has a list of entity codes which correspond to codes provided by Fontello custom icon packs.
####Async
Whenever there is an asynchronous block of code, wrap it in models/system.async()
which returns a callback function which you call when done. That gives us a consistent loading spinner when things are happening.
###CSS
When developing in LESS, be aware that LESS Hat is imported into the app.
##Tests
Tests run via Mocha and Blanket for coverage. You can use proxyquire to override requires, but results in incorrect test coverage when used with Blanket.
The test/fixtures
folder contains example responses from GitHub.