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-10-22 03:45:45 -05:00
|
|
|
## Logging, Tracing & Debugging
|
2020-09-23 02:28:31 -05:00
|
|
|
|
2020-10-22 03:45:45 -05:00
|
|
|
As a traditional way for debugging and tracing you have the followimg approach:
|
2020-09-23 02:28:31 -05:00
|
|
|
|
2020-10-22 03:45:45 -05:00
|
|
|
|
|
|
|
Print data to the devtool console using clojurescript helper:
|
|
|
|
**prn**. This helper automatically formats the clojure and js data
|
|
|
|
structures as plain EDN for easy visual inspection of the data and the
|
|
|
|
type of the data.
|
2020-09-23 02:28:31 -05:00
|
|
|
|
|
|
|
```clojure
|
2020-10-22 03:45:45 -05:00
|
|
|
(prn "message" expression)
|
2020-09-23 02:28:31 -05:00
|
|
|
```
|
|
|
|
|
2020-10-22 03:45:45 -05:00
|
|
|
An alternative is using the pprint function, usefull for pretty
|
|
|
|
printing a medium-big data sturcture for completly understand it.
|
|
|
|
|
2020-09-23 02:28:31 -05:00
|
|
|
```clojure
|
|
|
|
(:require [cljs.pprint :refer [pprint]])
|
|
|
|
(pprint expression)
|
|
|
|
; Outputs a clojure value as a string, nicely formatted and with data type information.
|
|
|
|
```
|
|
|
|
|
2020-10-22 03:45:45 -05:00
|
|
|
Use the js native functions for printing data. The clj->js converts
|
|
|
|
the clojure data sturcture to js data sturcture and it is
|
|
|
|
inspeccionable in the devtools console.
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
(js/console.log "message" (clj->js expression))
|
|
|
|
```
|
|
|
|
|
|
|
|
|
2020-09-23 02:28:31 -05:00
|
|
|
Also we can insert breakpoints in the code with this function:
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
(js-debugger)
|
|
|
|
```
|
|
|
|
|
2020-10-22 03:45:45 -05:00
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
### Logging framework
|
|
|
|
|
|
|
|
Additionally to the traditional way of putting traces in the code, we
|
|
|
|
have a logging framework with steroids. It is usefull for casual
|
|
|
|
debugging (as replacement for a `prn` and `js/console.log`) and as a
|
|
|
|
permanent traces in the code.
|
|
|
|
|
|
|
|
You have the ability to specify the logging level per namespace and
|
|
|
|
all logging is ellided in production build.
|
|
|
|
|
|
|
|
Lets start with a simple example:
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
(ns some.ns
|
|
|
|
(:require [app.util.logging :as log]))
|
|
|
|
|
|
|
|
;; This function sets the level to the current namespace; messages
|
|
|
|
;; with level behind this will not be printed.
|
|
|
|
(log/set-level! :info)
|
|
|
|
|
|
|
|
|
|
|
|
;; Log some data; The `app.util.logging` has the following
|
|
|
|
;; functions/macros:
|
|
|
|
|
|
|
|
(log/error :msg "error message")
|
|
|
|
(log/warn :msg "warn message")
|
|
|
|
(log/info :msg "info message")
|
|
|
|
(log/debug :msg "debug message")
|
|
|
|
(log/trace :msg "trace message")
|
|
|
|
```
|
|
|
|
|
|
|
|
Each macro accept arbitrary number of key values pairs:
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
(log/info :foo "bar" :msg "test" :value 1 :items #{1 2 3})
|
|
|
|
```
|
|
|
|
|
|
|
|
Some keys ara treated as special cases for helping in debugging:
|
|
|
|
|
|
|
|
```clojure
|
|
|
|
;; The special case for :js/whatever; if you namespace the key
|
|
|
|
;; with `js/`, the variable will be printed as javascript
|
|
|
|
;; inspectionable object.
|
|
|
|
|
|
|
|
(let [foobar {:a 1 :b 2}]
|
|
|
|
(log/info :msg "Some data" :js/data foobar))
|
|
|
|
|
|
|
|
;; The special case for `:err`; If you attach this key, the
|
|
|
|
;; exception stack trace is printed as additional log entry.
|
|
|
|
```
|
2020-09-23 02:28:31 -05:00
|
|
|
|
|
|
|
|
|
|
|
## Access to clojure from javascript console
|
|
|
|
|
2020-10-28 03:34:47 -05:00
|
|
|
The penpot namespace of the main application is exported, so that is
|
2020-09-23 02:28:31 -05:00
|
|
|
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"
|
|
|
|
```
|
|
|
|
|
|
|
|
|