Skip to content

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

4 watching

Forks

Latest commit

 

History

4,916 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Kausal Watch

Kausal Watch is a service for administrating and monitoring action plans. It has the following components:

  • admin UI for modifying action plan content
  • REST API for distributing the information

The service was first used to implement monitoring for the Carbon-neutral Helsinki 2035 action plan. The ReactJS UI code is also open source.

Installation

Run in Docker locally

Build the Docker containers first with:

docker compose build

Then start them with:

docker compose -f docker-compose.yml -f docker-compose.local.yml up -d app

This should start an HTTP server on localhost, port 8000. To be able to log in, you'll need to create a user together with some test data:

docker compose exec app ./manage.py create_superuser_with_defaults \
  --email superuser@example.com --organization "Test org" \
  --first-name Super --last-name User

After the command above finishes, you can point your browser at localhost:8000 and log in using the password you provided.

Development

Installation

Initialize the required shared-code submodule. It also provides the mise configuration shared with Kausal Paths through the symlinks in mise/:

git submodule update --init kausal_common

In the project root directory, create and activate a Python virtual environment:

uv venv
source .venv/bin/activate

Install the required Python packages:

uv sync

The Django apps live under src/ (a src layout), and uv sync installs the project itself in editable mode, which is what puts src/ on the import path. The apps are enumerated in [tool.uv.build-backend] module-name in pyproject.toml, so a newly added app has to be listed there as well. manage.py, conftest.py, templates/ and locale/ stay at the repo root.

If you have access to the Kausal private extensions, check out the optional submodule. A plain git submodule update --init skips it on purpose, so it needs an explicit --checkout:

git submodule update --init --checkout private/extensions

The kausal_watch_extensions package then becomes importable through the committed src/kausal_watch_extensions symlink. When the submodule is absent, the symlink dangles and the extension is simply not installed.

Setup

Create a .env file in your repo root with the following contents. Ask a teammate for the values of AZURE_AD_ variables.

DEBUG=1
DATABASE_URL=postgis:///aplans
AZURE_AD_CLIENT_ID=
AZURE_AD_CLIENT_SECRET=

Build the Kausal extensions (only relevant when the submodule is checked out):

mise deps

This installs the extension client's Node dependencies, builds its bundles into the extension's static/ directory, and compiles its translations. The provider configuration lives in the submodule (private/extensions/mise/watch.toml) and is loaded through mise/conf.d/. Whenever a submodule update changes the client sources or translation files, mise reminds you to rerun it and mise run does so automatically.

Collect static files:

python manage.py collectstatic

Make sure you have created a Postgres database with the same name (here aplans).

Run migrations:

python manage.py migrate

Create a superuser:

Note: You might need the following translations during the createsuperuser operation: käyttäjätunnus = username, sähköpostiosoite = e-mail

python manage.py createsuperuser

To access the admin UI with the created superuser, create and associate a Person with it:

python manage.py shell_plus
superuser = User.objects.get(email='<email of the superuser you created>')
organization = Organization.objects.get(
    abbreviation='Kausal'
)  # Found only if database is prepopulated with the help of a coworker

person = Person.objects.create(
    user=superuser,
    first_name='<first name of your user>',
    last_name='<last name of your user>',
    email='<email of the superuser you created>',
    organization=organization,
)
person.save()

Compile the translation files:

python manage.py compilemessages

Run the development server, the Admin UI will be available at localhost:8000:

python manage.py runserver

Note: the database will be empty, ask a teammate for help to restore your local database from a backup

Production

The project is containerized using Docker Compose. You will still need to set some variables in your environment; see the first few lines in src/aplans/settings.py.

In particular, you will need to set the database credentials; for example:

POSTGRES_PASSWORD=change_me
DATABASE_URL=postgis://watch:change_me@db/watch

Contributing

Python requirements

We use uv to manage dependencies. Invoke uv sync -P <PACKAGE> to upgrade one package, and uv sync -U to upgrade all of them.

Updating translations

To extract translatable strings and update every translation catalogue this repo owns, run:

mise run messages

This updates the Watch catalogues in locale/ (the django, djangojs and notifications domains), the shared kausal_common/locale/, and, when the extensions submodule is checked out, the catalogue of the package named by extension_package in mise.dev.toml. mise run messages-host, messages-common and messages-extensions update one of them at a time. The tasks come from the shared mise config in kausal_common and all run kausal_common/development/tools/makemessages.sh.

Do not run a bare python manage.py makemessages from the repo root. Django walks every directory under the current one, so it would also rewrite the catalogues of kausal_common and the extensions submodule, and send strings from their shared modules into locale/. The script instead scopes each run to its own catalogue, and extracts kausal_common and the extensions from inside their own directories so that Watch and Paths produce identical catalogues for them.

Only languages that already have a catalogue are updated. To add a language, create its catalogue once by hand, for example python manage.py makemessages -l de --add-location=file --no-wrap --ignore private --ignore kausal_common --ignore node_modules.

The notification templates (.mjml) use Jinja2 rather than the Django template language, so their notifications domain is extracted with pybabel as configured in babel.cfg.

To create a new message catalog (.po file) from the generated .pot file, you can run the following (example for the de locale):

pybabel init -D notifications -i locale/notifications.pot -d locale -l de

The equivalent of compilemessages for the MJML templates is the following (example for the de locale):

pybabel compile -D notifications -d locale -l de

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

4 watching

Forks

Releases

Packages

Used by

Contributors

Languages