mirror of
https://github.com/penpot/penpot.git
synced 2025-05-10 15:06:38 +02:00
✨ Point documentation to the help center.
This commit is contained in:
parent
5ae823b25c
commit
868f18fd21
10 changed files with 3 additions and 1102 deletions
|
@ -1,62 +0,0 @@
|
|||
# Getting Started ##
|
||||
|
||||
This documentation intends to explain how to get penpot application and run it locally.
|
||||
|
||||
The simplest approach is using docker and docker-compose.
|
||||
|
||||
|
||||
## Install Docker ##
|
||||
|
||||
Skip this section if you already have docker installed, up and running.
|
||||
|
||||
You can install docker and its dependencies from your distribution
|
||||
repository with:
|
||||
|
||||
```bash
|
||||
sudo apt-get install docker docker-compose
|
||||
```
|
||||
|
||||
Or follow installation instructions from docker.com; (for Debian
|
||||
https://docs.docker.com/engine/install/debian/).
|
||||
|
||||
Ensure that the docker is started and optionally enable it to start
|
||||
with the system:
|
||||
|
||||
```bash
|
||||
sudo systemctl start docker
|
||||
sudo systemctl enable docker
|
||||
```
|
||||
|
||||
And finally, add your user to the docker group:
|
||||
|
||||
```basb
|
||||
sudo usermod -aG docker $USER
|
||||
```
|
||||
|
||||
This will make use of the docker without `sudo` command all the time.
|
||||
|
||||
NOTE: probably you will need to re-login again to make this change
|
||||
take effect.
|
||||
|
||||
|
||||
## Start penpot application ##
|
||||
|
||||
You can create it from scratch or take a base from the [penpot
|
||||
repository][1]
|
||||
|
||||
[1]: https://raw.githubusercontent.com/penpot/penpot/develop/docker/images/docker-compose.yaml
|
||||
|
||||
```bash
|
||||
wget https://raw.githubusercontent.com/penpot/penpot/develop/docker/images/docker-compose.yaml
|
||||
```
|
||||
|
||||
And then:
|
||||
|
||||
```bash
|
||||
docker-compose -p penpot -f docker-compose.yaml up
|
||||
```
|
||||
|
||||
The docker compose file contains the essential configuration for
|
||||
getting the application running, and many essential configurations
|
||||
already explained in the comments. All other configuration options are
|
||||
explained in [configuration guide](./05-Configuration-Guide.md).
|
|
@ -1,146 +0,0 @@
|
|||
# Developer Guide #
|
||||
|
||||
This is a generic "getting started" guide for the Penpot platform. It
|
||||
intends to explain how to get the development environment up and
|
||||
running with many additional tips.
|
||||
|
||||
The main development environment consists in a docker compose
|
||||
configuration that starts the external services and the development
|
||||
container (called **devenv**).
|
||||
|
||||
We use tmux script in order to multiplex the single terminal and run
|
||||
both the backend and frontend in the same container.
|
||||
|
||||
|
||||
## System requirements ##
|
||||
|
||||
You should have `docker` and `docker-compose` installed in your system
|
||||
in order to set up properly the development enviroment.
|
||||
|
||||
In debian like linux distributions you can install it executing:
|
||||
|
||||
```bash
|
||||
sudo apt-get install docker docker-compose
|
||||
```
|
||||
|
||||
Start and enable docker environment:
|
||||
|
||||
|
||||
```bash
|
||||
sudo systemctl start docker
|
||||
sudo systemctl enable docker
|
||||
```
|
||||
|
||||
Add your user to the docker group:
|
||||
|
||||
```basb
|
||||
sudo usermod -aG docker $USER
|
||||
```
|
||||
|
||||
And finally, increment user watches:
|
||||
|
||||
```
|
||||
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
|
||||
```
|
||||
|
||||
NOTE: you probably need to login again for group change take the effect.
|
||||
|
||||
|
||||
## Start the devenv ##
|
||||
|
||||
**Requires a minimum knowledge of tmux usage in order to use that
|
||||
development environment.**
|
||||
|
||||
For start it, staying in this repository, execute:
|
||||
|
||||
```bash
|
||||
./manage.sh pull-devenv
|
||||
./manage.sh run-devenv
|
||||
```
|
||||
|
||||
This will do the following:
|
||||
|
||||
- Pulls the latest devenv image.
|
||||
- Starts all the containers in the background.
|
||||
- Attaches to the **devenv** container and executes the tmux session.
|
||||
- The tmux session automatically starts all the necessary services.
|
||||
|
||||
You can execute the individual steps manully if you want:
|
||||
|
||||
```bash
|
||||
./manage.sh build-devenv # builds the devenv docker image (not necessary in normal sircumstances)
|
||||
./manage.sh start-devenv # starts background running containers
|
||||
./manage.sh run-devenv # enters to new tmux session inside of one of the running containers
|
||||
./manage.sh stop-devenv # stops background running containers
|
||||
./manage.sh drop-devenv # removes all the volumes, containers and networks used by the devenv
|
||||
```
|
||||
|
||||
Now having the the container running and tmux open inside the
|
||||
container, you are free to execute any commands and open many shells
|
||||
as you want.
|
||||
|
||||
You can create a new shell just pressing the **Ctr+b c** shortcut. And
|
||||
**Ctrl+b w** for switch between windows, **Ctrl+b &** for kill the
|
||||
current window.
|
||||
|
||||
For more info: https://tmuxcheatsheet.com/
|
||||
|
||||
|
||||
### Inside the tmux session
|
||||
|
||||
#### gulp
|
||||
|
||||
The styles and many related tasks are executed thanks to gulp and they are
|
||||
executed in the tmux **window 0**. This is a normal gulp watcher with some
|
||||
additional tasks.
|
||||
|
||||
|
||||
#### shadow-cljs
|
||||
|
||||
The frontend build process is located on the tmux **window 1**.
|
||||
**Shadow-cljs** is used for build and serve the frontend code. For
|
||||
more information, please refer to `02-Frontend-Developer-Guide.md`.
|
||||
|
||||
By default the **window 1** executes the shadow-cljs watch process,
|
||||
that starts a new JVM/Clojure instance if there is no one running.
|
||||
|
||||
Finally, you can start a REPL linked to the instance and the current
|
||||
connected browser, by opening a third window with `Ctrl+c` and running
|
||||
`npx shadow-cljs cljs-repl main`.
|
||||
|
||||
|
||||
#### exporter
|
||||
|
||||
The exporter app (clojurescript app running in nodejs) is located in
|
||||
**window 2**, and you can go directly to it using `ctrl+b 2` shortcut.
|
||||
|
||||
There you will found the window split in two slices. On the top slice
|
||||
you will have the build process (using shadow-cljs in the same way as
|
||||
frontend application), and on the bot slice the script that launeches
|
||||
the node process.
|
||||
|
||||
If some reason scripts does not stars correctly, you can manually
|
||||
execute `node target/app.js ` to start the exporter app.
|
||||
|
||||
|
||||
#### backend
|
||||
|
||||
The backend related environment is located in the tmux **window 3**,
|
||||
and you can go directly to it using `ctrl+b 2` shortcut.
|
||||
|
||||
By default the backend will be started in non-interactive mode for
|
||||
convenience but you can just press `Ctrl+c` and execute `./scripts/repl`
|
||||
for start the repl.
|
||||
|
||||
On the REPL you have this helper functions:
|
||||
- `(start)`: start all the environment
|
||||
- `(stop)`: stops the environment
|
||||
- `(restart)`: stops, reload and start again.
|
||||
|
||||
And many other that are defined in the `dev/user.clj` file.
|
||||
|
||||
If some exception is raised when code is reloaded, just use
|
||||
`(repl/refresh-all)` in order to finish correctly the code swaping and
|
||||
later use `(restart)` again.
|
||||
|
||||
For more information, please refer to: `03-Backend-Guide.md`.
|
|
@ -1,283 +0,0 @@
|
|||
# Frontend Guide #
|
||||
|
||||
This guide intends to explain the essential details of the frontend
|
||||
application.
|
||||
|
||||
|
||||
## Visual debug mode and utilities
|
||||
|
||||
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.
|
||||
|
||||
To activate it, open the javascript console and type
|
||||
|
||||
```javascript
|
||||
app.util.debug.toggle_debug("option")
|
||||
```
|
||||
|
||||
Current options are `bounding-boxes`, `group`, `events` and
|
||||
`rotation-handler`.
|
||||
|
||||
You can also activate or deactivate all visual aids with
|
||||
|
||||
```javascript
|
||||
app.util.debug.debug_all()
|
||||
app.util.debug.debug_none()
|
||||
```
|
||||
|
||||
## Logging, Tracing & Debugging
|
||||
|
||||
As a traditional way for debugging and tracing you have the followimg approach:
|
||||
|
||||
|
||||
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.
|
||||
|
||||
```clojure
|
||||
(prn "message" expression)
|
||||
```
|
||||
|
||||
An alternative is using the pprint function, usefull for pretty
|
||||
printing a medium-big data sturcture for completly understand it.
|
||||
|
||||
```clojure
|
||||
(:require [cljs.pprint :refer [pprint]])
|
||||
(pprint expression)
|
||||
; Outputs a clojure value as a string, nicely formatted and with data type information.
|
||||
```
|
||||
|
||||
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))
|
||||
```
|
||||
|
||||
|
||||
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.
|
||||
|
||||
|
||||
### 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.
|
||||
```
|
||||
|
||||
|
||||
## Access to clojure from javascript console
|
||||
|
||||
The penpot 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)
|
||||
```
|
||||
|
||||
|
||||
## Debug state and objects
|
||||
|
||||
There are also some useful functions to visualize the global state or
|
||||
any complex object. To use them from clojure:
|
||||
|
||||
```clojure
|
||||
(ns app.util.debug)
|
||||
(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.
|
||||
|
||||
(ns app.main.store)
|
||||
(dump-state) ; to print in console all the global state
|
||||
(dump-objects) ; to print in console all objects in workspace
|
||||
```
|
||||
|
||||
But last ones are most commonly used from javscript console:
|
||||
|
||||
```javascript
|
||||
app.main.store.dump_state()
|
||||
app.main.store.dump_objects()
|
||||
```
|
||||
|
||||
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)
|
||||
```
|
||||
|
||||
|
||||
## 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
|
||||
`app.builtins.icons/icon-xref` macro:
|
||||
|
||||
```clojure
|
||||
(ns some.namespace
|
||||
(:require-macros [app.main.ui.icons :refer [icon-xref]]))
|
||||
|
||||
(icon-xref :arrow)
|
||||
```
|
||||
|
||||
For performance reasons, all used icons are statically defined in the
|
||||
`src/app/main/ui/icons.cljs` file.
|
||||
|
||||
|
||||
|
||||
## 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" : {
|
||||
"used-in" : [ "src/app/main/ui/auth/login.cljs:61" ],
|
||||
"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
|
||||
clojure -Adev locales.clj collect src/app/main/ resources/locales.json
|
||||
```
|
||||
|
||||
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).
|
||||
|
||||
The `app.util.i18n/tr` is the general purpose function. This is a
|
||||
simple use case example:
|
||||
|
||||
```clojure
|
||||
(require '[app.util.i18n :refer [tr])
|
||||
|
||||
(tr "auth.email-or-username")
|
||||
;; => "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
|
||||
(require '[app.util.i18n :as i18n :refer [tr]])
|
||||
|
||||
(tr "ds.num-projects" (i18n/c 10))
|
||||
;; => "10 projects"
|
||||
|
||||
(tr "ds.num-projects" (i18n/c 1))
|
||||
;; => "1 project"
|
||||
```
|
||||
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
# Backend Developer Guide #
|
||||
|
||||
This guide intends to explain the essential details of the backend
|
||||
application.
|
||||
|
||||
|
||||
## Fixtures ##
|
||||
|
||||
This is a development feature that allows populate the database with a
|
||||
good amount of content (usually used for just test the application or
|
||||
perform performance tweaks on queries).
|
||||
|
||||
In order to load fixtures, enter to the REPL environment executing the
|
||||
`bin/repl` script, and then execute `(app.cli.fixtures/run {:preset :small})`.
|
||||
|
||||
You also can execute this as a standalone script with:
|
||||
|
||||
```bash
|
||||
clojure -Adev -X:fn-fixtures
|
||||
```
|
||||
|
||||
NOTE: It is an optional step because the application can start with an
|
||||
empty database.
|
||||
|
||||
This by default will create a bunch of users that can be used to login
|
||||
in the aplication. All users uses the following pattern:
|
||||
|
||||
- Username: `profileN@example.com`
|
||||
- Password: `123123`
|
||||
|
||||
Where `N` is a number from 0 to 5 on the default fixture parameters.
|
||||
|
||||
If you have a REPL access to the running process, you can execute it
|
||||
from there:
|
||||
|
||||
```clojure
|
||||
(require 'app.cli.fixtures)
|
||||
(app.cli.fixtures/run :small)
|
||||
```
|
||||
|
||||
To access to the running process repl you usually will execute this
|
||||
command:
|
||||
|
||||
```bash
|
||||
rlwrap netcat localhost 6062
|
||||
```
|
||||
|
||||
## Migrations
|
||||
|
||||
The database migrations are located in two directories:
|
||||
|
||||
- `src/app/migrations` (contains migration scripts in clojure)
|
||||
- `src/app/migrations/sql` (contains the pure SQL migrations)
|
||||
|
||||
The SQL migration naming consists in the following:
|
||||
|
||||
```
|
||||
XXXX-<add|mod|del|drop|[...verb...]>-<table-name>-<any-additional-text>
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
```
|
||||
0025-del-generic-tokens-table
|
||||
0026-mod-profile-table-add-is-active-field
|
||||
```
|
||||
|
||||
**NOTE**: if table name has more than one words, we still use `-` as a separator.
|
||||
|
||||
If you need to have a global overview of the all schema of the database you can extract it
|
||||
using postgresql:
|
||||
|
||||
```bash
|
||||
# (in the devenv environment)
|
||||
pg_dump -h postgres -s > schema.sql
|
||||
```
|
|
@ -1,61 +0,0 @@
|
|||
# Common's guide #
|
||||
|
||||
This section intends to have articles that related to both frontend
|
||||
and backend, such as: code style hints, architecture dicisions, etc...
|
||||
|
||||
|
||||
## Assertions ##
|
||||
|
||||
Penpot source code has this types of assertions:
|
||||
|
||||
**assert**: just using the clojure builtin `assert` macro.
|
||||
|
||||
Example:
|
||||
|
||||
```clojure
|
||||
(assert (number? 3) "optional message")
|
||||
```
|
||||
|
||||
This asserts are only executed on development mode. On production
|
||||
environment all assets like this will be ignored by runtime.
|
||||
|
||||
**spec/assert**: using the `app.common.spec/assert` macro.
|
||||
|
||||
Also, if you are using clojure.spec, you have the spec based
|
||||
`clojure.spec.alpha/assert` macro. In the same way as the
|
||||
`clojure.core/assert`, on production environment this asserts will be
|
||||
removed by the compiler/runtime.
|
||||
|
||||
Example:
|
||||
|
||||
````clojure
|
||||
(require '[clojure.spec.alpha :as s]
|
||||
'[app.common.spec :as us])
|
||||
|
||||
(s/def ::number number?)
|
||||
|
||||
(us/assert ::number 3)
|
||||
```
|
||||
|
||||
In the same way as the `assert` macro, this performs the spec
|
||||
assertion only on development build. On production this code will
|
||||
completely removed.
|
||||
|
||||
**spec/verify**: An assertion type that is executed always.
|
||||
|
||||
Example:
|
||||
|
||||
```clojure
|
||||
(require '[app.common.spec :as us])
|
||||
|
||||
(us/verify ::number 3)
|
||||
```
|
||||
|
||||
This macro enables you have assetions on production code.
|
||||
|
||||
**Why don't use the `clojure.spec.alpha/assert` instead of the `app.common.spec/assert`?**
|
||||
|
||||
The Penpot variant does not peforms additional runtime checks for know
|
||||
if asserts are disabled in "runtime". As a result it generates much
|
||||
simplier code at development and production builds.
|
||||
|
|
@ -1,240 +0,0 @@
|
|||
# Configuration Guide #
|
||||
|
||||
This section intends to explain all available configuration options.
|
||||
|
||||
## Backend ##
|
||||
|
||||
The default approach for pass options to backend application is using
|
||||
environment variables. Almost all environment variables starts with
|
||||
the `PENPOT_` prefix.
|
||||
|
||||
NOTE: All the examples that comes with values, they represent the
|
||||
**default** values.
|
||||
|
||||
|
||||
### Configuration Options
|
||||
|
||||
|
||||
#### Database Connection
|
||||
|
||||
```sh
|
||||
PENPOT_DATABASE_USERNAME=penpot
|
||||
PENPOT_DATABASE_PASSWORD=penpot
|
||||
PENPOT_DATABASE_URI=postgresql://127.0.0.1/penpot
|
||||
```
|
||||
|
||||
The username and password are optional.
|
||||
|
||||
#### Email (SMTP)
|
||||
|
||||
```sh
|
||||
PENPOT_SMTP_DEFAULT_REPLY_TO=no-reply@example.com
|
||||
PENPOT_SMTP_DEFAULT_FROM=no-reply@example.com
|
||||
|
||||
# When not enabled, the emails are printed to the console.
|
||||
PENPOT_SMTP_ENABLED=false
|
||||
|
||||
PENPOT_SMTP_HOST=<host>
|
||||
PENPOT_SMTP_PORT=25
|
||||
PENPOT_SMTP_USER=<username>
|
||||
PENPOT_SMTP_PASSWORD=<password>
|
||||
PENPOT_SMTP_SSL=false
|
||||
PENPOT_SMTP_TLS=false
|
||||
```
|
||||
|
||||
#### Storage (assets)
|
||||
|
||||
Assets storage is implemented using "plugable" backends. Currently
|
||||
there are three backends available: `db`, `fs` and `s3` (for AWS S3).
|
||||
|
||||
##### fs backend
|
||||
|
||||
The default backend is: **fs**.
|
||||
|
||||
```sh
|
||||
PENPOT_STORAGE_BACKEND=fs
|
||||
PENPOT_STORAGE_FS_DIRECTORY=resources/public/assets`
|
||||
```
|
||||
|
||||
The fs backend is hightly coupled with nginx way to serve files using
|
||||
`x-accel-redirect` and for correctly configuring it you will need to
|
||||
touch your nginx config for correctly expose the directory specified
|
||||
in `PENPOT_STORAGE_FS_DIRECTORY` environment.
|
||||
|
||||
For more concrete example look at the devenv nginx configurtion
|
||||
located in `<repo-root>/docker/devenv/files/nginx.conf`.
|
||||
|
||||
**NOTE**: The **fs** storage backend is used for store temporal files
|
||||
when a user uploads an image and that image need to be processed for
|
||||
creating thumbnails. So is **hightly recommeded** setting up a correct
|
||||
directory for this backend independently if it is used as main backend
|
||||
or not.
|
||||
|
||||
##### db backend
|
||||
|
||||
In some circumstances or just for convenience you can use the `db`
|
||||
backend that stores all media uploaded by the user directly inside the
|
||||
database. This backend, at expenses of some overhead, facilitates the
|
||||
backups, because with this backend all that you need to backup is the
|
||||
postgresql database. Convenient for small installations and personal
|
||||
use.
|
||||
|
||||
```sh
|
||||
PENPOT_STORAGE_BACKEND=db
|
||||
```
|
||||
|
||||
|
||||
##### s3 backend
|
||||
|
||||
And finally, you can use AWS S3 service as backend for assets
|
||||
storage. For this you will need to have AWS credentials, an bucket and
|
||||
the region of the bucket.
|
||||
|
||||
```sh
|
||||
AWS_ACCESS_KEY_ID=<you-access-key-id-here>
|
||||
AWS_SECRET_ACCESS_KEY=<your-secret-access-key-here>
|
||||
PENPOT_STORAGE_BACKEND=s3
|
||||
PENPOT_STORAGE_S3_REGION=<aws-region>
|
||||
PENPOT_STORAGE_S3_BUCKET=<bucket-name>
|
||||
```
|
||||
|
||||
Right now, only `eu-central-1` region is supported. If you need others, open an issue.
|
||||
|
||||
#### Redis
|
||||
|
||||
The redis configuration is very simple, just provide with a valid redis URI. Redis is used
|
||||
mainly for websocket notifications coordination.
|
||||
|
||||
```sh
|
||||
PENPOT_REDIS_URI=redis://localhost/0
|
||||
```
|
||||
|
||||
|
||||
#### HTTP Server
|
||||
|
||||
```sh
|
||||
PENPOT_HTTP_SERVER_PORT=6060
|
||||
PENPOT_PUBLIC_URI=http://localhost:3449
|
||||
PENPOT_REGISTRATION_ENABLED=true
|
||||
|
||||
# comma-separated domains, defaults to `""` which means that all domains are allowed)
|
||||
PENPOT_REGISTRATION_DOMAIN_WHITELIST=""
|
||||
```
|
||||
|
||||
#### Server REPL
|
||||
|
||||
The production environment by default starts a server REPL where you
|
||||
can connect and perform diagnosis operations. For this you will need
|
||||
`netcat` or `telnet` installed in the server.
|
||||
|
||||
```bash
|
||||
$ rlwrap netcat localhost 6062
|
||||
user=>
|
||||
```
|
||||
The default configuration is:
|
||||
|
||||
```sh
|
||||
PENPOT_SREPL_HOST=127.0.0.1
|
||||
PENPOT_SREPL_PORT=6062
|
||||
```
|
||||
|
||||
#### Auth with 3rd party
|
||||
|
||||
**NOTE**: a part of setting this configuration on backend, frontend
|
||||
application will also require configuration tweaks for make it work.
|
||||
|
||||
##### Google
|
||||
|
||||
```sh
|
||||
PENPOT_GOOGLE_CLIENT_ID=<client-id>
|
||||
PENPOT_GOOGLE_CLIENT_SECRET=<client-secret>
|
||||
```
|
||||
|
||||
##### Gitlab
|
||||
|
||||
```sh
|
||||
PENPOT_GITLAB_BASE_URI=https://gitlab.com
|
||||
PENPOT_GITLAB_CLIENT_ID=<client-id>
|
||||
PENPOT_GITLAB_CLIENT_SECRET=<client-secret>
|
||||
```
|
||||
|
||||
##### Github
|
||||
|
||||
```sh
|
||||
PENPOT_GITHUB_CLIENT_ID=<client-id>
|
||||
PENPOT_GITHUB_CLIENT_SECRET=<client-secret>
|
||||
```
|
||||
|
||||
##### LDAP
|
||||
|
||||
```sh
|
||||
PENPOT_LDAP_AUTH_HOST=
|
||||
PENPOT_LDAP_AUTH_PORT=
|
||||
PENPOT_LDAP_AUTH_VERSION=3
|
||||
PENPOT_LDAP_BIND_DN=
|
||||
PENPOT_LDAP_BIND_PASSWORD=
|
||||
PENPOT_LDAP_AUTH_SSL=false
|
||||
PENPOT_LDAP_AUTH_STARTTLS=false
|
||||
PENPOT_LDAP_AUTH_BASE_DN=
|
||||
PENPOT_LDAP_AUTH_USER_QUERY=(|(uid=:username)(mail=:username))
|
||||
PENPOT_LDAP_AUTH_USERNAME_ATTRIBUTE=uid
|
||||
PENPOT_LDAP_AUTH_EMAIL_ATTRIBUTE=mail
|
||||
PENPOT_LDAP_AUTH_FULLNAME_ATTRIBUTE=displayName
|
||||
PENPOT_LDAP_AUTH_AVATAR_ATTRIBUTE=jpegPhoto
|
||||
```
|
||||
|
||||
## Frontend ##
|
||||
|
||||
In comparison with backend frontend only has a few number of runtime
|
||||
configuration options and are located in the
|
||||
`<dist-root>/js/config.js` file. This file is completly optional; if
|
||||
it exists, it is loaded by the main index.html.
|
||||
|
||||
The `config.js` consists in a bunch of globar variables that are read
|
||||
by the frontend application on the bootstrap.
|
||||
|
||||
|
||||
### Auth with 3rd party
|
||||
|
||||
If any of the following variables are defined, they will enable the
|
||||
corresponding auth button in the login page
|
||||
|
||||
```js
|
||||
var penpotGoogleClientID = "<google-client-id-here>";
|
||||
var penpotGitlabClientID = "<gitlab-client-id-here>";
|
||||
var penpotGithubClientID = "<github-client-id-here>";
|
||||
var penpotLoginWithLDAP = <true|false>;
|
||||
```
|
||||
|
||||
**NOTE:** The configuration should match the backend configuration for
|
||||
respective services.
|
||||
|
||||
|
||||
### Demo warning and Demo users
|
||||
|
||||
It is possible to display a warning message on a demo environment and
|
||||
disable/enable demo users:
|
||||
|
||||
```js
|
||||
var penpotDemoWarning = <true|false>;
|
||||
var penpotAllowDemoUsers = <true|false>;
|
||||
```
|
||||
|
||||
**NOTE:** The configuration for demo users should match the backend
|
||||
configuration.
|
||||
|
||||
|
||||
## Exporter ##
|
||||
|
||||
The exporter application only have a single configuration option and
|
||||
it can be provided using environment variables in the same way as
|
||||
backend.
|
||||
|
||||
|
||||
```sh
|
||||
PENPOT_PUBLIC_URI=http://pubic-domain
|
||||
```
|
||||
|
||||
This environment variable indicates where the exporter can access to
|
||||
the public frontend application (because it uses special pages from it
|
||||
to render the shapes in the underlying headless web browser).
|
|
@ -1,45 +0,0 @@
|
|||
# Testing guide #
|
||||
|
||||
## Backend / Common
|
||||
|
||||
You can run the tests directly with:
|
||||
|
||||
```bash
|
||||
~/penpot/backend$ clojure -M:dev:tests
|
||||
```
|
||||
|
||||
Alternatively, you can run them from a REPL. First starting a REPL.
|
||||
|
||||
```bash
|
||||
~/penpot/backend$ scripts/repl
|
||||
```
|
||||
|
||||
And then:
|
||||
|
||||
```bash
|
||||
user=> (run-tests)
|
||||
user=> (run-tests 'namespace)
|
||||
user=> (run-tests 'namespace/test)
|
||||
```
|
||||
|
||||
## Frontend
|
||||
|
||||
Frontend tests have to be compiled first, and then run with node.
|
||||
|
||||
```bash
|
||||
npx shadow-cljs compile tests && node target/tests.js
|
||||
```
|
||||
|
||||
Or run the watch (that automatically runs the test):
|
||||
|
||||
```bash
|
||||
npx shadow-cljs watch tests
|
||||
```
|
||||
|
||||
## Linter
|
||||
|
||||
We can execute the linter for the whole codebase with the following command:
|
||||
|
||||
```bash
|
||||
clj-kondo --lint common:backend/src:frontend/src
|
||||
```
|
|
@ -1,170 +0,0 @@
|
|||
# Collaborative Edition & Persistence protocol
|
||||
|
||||
This is a collection of design notes for collaborative edition feature
|
||||
and persistence protocol.
|
||||
|
||||
|
||||
## Persistence Operations
|
||||
|
||||
This is a page data structure:
|
||||
|
||||
```
|
||||
{:version 2
|
||||
:options {}
|
||||
|
||||
:rmap
|
||||
{:id1 :default
|
||||
:id2 :default
|
||||
:id3 :id1}
|
||||
|
||||
:objects
|
||||
{:root
|
||||
{:type :root
|
||||
:shapes [:id1 :id2]}
|
||||
|
||||
:id1
|
||||
{:type :canvas
|
||||
:shapes [:id3]}
|
||||
|
||||
:id2 {:type :rect}
|
||||
:id3 {:type :circle}}}
|
||||
```
|
||||
|
||||
|
||||
This is a potential list of persistent ops:
|
||||
|
||||
```
|
||||
{:type :mod-opts
|
||||
:operations [<op>, ...]
|
||||
|
||||
{:type :add-obj
|
||||
:id <uuid>
|
||||
:parent <uuid>
|
||||
:obj <shape-object>}
|
||||
|
||||
{:type :mod-obj
|
||||
:id <uuid>
|
||||
:operations [<op>, ...]}
|
||||
|
||||
{:type :mov-obj
|
||||
:id <uuid>
|
||||
:frame-id <uuid>}
|
||||
|
||||
{:type :del-obj
|
||||
:id <uuid>}
|
||||
```
|
||||
|
||||
This is a potential list of operations:
|
||||
|
||||
```
|
||||
{:type :set
|
||||
:attr <any>
|
||||
:val <any>}
|
||||
|
||||
{:type :abs-order
|
||||
:id <uuid>
|
||||
:index <int>}
|
||||
|
||||
{:type :rel-order
|
||||
:id <uuid>
|
||||
:loc <one-of:up,down,top,bottom>}
|
||||
```
|
||||
|
||||
|
||||
## Ephemeral communication (Websocket protocol)
|
||||
|
||||
|
||||
### `join` ###
|
||||
|
||||
Sent by clients for notify joining a concrete page-id inside a file.
|
||||
|
||||
```clojure
|
||||
{:type :join
|
||||
:page-id <id>
|
||||
:version <number>
|
||||
}
|
||||
```
|
||||
|
||||
Will cause:
|
||||
|
||||
- A posible `:page-changes`.
|
||||
- Broadcast `:joined` message to all users of the file.
|
||||
|
||||
The `joined` message has this aspect:
|
||||
|
||||
```clojure
|
||||
{:type :joined
|
||||
:page-id <id>
|
||||
:user-id <id>
|
||||
}
|
||||
```
|
||||
|
||||
### `who` ###
|
||||
|
||||
Sent by clients for request the list of users in the channel.
|
||||
|
||||
```clojure
|
||||
{:type :who}
|
||||
```
|
||||
|
||||
Will cause:
|
||||
|
||||
- Reply to the client with the current users list:
|
||||
|
||||
```clojure
|
||||
{:type :who
|
||||
:users #{<id>,...}}
|
||||
```
|
||||
|
||||
This will be sent all the time user joins or leaves the channel for
|
||||
maintain the frontend updated with the lates participants. This
|
||||
message is also sent at the beggining of connection from server to
|
||||
client.
|
||||
|
||||
|
||||
### `pointer-update` ###
|
||||
|
||||
This is sent by client to server and then, broadcasted to the rest of
|
||||
channel participants.
|
||||
|
||||
```clojure
|
||||
{:type :pointer-update
|
||||
:page-id <id>
|
||||
:x <number>
|
||||
:y <number>
|
||||
}
|
||||
```
|
||||
|
||||
The server broadcast message will look like:
|
||||
|
||||
```clojure
|
||||
{:type :pointer-update
|
||||
:user-id <id>
|
||||
:page-id <id>
|
||||
:x <number>
|
||||
:y <number>
|
||||
}
|
||||
```
|
||||
|
||||
### `:page-snapshot` ###
|
||||
|
||||
A message that server sends to client for notify page changes. It can be sent
|
||||
on `join` and when a page change is commited to the database.
|
||||
|
||||
```clojure
|
||||
{:type :page-snapshot
|
||||
:user-id <id>
|
||||
:page-id <id>
|
||||
:version <number>
|
||||
:operations [<op>, ...]
|
||||
}
|
||||
```
|
||||
|
||||
This message is only sent to users that does not perform this change.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 303 KiB |
Loading…
Add table
Add a link
Reference in a new issue