mirror of
https://github.com/penpot/penpot.git
synced 2025-01-06 14:50:20 -05: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
22
README.md
22
README.md
|
@ -9,27 +9,11 @@
|
|||
|
||||
# PENPOT #
|
||||
|
||||
We’re excited to share that Uxbox is now Penpot! We’re changing the name, but keeping the same project essence. Stay in the loop for more news coming early 2021. Alpha release is close!
|
||||
The open-source solution for design and prototyping.
|
||||
|
||||
![PENPOT](https://raw.githubusercontent.com/penpot/penpot/develop/docs/screenshot.png)
|
||||
![PENPOT](https://penpot.app/images/workspace-ui.jpg)
|
||||
|
||||
|
||||
## Introduction ##
|
||||
|
||||
The open-source solution for design and prototyping. PENPOT is
|
||||
currently at an early development stage but we are working hard to
|
||||
bring you the beta version as soon as possible. Follow the project
|
||||
progress in Twitter or Github and stay tuned!
|
||||
|
||||
|
||||
## SVG based ##
|
||||
|
||||
Penpot works with SVG, a standard format, for all your designs and
|
||||
prototypes . This means that all your stuff in Penpot is portable and
|
||||
editable in many other vector tools and easy to use on the web.
|
||||
|
||||
[See SVG specification](https://www.w3.org/Graphics/SVG/)
|
||||
|
||||
## Contributing ##
|
||||
|
||||
**Open to you!**
|
||||
|
@ -43,7 +27,7 @@ Please refer to the [Contributing Guide](./CONTRIBUTING.md)
|
|||
|
||||
## Documentation ##
|
||||
|
||||
Please refer to [docs/ directory](./docs/).
|
||||
Please refer to the [help center](https://help.penpot.app).
|
||||
|
||||
|
||||
## License ##
|
||||
|
|
|
@ -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…
Reference in a new issue