blob: f989cff0bf5d6858670d226edc276b855cc53e7d [file] [log] [blame] [view]
# Fauxton Code Overview
This page documents a little practical information about the Fauxton codebase to help you get up to speed.
## Backbone and React
Fauxton was originally written in [Backbone](http://backbonejs.org), but has since been rebuilt around [React](https://facebook.github.io/react/). Backbone models and collections are still being used for server-side data retrieval, storage, and URL routing. However, the plan is to completely phase out Backbone over time.
### React and the Flux pattern
You can read more about [React](https://facebook.github.io/react/) and [Flux](https://facebook.github.io/flux/docs/overview.html)
on their sites, but a few quick words about both.
React is a relatively new framework created by Facebook, built on the idea of automatic DOM re-renders. Contrary to other
frameworks, React decides when and where to redraw your UI based on changes to the underlying data set - and uses
a *virtual DOM* to handle the re-rendering. The key decisions to moving to React were simplicity, performance and
ease of testing. Check out [this page](https://facebook.github.io/react/docs/why-react.html) for a few more remarks.
Flux is primarily a *pattern* for keeping your code organized over time. One of its key ideas is to have *one-way
communication* as shown in the [diagram here](https://github.com/facebook/flux).
Note that Fauxton has no dependency with the Flux code as it implements its own dispatcher and reduce stores. The information flows like this:
1. User clicks on something in a React component,
2. the component fires an action (in an `actions.js` file),
3. the action dispatches an event (for us, that's the `FauxtonAPI.dispatch()` call),
4. stores listen to these events (in their `dispatch()` methods), change the content of the store, then notify
anyone that's interested that the store has changed,
5. finally, it comes full circle. React components listen for changes in the store by listening to their `change`
events. That's the purpose of the `storeName.on('change', this.onChange)` lines you'll see in the code.
So why do all this. The benefit is that it standardizes how data moves around the application, and keeps things
simple - regardless of how much bigger the application gets. This is pretty cool.
Here's a simple example: imagine if a user shrunk/expanded the main sidebar, and multiple components in the page
needed to know about it to make use of the new space. Maybe one was a graph and needed to redraw for the extra space,
and maybe another component could switch from "basic" to "advanced" view or something.
With this pattern, you can just publish the single event, then each store could listen for it, change whatever data was needed
internally, then notify any components that was listening: and they would then have the choice to rerender or not,
based on what changed. This is basic "pub/sub": allowing you to keep code loosely coupled, but still communicate.
### Moving to Redux
There are a few drawbacks in the implementation above though. For instance the reduce stores rely on Backbone.
For this reason and others, it's encouraged that new components use Redux (https://github.com/reactjs/redux), which follows the same principles as Flux. Additionally, use React Redux (https://github.com/reactjs/react-redux) to easily connect a Redux store to your React components.
## Addons
Each bit of functionality is its own separate module or addon. Addons are located in their own `app/addons/myaddon-name`
folder. As noted above, new code is being written in React so please favour React components over backbone views.
A good place to get started is to read through a couple of the existing addons. A good starting point is
[app/addons/verifyinstall](app/addons/verifyinstall). This is relatively self-contained and maps to a specific page in
the Fauxton interface so you can see exactly where it appears and what it does.
Each module must have a `base.js` file, this is read and compiled when Fauxton is deployed. A `resources.js` file
is usually used for your Backbone.Models and Backbone.Collections, `components.js` for your React components.
The `routes.js` is used to register one or more URL paths for your addon along with what layout, data, breadcrumbs and API
point is required for the view.
Check out [writing_addons.md](writing_addons.md) for more information on writing your own addons.
## CSS / SCSS
We use SCSS for generating our CSS. The bulk of the shared CSS used throughout the application is found in
[assets/scss/](assets/scss), but any addon may contain its own `assets/scss` subfolder containing whatever unique
styles are needed.
## Icons
Fauxton uses icon fonts, which are packaged as font files in the [assets/fonts](assets/fonts) folder.
As the name implies, these are fonts that contain icons instead of letters and numbers.
To use an icon, simply add the corresponding `fonticon-<icon_name>` CSS class to the HTML element. E.g. `<i className="fonticon-attention-circled"></i>`.
The CSS classes are defined in [assets/scss/icon.scss](assets/scss/icon.scss) - a generated file. In order to add, update or remove icons, follow the steps outlined at [assets/iconfontgenerator/README.md](assets/iconfontgenerator/README.md). The source SVG files for each icon are located at [assets/icons](assets/icons).
## app/addons/components / app/addons/fauxton
These two contain React components and functionality intended for sharing throughout the app. You'll find many
common elements in there, like trays, buttons, loading lines, clipboard functionality and more.