2019-12-09 10:28:15 -05:00
|
|
|
# Frontend Guide #
|
|
|
|
|
|
|
|
This guide intends to explain the essential details of the frontend
|
|
|
|
application.
|
2020-01-11 10:28:54 -05:00
|
|
|
|
2020-08-17 08:04:21 -05:00
|
|
|
|
2020-04-28 04:54:10 -05:00
|
|
|
## Visual debug mode and utilities
|
|
|
|
|
2020-05-22 06:48:21 -05:00
|
|
|
Debugging a problem in the viewport algorithms for grouping and
|
|
|
|
rotating is difficult. We have set a visual debug mode that displays
|
|
|
|
some annotations on screen, to help understanding what's happening.
|
2020-04-28 04:54:10 -05:00
|
|
|
|
2020-05-12 05:50:23 -05:00
|
|
|
To activate it, open the javascript console and type
|
2020-05-22 06:48:21 -05:00
|
|
|
|
2020-05-12 05:50:23 -05:00
|
|
|
```javascript
|
2020-08-18 12:40:49 -05:00
|
|
|
app.util.debug.toggle_debug("option")
|
2020-04-28 04:54:10 -05:00
|
|
|
```
|
2020-05-22 06:48:21 -05:00
|
|
|
|
|
|
|
Current options are `bounding-boxes`, `group`, `events` and
|
|
|
|
`rotation-handler`.
|
2020-04-28 04:54:10 -05:00
|
|
|
|
2020-05-12 05:50:23 -05:00
|
|
|
You can also activate or deactivate all visual aids with
|
2020-05-22 06:48:21 -05:00
|
|
|
|
2020-05-12 05:50:23 -05:00
|
|
|
```javascript
|
2020-08-18 12:40:49 -05:00
|
|
|
app.util.debug.debug_all()
|
|
|
|
app.util.debug.debug_none()
|
2020-04-28 04:54:10 -05:00
|
|
|
```
|
|
|
|
|
2020-09-23 02:28:31 -05:00
|
|
|
## Traces and step-by-step debugging
|
|
|
|
|
|
|
|
There are some useful functions to trace program execution:
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
(println "message" expression)
|
|
|
|
; Outputs data to the devtools console. Clojure variables are converted to string, as in (str) function.
|
|
|
|
```
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
(js/console.log "message" (clj->js expression))
|
|
|
|
; Clojure values are converted to equivalent js objects, and displayed as a foldable widget in console.
|
|
|
|
```
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
(:require [cljs.pprint :refer [pprint]])
|
|
|
|
(pprint expression)
|
|
|
|
; Outputs a clojure value as a string, nicely formatted and with data type information.
|
|
|
|
```
|
|
|
|
|
|
|
|
Also we can insert breakpoints in the code with this function:
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
(js-debugger)
|
|
|
|
```
|
|
|
|
|
|
|
|
You can also set a breakpoint from the sources tab in devtools. One way of locating a source file is to
|
|
|
|
output a trace with (js/console.log) and then clicking in the source link that shows in the console.
|
|
|
|
|
|
|
|
|
|
|
|
## Access to clojure from javascript console
|
|
|
|
|
|
|
|
The uxbox namespace of the main application is exported, so that is
|
|
|
|
accessible from javascript console in Chrome developer tools. Object
|
|
|
|
names and data types are converted to javascript style. For example
|
|
|
|
you can emit the event to reset zoom level by typing this at the
|
|
|
|
console (there is autocompletion for help):
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
app.main.store.emit_BANG_(app.main.data.workspace.reset_zoom)
|
|
|
|
```
|
|
|
|
|
2020-08-17 08:04:21 -05:00
|
|
|
|
2020-04-27 07:31:57 -05:00
|
|
|
## Debug state and objects
|
|
|
|
|
2020-05-22 06:48:21 -05:00
|
|
|
There are also some useful functions to visualize the global state or
|
|
|
|
any complex object. To use them from clojure:
|
2020-04-27 07:31:57 -05:00
|
|
|
|
2020-04-28 04:54:10 -05:00
|
|
|
```clojure
|
2020-08-18 12:40:49 -05:00
|
|
|
(ns app.util.debug)
|
2020-04-28 04:58:33 -05:00
|
|
|
(logjs <msg> <var>) ; to print the value of a variable
|
|
|
|
(tap <fn>) ; to include a function with side effect (e.g. logjs) in a transducer.
|
2020-04-27 07:31:57 -05:00
|
|
|
|
2020-08-18 12:40:49 -05:00
|
|
|
(ns app.main.store)
|
2020-04-27 07:31:57 -05:00
|
|
|
(dump-state) ; to print in console all the global state
|
|
|
|
(dump-objects) ; to print in console all objects in workspace
|
2020-04-28 04:54:10 -05:00
|
|
|
```
|
2020-01-11 10:28:54 -05:00
|
|
|
|
2020-05-12 05:50:23 -05:00
|
|
|
But last ones are most commonly used from javscript console:
|
|
|
|
|
2020-09-23 02:28:31 -05:00
|
|
|
```javascript
|
2020-08-18 12:40:49 -05:00
|
|
|
app.main.store.dump_state()
|
|
|
|
app.main.store.dump_objects()
|
2020-05-12 05:50:23 -05:00
|
|
|
```
|
|
|
|
|
2020-09-23 02:28:31 -05:00
|
|
|
And we have also exported `pprint` and `clj->js` functions for the console:
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
pp(js_expression) // equivalent to cljs.pprint.pprint(js_expression)
|
|
|
|
dbg(js_expression) // equivalent to cljs.core.clj__GT_js(js_expression)
|
|
|
|
```
|
|
|
|
|
2020-01-11 10:28:54 -05:00
|
|
|
|
2020-03-08 07:13:32 -05:00
|
|
|
## Icons & Assets
|
|
|
|
|
|
|
|
The icons used on the frontend application are loaded using svgsprite
|
|
|
|
(properly handled by the gulp watch task). All icons should be on SVG
|
|
|
|
format located in `resources/images/icons`. The gulp task will
|
|
|
|
generate the sprite and the embedd it into the `index.html`.
|
|
|
|
|
|
|
|
Then, you can reference the icon from the sprite using the
|
2020-08-18 12:40:49 -05:00
|
|
|
`app.builtins.icons/icon-xref` macro:
|
2020-03-08 07:13:32 -05:00
|
|
|
|
|
|
|
```clojure
|
|
|
|
(ns some.namespace
|
2020-08-18 12:40:49 -05:00
|
|
|
(:require-macros [app.main.ui.icons :refer [icon-xref]]))
|
2020-03-08 07:13:32 -05:00
|
|
|
|
|
|
|
(icon-xref :arrow)
|
|
|
|
```
|
|
|
|
|
|
|
|
For performance reasons, all used icons are statically defined in the
|
2020-08-18 12:40:49 -05:00
|
|
|
`src/app/main/ui/icons.cljs` file.
|
2020-03-08 07:13:32 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
2020-01-11 10:28:54 -05:00
|
|
|
## Translations (I18N) ##
|
|
|
|
|
|
|
|
### How it Works ###
|
|
|
|
|
|
|
|
All the translation strings of this application are stored in
|
|
|
|
`resources/locales.json` file. It has a self explanatory format that
|
|
|
|
looks like this:
|
|
|
|
|
|
|
|
```json
|
|
|
|
{
|
|
|
|
"auth.email-or-username" : {
|
2020-08-18 12:40:49 -05:00
|
|
|
"used-in" : [ "src/app/main/ui/auth/login.cljs:61" ],
|
2020-01-11 10:28:54 -05:00
|
|
|
"translations" : {
|
|
|
|
"en" : "Email or Username",
|
|
|
|
"fr" : "adresse email ou nom d'utilisateur"
|
|
|
|
}
|
|
|
|
},
|
|
|
|
"ds.num-projects" : {
|
|
|
|
"translations": {
|
|
|
|
"en": ["1 project", "%s projects"]
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
For development convenience, you can forget about the specific format
|
|
|
|
of that file, and just add a simple key-value entry pairs like this:
|
|
|
|
|
|
|
|
```
|
|
|
|
{
|
|
|
|
[...],
|
|
|
|
"foo1": "bar1",
|
|
|
|
"foo2": "bar2"
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
The file is automatically bundled into the `index.html` file on
|
|
|
|
compile time (in development and production). The bundled content is a
|
|
|
|
simplified version of this data structure for avoid load unnecesary
|
|
|
|
data.
|
|
|
|
|
|
|
|
The development environment has a watch process that detect changes on
|
|
|
|
that file and recompiles the `index.html`. **There are no hot reload
|
|
|
|
for translations strings**, you just need to refresh the browser tab
|
|
|
|
for refresh the translations in the running the application.
|
|
|
|
|
|
|
|
If you have used the short (key-value) format, the watch process will
|
|
|
|
automatically convert it to the apropriate format before generate the
|
|
|
|
`index.html`.
|
|
|
|
|
|
|
|
Finally, when you have finished to adding texts, execute the following
|
|
|
|
command for reformat the file, and track the usage locations (the
|
|
|
|
"used-in" list) before commiting the file into the repository:
|
|
|
|
|
|
|
|
```bash
|
2020-08-18 12:40:49 -05:00
|
|
|
clojure -Adev locales.clj collect src/app/main/ resources/locales.json
|
2020-01-11 10:28:54 -05:00
|
|
|
```
|
|
|
|
|
|
|
|
NOTE: Later, we will need to think and implement the way to export and
|
|
|
|
import to other formats (mainly for transifex and similar services
|
|
|
|
compatibility).
|
|
|
|
|
|
|
|
|
|
|
|
### How to use it ###
|
|
|
|
|
|
|
|
You have two aproaches for translate strings: one for general purpose
|
|
|
|
and other specific for React components (that leverages reactivity for
|
|
|
|
language changes).
|
|
|
|
|
2020-08-18 12:40:49 -05:00
|
|
|
The `app.util.i18n/tr` is the general purpose function. This is a
|
2020-01-11 10:28:54 -05:00
|
|
|
simple use case example:
|
|
|
|
|
|
|
|
```clojure
|
2020-08-18 12:40:49 -05:00
|
|
|
(require '[app.util.i18n :refer [tr])
|
2020-01-11 10:28:54 -05:00
|
|
|
|
2020-01-16 13:28:19 -05:00
|
|
|
(tr "auth.email-or-username")
|
2020-01-11 10:28:54 -05:00
|
|
|
;; => "Email or Username"
|
|
|
|
```
|
|
|
|
|
|
|
|
If you have defined plurals for some translation resource, then you
|
|
|
|
need to pass an additional parameter marked as counter in order to
|
|
|
|
allow the system know when to show the plural:
|
|
|
|
|
|
|
|
```clojure
|
2020-08-18 12:40:49 -05:00
|
|
|
(require '[app.util.i18n :as i18n :refer [tr]])
|
2020-01-11 10:28:54 -05:00
|
|
|
|
2020-01-16 13:28:19 -05:00
|
|
|
(tr "ds.num-projects" (i18n/c 10))
|
2020-01-11 10:28:54 -05:00
|
|
|
;; => "10 projects"
|
|
|
|
|
2020-01-16 13:28:19 -05:00
|
|
|
(tr "ds.num-projects" (i18n/c 1))
|
2020-01-11 10:28:54 -05:00
|
|
|
;; => "1 project"
|
|
|
|
```
|
|
|
|
|
2020-08-18 12:40:49 -05:00
|
|
|
For React components, you have `app.util.i18n/use-locale` hook
|
|
|
|
and the `app.util.i18n/t` function:
|
2020-01-11 10:28:54 -05:00
|
|
|
|
|
|
|
```clojure
|
2020-08-18 12:40:49 -05:00
|
|
|
(require '[app.util.i18n :as i18n :refer [t]])
|
2020-01-16 13:28:19 -05:00
|
|
|
|
2020-01-11 10:28:54 -05:00
|
|
|
(mf/defc my-component
|
|
|
|
[props]
|
2020-01-16 13:28:19 -05:00
|
|
|
(let [locale (i18n/use-locale)]
|
2020-01-11 10:28:54 -05:00
|
|
|
[:div
|
2020-01-16 13:28:19 -05:00
|
|
|
[:span (t locale "auth.email-or-username")]]))
|
2020-01-11 10:28:54 -05:00
|
|
|
```
|
|
|
|
|
|
|
|
You can use the general purpose function in React component but when
|
|
|
|
language is changed the component will not be rerendered
|
|
|
|
automatically.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|