Initial commit
This commit is contained in:
@@ -0,0 +1,287 @@
|
||||
# CARTO Frontend documentation
|
||||
|
||||
1. [Running the project](#running-the-project)
|
||||
2. [Tasks](#tasks)
|
||||
3. [Pull Request rules](#pull-request-rules)
|
||||
4. [JS Styleguide](#js-styleguide)
|
||||
4. [CSS Styleguide](#css-styleguide)
|
||||
4. [Testing](#testing)
|
||||
4. [Static pages](#static-pages)
|
||||
|
||||
## Running the project
|
||||
|
||||
We use [Webpack](https://webpack.js.org/) to automate build tasks related to both CSS and JS and [NodeJS](http://nodejs.org/) v6.9.2 (we recommend to use [NVM](https://github.com/creationix/nvm)).
|
||||
|
||||
Install dependencies using a normal npm install as such:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
Then you can run the project with:
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
That enables CSS and JS watchers for rebuilding bundles automatically upon changes.
|
||||
|
||||
**Note!** Make sure `config/app_config.yml` doesn't contain the `app_assets` configuration, i.e.:
|
||||
|
||||
```ruby
|
||||
# Make sure the following lines are removed, or commented like this:
|
||||
# app_assets:
|
||||
# asset_host: '//cartodb-libs.global.ssl.fastly.net/cartodbui'
|
||||
```
|
||||
|
||||
_Don't forget to restart Rails after you have modified `config/app_config.yml`._
|
||||
|
||||
|
||||
## Tasks
|
||||
|
||||
This is a list of available tasks to run:
|
||||
|
||||
| Task | Description
|
||||
| --------- | ---
|
||||
| `npm start` | Compiles `carto-node`, the static pages and watches Builder and Dashboard
|
||||
| `npm run dev` | Runs webpack for Builder and Dashboard
|
||||
| `npm run dev:static` | Runs webpack for static pages
|
||||
| `npm run dev:editor` | Runs Editor for development
|
||||
| `npm run build` | Create production builds for Builder and Dashboard
|
||||
| `npm run build:static` | Create production builds for static pages
|
||||
| `npm run carto-node` | Create production builds for `carto-node`
|
||||
| `npm run test` | Run all test suites
|
||||
| `npm run test:builder` | Run and watches builder test suites
|
||||
| `npm run test:dashboard` | Run and watches dashboard test suites
|
||||
| `npm run test:editor` | Run and watches editor test suites
|
||||
| `npm run lint` | Runs the Javascript linter
|
||||
| `npm run lint:fix` | Runs the Javascript linter with the `--fix` flag
|
||||
| `npm run lint:css` | Runs the CSS linter
|
||||
| `npm run bump` | Creates a patch version
|
||||
| `npm run bump:major` | Creates a major version
|
||||
| `npm run bump:minor` | Creates a minor version
|
||||
| `npm run update-internal-deps` | Update the `package-lock` file
|
||||
| `npm run ci` | Runs the CSS lint and tests
|
||||
|
||||
## Pull Request rules
|
||||
|
||||
There are several rules you should follow when creating a new pull request:
|
||||
|
||||
- Title has to be descriptive. If you are fixing a bug don't use the ticket title or number.
|
||||
- Explain what you have achieved in the description. If you change something related with the UI of the application add an image or an animation ([LiceCap](https://www.cockos.com/licecap/) is awesome) about the feature you have just implemented. Or show the change against what it is already done.
|
||||
- Add acceptance instructions, they're really useful for the person who tests it.
|
||||
- Update `NEWS.md` file with a description about the task, and the issue number.
|
||||
- CSS and JS linters must pass.
|
||||
- Every new feature (as well as bug fixes) must come with a test case.
|
||||
- All tests must pass (see Testing).
|
||||
- You can see an example of a pull request [here](https://github.com/CartoDB/cartodb/pull/12186).
|
||||
|
||||
## JS Styleguide
|
||||
|
||||
CARTO is built on top of [CARTO.js](https://github.com/CartoDB/carto.js), which in turns depends on some common libraries, in particular worth mentioning:
|
||||
|
||||
- [BackboneJS 1.2.3](https://cdn.rawgit.com/jashkenas/backbone/1.2.3/index.html).
|
||||
- [jQuery 2.1.4](https://api.jquery.com/category/version/1.12-2.2/)
|
||||
- [Underscore.js 1.8.3](https://cdn.rawgit.com/jashkenas/underscore/1.8.3/index.html)
|
||||
|
||||
Source code is located at `lib/assets/javascripts`, dependencies at `vendor/assets/javascripts`.
|
||||
|
||||
We use [semistandard](https://github.com/Flet/semistandard) style guide for syntax consistency, it's checked as part of test run.
|
||||
|
||||
It's recommended to use it in your IDE, you can either use a [Semistandard](https://github.com/Flet/semistandard#editor-plugins) plugin or a [ESLint](https://eslint.org/docs/user-guide/integrations#editors) plugin.
|
||||
|
||||
### General rules
|
||||
|
||||
We use dangling underscores to mark a method as "private", so we know it's only used there. For example `_showTooltip`.
|
||||
|
||||
### Backbone events
|
||||
|
||||
To keep the code organised we initialise all events in the `_initBinds` function, which is usually called in the `constructor`.
|
||||
|
||||
When using `on` or `bind` methods, we have to use `add_related_model` so when the view is removed, the binding is removed too. We won't need to do it if we're using `listenTo` or the model is `this.model`.
|
||||
|
||||
```js
|
||||
// Example with listenTo
|
||||
_initBinds: function () {
|
||||
this.listenTo(this.model, 'change:show', this._onShowChange);
|
||||
this.listenTo(this.model, 'destroy', this._onDestroy);
|
||||
},
|
||||
|
||||
// Example with on and add_related_model
|
||||
_initBinds: function () {
|
||||
this._stateModel.on('change:status', this.render, this);
|
||||
this.add_related_model(this._stateModel);
|
||||
},
|
||||
```
|
||||
|
||||
If you want to create a custom event, remember to create it in `camelCase` and using the action in past simple, example:
|
||||
|
||||
```js
|
||||
this.model.trigger('sendMessage', 'Hello there!');
|
||||
this.listenTo(this.model, 'sendMessage', message => console.log(message));
|
||||
```
|
||||
|
||||
### Backbone views
|
||||
The render method should be the first in the view after the initialize.
|
||||
|
||||
The test should always have the `toHaveNoLeaks` test.
|
||||
|
||||
You can add a label to help you relate where the view belongs in the code. Use the attribute `module` in any view and you'll see a data attribute in the HTML element when in development node. [more info](https://github.com/CartoDB/cartodb/pull/12341)
|
||||
|
||||
If we have to initialise multiple views inside another view, we use the `_initViews` function as same as we do with events, to keep the code organised.
|
||||
|
||||
```js
|
||||
_initViews: function () {
|
||||
// Create view
|
||||
this._firstView = new FirstView({
|
||||
model: this.model,
|
||||
});
|
||||
// Render it
|
||||
this.$('.js-first').append(this._firstView.render().el);
|
||||
// Add as subview to the current view
|
||||
this.addView(this._firstView);
|
||||
|
||||
// ... more views here
|
||||
},
|
||||
```
|
||||
|
||||
## CSS Styleguide
|
||||
|
||||
We use [SASS](http://sass-lang.com/), with [.scss](http://www.thesassway.com/editorial/sass-vs-scss-which-syntax-is-better) format, which are located at ```assets/stylesheets```. [Webpack](https://webpack.js.org/) is used to compile the files into ```.css``` files.
|
||||
|
||||
Also CARTO makes use of a linter machine for checking possible errors in those stylesheets. Rules are specified in the [scss-style.yml](.stylelintrc) file.
|
||||
|
||||
We use Stylelint with the [standard config](https://github.com/stylelint/stylelint-config-standard) and the [property sort ordering](https://github.com/cahamilton/stylelint-config-property-sort-order-smacss) based on the SMACSS methodology.
|
||||
|
||||
### General rules
|
||||
- All new elements added in this CartoAssets repository should have included a CDB- namespace.
|
||||
- Don't create default styles for common elements (e.g. `input { padding: 10px 0 }`). It will make more difficult edit styles for the future custom elements and the !important use will grow.
|
||||
- Avoid creating new classes with only one attribute (e.g. `.marginRight { margin-right: 10px }`). It is impossible to manage the amount of cases we would like to cover.
|
||||
|
||||
### Components
|
||||
|
||||
The component's name must be written in camel case:
|
||||
|
||||
```css
|
||||
.MyComponent {}
|
||||
```
|
||||
|
||||
### Component modifiers
|
||||
|
||||
A component modifier is a class that modifies the presentation of the base component in some form.
|
||||
|
||||
- Modifier names must be written in “camelCase” and be separated from the component name by two hyphens.
|
||||
- The class should be included in the HTML in addition to the base component class.
|
||||
|
||||
```css
|
||||
.Button {}
|
||||
.Button--small {}
|
||||
```
|
||||
|
||||
### Component descendants
|
||||
A component descendent is a class that is attached to a descendent node of a component. It's responsible for applying presentation directly to the descendent on behalf of a particular component. Descendent names must be written in camel case.
|
||||
|
||||
```css
|
||||
.Card {}
|
||||
.Card-header {}
|
||||
.Card-footer {}
|
||||
.Card-fullWidth {}
|
||||
```
|
||||
|
||||
### Component states
|
||||
|
||||
Use `is-stateName` to reflect changes to a component's state, the state name must be camel case.
|
||||
|
||||
Never style these classes directly, they should always be used as an adjoining class, this means that the same state names can be used in multiple contexts, but every component must define its own styles for the state (as they are scoped to the component).
|
||||
|
||||
```css
|
||||
.Dropdown {}
|
||||
.Dropdown.is-open {}
|
||||
.Dropdown.is-disabled {}
|
||||
```
|
||||
|
||||
### Component javascript classes
|
||||
|
||||
JavaScript-specific classes reduce the risk that changing the structure or theme of components will inadvertently affect any required JavaScript behaviour and complex functionality. It is not necessary to use them in every case, just think of them as a tool in your utility belt. If you are creating a class, which you dont intend to use for styling, but instead only as a selector in JavaScript, you should probably be adding the `js-` prefix. In practice this looks like this:
|
||||
|
||||
```html
|
||||
<button class="Button Button--primary js-delete">Delete</button>
|
||||
```
|
||||
|
||||
JavaScript-specific classes should not, under any circumstances, be styled.
|
||||
|
||||
## Testing
|
||||
We use [Jasmine 2.5.2](https://jasmine.github.io/) as test framework.
|
||||
|
||||
You can find the spec files in:
|
||||
|
||||
```
|
||||
lib/assets/test/spec/(dashboard|builder|carto-node|deep-insights)
|
||||
```
|
||||
|
||||
To start specs development type the next command:
|
||||
|
||||
```bash
|
||||
# Builder specs
|
||||
npm run test:builder
|
||||
|
||||
# Dashboard specs
|
||||
npm run test:dashboard
|
||||
```
|
||||
|
||||
You can optionally provide an argument to grunt to filter what specs will be generated, like this:
|
||||
|
||||
```bash
|
||||
npm run test:builder -- --match=dropdown
|
||||
```
|
||||
|
||||
After building the whole suite for the first time, a web server will be started on port 8088 and the spec runner webpage will show up. If you need to use a different port, change the port & URL values on the [connect task](lib/build/tasks/connect.js)
|
||||
|
||||
The process will watch changes in the codebase and will regenerate the specs as needed. Just refresh the Jasmine page to pass the tests again.
|
||||
|
||||
If you only want to run a subset of tests the easiest and fastest way is to use [focused specs](jasmine.github.io/2.1/focused_specs.html), but you can also append `?spec=str-matching-a-describe` to test URL, or use [--filter flag](https://github.com/gruntjs/grunt-contrib-jasmine#filtering-specs) if running tests in a terminal.
|
||||
|
||||
## Static pages
|
||||
|
||||
There are some views that can be served from a static file in `public/static/` directory and must be built beforehand. For that purpose run the following command:
|
||||
|
||||
```bash
|
||||
npm run build:static
|
||||
```
|
||||
|
||||
# Carto v3
|
||||
|
||||
- [Backbone with organizations](editor/js/backbone-with-organizations.md)
|
||||
- [Global objects](editor/js/global-objects.md)
|
||||
- [Conventions](editor/js/conventions.md)
|
||||
- [URLs](editor/urls.md)
|
||||
|
||||
## Update CartoDB.js v3
|
||||
|
||||
Follow these steps to update to get latest changes:
|
||||
|
||||
- go to `lib/assets/javascripts/cdb/`
|
||||
- `git checkout v3 && git pull`
|
||||
- go back to root and run `grunt cdb`
|
||||
- commit both the new revision of the submodule and the generated file `vendor/assets/javascripts/cartodb.uncompressed.js`
|
||||
|
||||
## Old Editor specs
|
||||
|
||||
In order to develop tests for the codebase outside Builder (that is, old Editor and dashboard pages) we advise to run:
|
||||
|
||||
```bash
|
||||
npm run test:editor
|
||||
```
|
||||
|
||||
After the building process finish, a webpage will show up with a link to the Jasmine page with all the specs. The URL of this page is `http://localhost:8089/_SpecRunner.html`
|
||||
|
||||
Then, the process will watch changes in the codebase and will regenerate the specs as needed. Just refresh the Jasmine page to pass the tests again.
|
||||
|
||||
**Run specs and regular codebase simultaneously**
|
||||
|
||||
If you want to run simultaneously the application and the specs generation follow these steps:
|
||||
|
||||
1. Open a terminal with Node v6.9.2 (use nvm) and run `grunt editor`. This will build the application assets and will watch for changes.
|
||||
|
||||
2. Open a second terminal and run `grunt affected_editor_specs`.
|
||||
|
||||
3. That's it. When you change any Builder Javascript file `grunt editor` will build the application bundle and `grunt affected_editor_specs` will build the specs.
|
||||
@@ -0,0 +1,52 @@
|
||||
This document contains some notes on how to work with backbone models related to organization
|
||||
|
||||
## Models related to organization
|
||||
|
||||
- [cdb.admin.User](https://github.com/CartoDB/cartodb/blob/CDB-2891/lib/assets/javascripts/cartodb/models/user.js): it already existed, but it takes more importance
|
||||
- [cdb.admin.Organization](https://github.com/CartoDB/cartodb/blob/CDB-2891/lib/assets/javascripts/cartodb/models/organization.js): this represents an organization
|
||||
- [cdb.admin.Permission](https://github.com/CartoDB/cartodb/blob/CDB-2891/lib/assets/javascripts/cartodb/models/permissions.js): permission object, contains the information to know about the ownership and
|
||||
permission list (called ``acl``) of an object. See https://github.com/Vizzuality/cartodb-management/wiki/multiuser-REST-API#permissions-object
|
||||
|
||||
### Changes
|
||||
|
||||
- ``User`` model has an organization attribute. Each user is **always** inside an organization, so
|
||||
this will be always filled. When the organization contains only a user, the application behavior is the
|
||||
same than we currently have (CartoDB 2.0)
|
||||
|
||||
- ``Visualization`` object contains a ``permission`` attribute (instance of ``cdb.admin.Permission``)
|
||||
|
||||
|
||||
### How to use them
|
||||
|
||||
- add read permissions to a table
|
||||
|
||||
```
|
||||
canonical_visualization.permission.setPermission(user_model, 'r').save();
|
||||
```
|
||||
|
||||
- add read/write permissions to a table
|
||||
```
|
||||
canonical_visualization.permission.setPermission(user_model, 'rw').save();
|
||||
```
|
||||
|
||||
- how to know if the organization for the current user is single or multiuser
|
||||
```
|
||||
user.isInsideOrg()
|
||||
user.isAdminOrg()
|
||||
```
|
||||
|
||||
- know what users have access to a visualization
|
||||
|
||||
```
|
||||
vis.permission.acl.each(function(aclItem) {
|
||||
console.log("user " + aclItem.get('user').get('username') + " permission: " + aclItem.get('type'))
|
||||
})
|
||||
```
|
||||
|
||||
- know the owner of a visualization
|
||||
```
|
||||
// owner is a cdb.admin.User instance
|
||||
vis.permission.owner.get('username')
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
This article describes conventions we defined for the JS code.
|
||||
|
||||
## Backbone
|
||||
|
||||
### Views
|
||||
|
||||
#### Event names
|
||||
Use `done` and `fail` for event names, to be consistent with naming convention used in [jqXHR](http://api.jquery.com/jQuery.ajax/#jqXHR) objects (typically returned from a Backbone model/collection on an asynchronious operation. Typically used for dialogs, where the final operation and its outcome should have some implication in the UI (e.g. refresh list, hide/show some view etc.)
|
||||
|
||||
Example:
|
||||
```js
|
||||
aDialogView
|
||||
.bind('done', function() {
|
||||
console.log('dialog is done :)');
|
||||
this.collection.fetch();
|
||||
.bind('fail', function(err) {
|
||||
console.log('something failed :/');
|
||||
// Do nothing for now
|
||||
};
|
||||
```
|
||||
@@ -0,0 +1,12 @@
|
||||
As a general rule setting variables and objects in global namespace is highly discouraged. Instead, the code related to the CartoDB should be placed in the `cdb.admin` namespace.
|
||||
|
||||
There are some use-cases where having a global objects makes things simpler and easier to maintain, see below.
|
||||
|
||||
### cdb.god
|
||||
The `cdb.god` is a Backbone model which is intended to be used a global event bus to make it easier to bind and trigger to events that affects the global state in some way.
|
||||
|
||||
As a general rule accessing global objects is highly discouraged, but there are some use-cases where having a global mechanism makes things simpler and easier to maintain, e.g.:
|
||||
- Global UI state changes
|
||||
- Some UI action should have a side-effect in another view, but they either don't know about each other and/or are logically located far away from each other.
|
||||
|
||||
[Search for `cdb.god.`](https://github.com/CartoDB/cartodb/search?utf8=%E2%9C%93&q=cdb.god.)) in the source code you can see where it's currently applied.
|
||||
@@ -0,0 +1,15 @@
|
||||
URLs within the application might be necessary.
|
||||
|
||||
To avoid constructing these URLS manually, i.e. concatenating strings and thus duplicating logic, there are convenient ways of constructing them. Depending on context (server- or client-side) you might take one approach or another.
|
||||
|
||||
## Rails
|
||||
In Rails simply use the [standard routing helper methods](http://guides.rubyonrails.org/v3.2.21/routing.html). Have a look at [routes.rb](https://github.com/CartoDB/cartodb/blob/master/config/routes.rb) for the semantic names and paths available.
|
||||
|
||||
## Client-side
|
||||
For a current sub-app you can access URLs through the current router model, e.g. `router.currentUrl()`.
|
||||
|
||||
For a URL that is associated with a specific model you can access the URL by call `.viewUrl()` on that model, and chaining methods afterwards to "drill down" on what (available) path you want, e.g.
|
||||
- `user.viewUrl().dashboard().datasets())`, the URL to a user's datasets on the dashboard.
|
||||
- `vis.viewUrl().public()`, the URL to a visualization's public page.
|
||||
|
||||
See the [models](https://github.com/CartoDB/cartodb/blob/master/lib/assets/test/spec/cartodb/common/urls) for available models and methods.
|
||||
@@ -0,0 +1,152 @@
|
||||
# New Dashboard documentation
|
||||
|
||||
## Getting Started
|
||||
New Dashboard was born as a way to redesign the current dashboard, adapting it to the new times and improving some of the UX patterns there.
|
||||
|
||||
We chose Vue for our New Dashboard project because we are using Vue for the new CARTO frontend's projects. That way we can benefit from all the patterns and behaviours implemented in one project or another.
|
||||
|
||||
## How to run it
|
||||
Following [`Running the project` steps in CARTO Frontend's documentation](https://github.com/CartoDB/cartodb/tree/master/doc/frontend#running-the-project) is the way to run New Dashboard.
|
||||
|
||||
Once Ruby on Rails is listening on the desired port and Webpack has finished compiling assets, everything should be ready to launch and access the dashboard in localhost:3000.
|
||||
|
||||
However, as long as New Dashboard is under a Feature Flag, there are some additional steps to perform before being able to see New Dashboard as the main UI.
|
||||
|
||||
### Adding and Enabling `new-dashboard-feature` feature flag
|
||||
There are two steps to be performed to enable the feature flag to a given user:
|
||||
|
||||
- Adding the feature flag
|
||||
```bash
|
||||
$ bundle exec rake cartodb:features:add_feature_flag["new-dashboard-feature"]
|
||||
```
|
||||
|
||||
- Enabling it to a specific user
|
||||
```bash
|
||||
$ bundle exec rake cartodb:features:enable_feature_for_user["new-dashboard-feature","your_username"]
|
||||
```
|
||||
|
||||
|
||||
## Command Explanation
|
||||
We can find some commands in [`package.json`](https://github.com/CartoDB/cartodb/blob/master/package.json) to launch tasks related to new dashboard.
|
||||
|
||||
- `npm run start`
|
||||
This command will compile all assets needed to launch cartodb with Webpack.
|
||||
|
||||
- `npm run test:new_dashboard`
|
||||
This command will run all new dashboard tests with Jest. You can add any Jest's CLI option to the command by appending `--` and the desired option, i.e. `-- --watch`. Please see all CLI options [here](https://jestjs.io/docs/en/cli#options)
|
||||
|
||||
|
||||
## Folder Structure
|
||||
Root folder of new dashboard is `lib/assets/javascripts/new-dashboard`. You will find several folders within that one that define different aspects of our application.
|
||||
|
||||
- **assets**\
|
||||
This folder contains icons or images referenced within the application.
|
||||
|
||||
- **components**\
|
||||
Standalone components that can be composed or used within other components or pages.
|
||||
|
||||
- **core**\
|
||||
Set of common domain login separated from components. An example of this functions would be visualization functions to generate the proper visualizations' URL link.
|
||||
|
||||
- **directives**\
|
||||
Common application directives for DOM behaviour like closing dropdowns when clicking outside.
|
||||
|
||||
- **i18n**\
|
||||
Internacionalization configuration for `vue-i18n` and translation strings.
|
||||
|
||||
- **pages**\
|
||||
Page components used in Vue router to be rendered.
|
||||
|
||||
- **plugins**\
|
||||
Custom Vue plugins. There is only one right now to inject `$cartoModels` in every component to be able to use initialized UserModel and ConfigModel wherever we need them.
|
||||
|
||||
- **router**\
|
||||
Router configuration for pages within the Dashboard. It includes navigation hooks for loading data beforehand.
|
||||
|
||||
- **store**\
|
||||
State management configuration and store for the application which holds all the visualizations, user data, application configuration, etc...
|
||||
|
||||
- **styles**\
|
||||
Global styles for the application. Here we put common or styles that don't belong to any specific components, such as grid styles, button styles, and so on and so forth.
|
||||
|
||||
- **utils**\
|
||||
Set of functions to be used application-wide that perform a specific action like counting characters in an array or things like that.
|
||||
|
||||
## Bundles
|
||||
There are several bundles within the application that serve different purposes.
|
||||
|
||||
- **Main Bundle**
|
||||
This bundle contains the whole application that is served in Ruby on Rails when accessing Dashboard. This bundle uses i18n, router, store, and plugins.
|
||||
|
||||
The two bundles below are reduced bundles that are included within private pages to be able to show [Header](https://github.com/CartoDB/cartodb/issues/14312) and [Footer](https://github.com/CartoDB/cartodb/issues/14342) without copying or adapting the code to Ruby on Rails' templates.
|
||||
|
||||
- **Header Bundle**.
|
||||
This bundle renders `<NavigationBar />` with the component receiving props from window variables like `user_data` or `organization_notifications`.
|
||||
|
||||
[Header Bundle folder](https://github.com/CartoDB/cartodb/tree/master/lib/assets/javascripts/new-dashboard/bundles/header)
|
||||
|
||||
- **Why we can't use $store within `<NavigationBar />`**\
|
||||
We have a strong limitation with Vuex in this bundle because we don't want to include it to make the bundle as smaller as possible. So, we rely on component parameters to inject all the needed properties.
|
||||
|
||||
- **Footer Bundle**
|
||||
This bundle renders `<Footer />` receiving `user` prop from `window.user_data`.
|
||||
|
||||
[Footer Bundle folder](https://github.com/CartoDB/cartodb/tree/master/lib/assets/javascripts/new-dashboard/bundles/footer)
|
||||
|
||||
- **Why we can't use $store within `<Footer />`**\
|
||||
We have a strong limitation with Vuex in this bundle because we don't want to include it to make the bundle as smaller as possible. So, we rely on component parameters to inject all the needed properties.
|
||||
|
||||
## Store
|
||||
The store holds all the data which is needed at the current page to be rendered properly, in addition to configuration data and user data.
|
||||
|
||||
There are several submodules attached to the main store that allow us to split and separate data domains. These submodules are: config, datasets, maps, notifications, recent content, search, and user.
|
||||
|
||||
The way we handle actions and mutations is pretty straightforward.
|
||||
|
||||
We do not manipulate data coming from API outside of the store, and whenever we need to retrieve visualizations or any other kind of data needed to render a page we do it through the store.
|
||||
|
||||
The flow would be like this:
|
||||
Let's say that we need visualizations to be rendered within a random component.
|
||||
|
||||
The thing we would do is to dispatch an action in the component to make a request to the API from within the store.
|
||||
```js
|
||||
mounted () {
|
||||
this.$store.dispatch('maps/fetch');
|
||||
}
|
||||
```
|
||||
|
||||
The dispatched action will request the visualizations to the API, and then will commit a mutation to set the response data to the state itself.
|
||||
|
||||
To use the data in page's component, we will create a computed variable with the state property that will be reevaluated whenever visualizations are available.
|
||||
|
||||
```js
|
||||
computed: {
|
||||
maps () {
|
||||
return this.$store.state.maps.list;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Components
|
||||
Components are one of the most important things within Vue applications. They are what allow us to build the application itself by using and composing them on one another.
|
||||
|
||||
We split components into two types: page components and regular components.
|
||||
|
||||
Page components are the ones that vue-router render when matching a predefined route. The regular ones are those which are within pages and build what we consider the whole page.
|
||||
|
||||
Currently, we are using `.vue` files which have a template, the style definition and the component declaration in the same file.
|
||||
|
||||
The template is a plain HTML string in which you can use the handy Vue modifiers like v-for, v-if, etc...
|
||||
|
||||
For our components' style definition, we use SCSS and it is scoped, that means that there wouldn't be any collisions amongst CSS classes with the same name.
|
||||
|
||||
## Backbone Connection
|
||||
There is a special thing in the new dashboard related to modals. As we didn't want to rewrite or redesign the existing Dashboard/Builder modals, we thought of using the same ones that we had. Those ones were written using Backbone.
|
||||
|
||||
So, we thought, why don't we render those modals within Vue components and use them as if they were Vue components? And that's what we did.
|
||||
|
||||
[Here](https://github.com/CartoDB/cartodb/tree/master/lib/assets/javascripts/new-dashboard/components/Backbone/Dialogs) you can find all the components mirroring Builder modals.
|
||||
|
||||
The key here is that we get the reference to a HTML node within the template and we inject it to `el` property in the Backbone component. The `el` property makes Backbone render the dialog within the element in the property.
|
||||
|
||||
To keep data synchronized between Backbone and our Vuex store, we listen to `change` event in the desired model and whenever that model updates, we react in consequence updating our application state.
|
||||
Reference in New Issue
Block a user