# Maják

Maják je CMS pro Pirátské weby. Postavený je na [Wagtail](https://wagtail.io/).

[![code style: Black](https://img.shields.io/badge/code%20style-Black-000000)](https://github.com/psf/black)
[![powered by: Wagtail](https://img.shields.io/badge/powered%20by-Wagtail-43b1b0)](https://wagtail.io)
[![powered by: Django](https://img.shields.io/badge/powered%20by-Django-0C4B33)](https://www.djangoproject.com)
[![licence AGPLv3](https://img.shields.io/badge/licence-AGPLv3-brightgreen)](LICENSE)

## Pod pokličkou

[Wagtail](https://wagtail.io) a [Django](https://www.djangoproject.com) jsou poměrně
vyspělé frameworky. Vždy mysli na to, že problém co řešíš, už pravděpodobně řešil
někdo před tebou. A obvykle existuje elegantní řešení.

Pár užitečných odkazů:

* [docs Wagtail](https://docs.wagtail.io/)
* [docs Django](https://docs.djangoproject.com/)

A za zmínku stojí [Awesome Wagtail](https://github.com/springload/awesome-wagtail)
jako přehled pluginů a rozšíření pro Wagtail.

Rozšíření která používáme:

* [wagtail-metadata](https://github.com/neon-jungle/wagtail-metadata)
  - upravený template `shared/templates/wagtailmetadata/parts/tags.html`

### Struktura projektu

    .
    ├── home            = app na web úvodní stránky Majáku
    ├── donate          = app na web dary.pirati.cz
    ├── senate          = app na web senat.pirati.cz
    ├── senat_campaign  = app na weby kandidátů na senátory
    ├── districts       = app na web kraje.pirati.cz
    ├── program2021     = app na prezentaci programu 2021
    ├── uniweb          = app na univerzalni webove stranky
    ...
    ├── majak           = Django projekt s konfigurací Majáku
    ├── shared          = app se sdílenými static soubory a templaty pro weby
    ├── calendar_utils  = app s modelem a utilitami na iCal kalendáře
    ├── search          = app pro fulltext search (default, asi se k ničemu nepoužívá)
    ├── tuning          = app na tuning administračního rozhraní Majáku
    └── users           = app s custom user modelem a SSO, apod.

### Styleguide

Některé weby využívají [Pirátskou UI styleguide](https://gitlab.pirati.cz/to/weby/ui-styleguide)
pro vzhled. Idea je, že se budou sdílet nejen statické assety (CSS, JS, ...),
ale i univerzální kusy template, které se dají includovat v různých webech
(patička webu, karta článku do přehledu, atp.).

Sdílené části využívané na více webech se umísťují do:

    shared/static/styleguideXX/     = statické assety (CSS, JS, obrázky, ...)
    shared/templates/styleguideXX/  = snippety pro include v templatech

`XX` v názvu adresáře je číslo major a minor verze šablony. Např. `styleguide18`
obsahuje věci ze šablony verze `1.8.x`. Důvodem je snažší migrace na novější
verze šablony, které mohou obsahovat nekompatibilní změny. Každý web tak může
(a nemusí) migrovat nezávisle dle potřeby.

Různé verze šablony jsou k vidění na [styleguide.pir-test.eu](https://styleguide.pir-test.eu/)

### Kalendáře

Pro práci s kalendáři v iCal formátu je připravena appka `calendar_utils`.

Poskytuje `CalendarMixin` do modelu, který přidá fieldy `calendar_url` pro
editaci a `calendar` pro vazbu na model `Calendar` (který se plní a automaticky
spravuje na pozadí). Typicky se použije ve Wagtail settings pro web, kde stačí
`calendar_url` zpřístupnit pro editaci.

Kalendář se stáhne při uložení modelu obsahujícího `CalendarMixin`.

Appka přidává management command `update_callendars`, který stahuje a updatuje
kalendáře. Je třeba ho pravidelně volat na pozadí (přes CRON).

### Jupyter notebooky

Appka Uniweb umí vložit do stránky Jupyter notebook a zobrazit jeho výstup.

Pokud některé buňky nechceš generovat do výstupní stránky, nastav u nich tag
"exclude".

Pokud chceš generovat jen výstup dané buňky, použij tag "output"

Pozor: u plotly grafů je nutno zadat tagem "output" výstup buňky s inicializací
knihovny, tedy něco kde je "import plotly" apod. Pokud celou takovou buňku
vynecháš tagem "exclude", žádné grafy se nezobrazí.


## Deployment

### Konfigurace

Je třeba nastavit environment proměnné:

| proměnná | default | popis |
| --- | --- | --- |
| `DATABASE_URL` | | DSN k databázi (např. `postgres://user:pass@localhost:5342/majak`) |
| `OIDC_RP_REALM_URL` | | OpenID server realm URL (např. `http://localhost:8080/auth/realms/master/`) |
| `OIDC_RP_CLIENT_ID` | | OpenID Client ID |
| `OIDC_RP_CLIENT_SECRET` | | OpenID Client Secret |
| `BASE_URL` | https://majak.pirati.cz | základní URL pro notifikační emaily apod. |

V produkci musí být navíc nastaveno:

| proměnná | default | popis |
| --- | --- | --- |
| `DJANGO_SECRET_KEY` | | tajný šifrovací klíč |
| `DJANGO_ALLOWED_HOSTS` | | allowed hosts (více hodnot odděleno čárkami) |

Různé:

| proměnná | default | popis |
| --- | --- | --- |
| `MAJAK_ENV` | prod | `prod`/`test`/`dev` prostředí kde Maják běží |
| `SENTRY_DSN` | | pokud je zadáno, pády se reportují do Sentry |

Settings pro appky na weby:

| proměnná | default | popis |
| --- | --- | --- |
| `DONATE_PORTAL_REDIRECT_URL` | "" | URL pro přesměrování z darovacího formuláře |
| `DONATE_PORTAL_REDIRECT_SOURCE` | dary.pirati.cz | identifikátor zdroje pro přesměrování na darovací portál |
| `DONATE_PORTAL_API_URL` | "" | URL s API darovacího portálu |

### Management commands

Přes CRON je třeba na pozadí spouštět Django `manage.py` commandy:

* `clearsessions` - maže expirované sessions (denně až týdně)
* `publish_scheduled_pages` - publikuje naplánované stránky (každou hodinu)
* `update_callendars` - stáhne a aktualizuje kalendáře (několikrát denně)

### Přidání nového webu

Doména či subdoména se musí nakonfigurovat v:

* environment proměnné `DJANGO_ALLOWED_HOSTS`
* proxy před Majákem
* SSO Client redirect URIs

## Vývoj

Pro vývoj je definován pomocný `Makefile` pro časté akce. Pro nápovědu zavolej:

    $ make help

### Lokální instalace a spuštění

#### Vytvoření virtualenv pro instalaci závislostí

Vytvoř virtualenv:

    $ make venv

Vytvoří virtualenv ve složce `.venv`. Předpokládá že výchozí `python` v terminálu
je Python 3. Pokud tomu tak není, použijte třeba [Pyenv](https://github.com/pyenv/pyenv)
pro instalaci více verzí Pythonu bez rizika rozbití systému.

#### Aktivace virtualenvu

Před prací na projektu je třeba aktivovat virtualenv. To bohužel nejde dělat
pomocí nástroje `make`. Je třeba zavolat příkaz:

    $ source .venv/bin/activate

Můžete asi na to vytvořit alias pro shell. Do `~/.bash_profile` nebo `~/.zshrc`
nebo jiného konfiguračního souboru dle vašeho shellu přidejte:

    alias senv='source .venv/bin/activate'

A pak můžete virtualenv aktivovat pouze jednoduchým voláním:

    $ senv

Pro sofistikovanější řešení, které vám aktivuje virtualenv při změně adresáře na
adresář s projektem, slouží nástroj [direnv](https://direnv.net/).

Deaktivace virtualenvu se dělá příkazem:

    $ deactivate

#### Instalace závislostí

V aktivovaném virtualenvu spusťte:

    $ make install

To nainstaluje Pythonní závislosti pro vývoj projektu na lokále.

#### Nastavení environment proměnných

Environment proměnné (viz konfigurace výše) se načítají ze souboru `.env`, který
může vypadat takto:

    DATABASE_URL=postgres://db:db@localhost:5432/majak
    OIDC_RP_REALM_URL=http://localhost:8080/auth/realms/master/
    OIDC_RP_CLIENT_ID=majak
    OIDC_RP_CLIENT_SECRET=abcd

Pro lokální vývoj obsahují settings tyto výchozí hodnoty:

    DEBUG = True
    ALLOWED_HOSTS = ["*"]
    MAJAK_ENV = "dev"

### Management projektu

#### Migrace databáze

Aplikuj migrace databáze:

    $ make migrate

Při změně modelů vygeneruj migrace pomocí:

    $ make migrations

#### Spuštění development serveru

Django development server na portu `8006` se spustí příkazem:

    $ make run

Poté můžete otevřít web na adrese [http://localhost:8006](http://localhost:8006)

#### Django shell

Django shell používající `shell_plus` z Django extensions spustíte:

    $ make shell

### Testy

Používá se testovací framework [pytest](https://pytest.org). Spuštění testů:

    $ pytest

Případně přes `make`, ale bez možnosti parametrizovat spuštění testů:

    $ make test

Coverage report:

    $ make coverage

### Code quality

K formátování kódu se používá [black](https://github.com/psf/black). Doporučujeme
ho nainstalovat do vašeho editoru kódu, aby soubory přeformátoval po uložení.

Přeformátování kódu nástrojem `black` je součástí `pre-commit` hooks (viz níže).

Součástí `pre-commit` hooků je také automatické seřazení importů v Pythonních
souborech nástrojem [isort](https://github.com/timothycrosley/isort/).

### Pre-commit hooky

Použivá se [pre-commit](https://pre-commit.com/) framework pro management git
pre-commit hooks.

Máte-li pre-commit framework [nainstalovaný](https://pre-commit.com/#installation)
spusttě příkaz:

    $ make install-hooks

Ten naisntaluje hooky pro projekt. A poté při každém commitu dojde k požadovaným
akcím na změněných souborech.

Ručně se dají hooky na všechny soubory spustit příkazem:

    $ make hooks

## Upgrade závislostí

K upgrade se používají [pip-tools](https://github.com/jazzband/pip-tools) (`pip install pip-tools`):

    $ cd requirements/
    $ pip-compile -U base.in
    $ pip-compile -U production.in
    $ pip-compile -U dev.in

Tím se vygenerují `base.txt`, `production.txt` a `dev.txt`.