+
+
+
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..5ace414
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/.idea/webResources.xml b/.idea/webResources.xml
new file mode 100644
index 0000000..b7a61f6
--- /dev/null
+++ b/.idea/webResources.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..0058d45
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,49 @@
+exclude: '^docs/|/migrations/|devcontainer.json'
+default_stages: [commit]
+
+default_language_version:
+ python: python3.12
+
+repos:
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v4.6.0
+ hooks:
+ - id: trailing-whitespace
+ - id: end-of-file-fixer
+ - id: check-json
+ - id: check-toml
+ - id: check-xml
+ - id: check-yaml
+ - id: debug-statements
+ - id: check-builtin-literals
+ - id: check-case-conflict
+ - id: check-docstring-first
+ - id: detect-private-key
+
+ - repo: https://github.com/adamchainz/django-upgrade
+ rev: '1.16.0'
+ hooks:
+ - id: django-upgrade
+ args: ['--target-version', '4.2']
+
+ # Run the Ruff linter.
+ - repo: https://github.com/astral-sh/ruff-pre-commit
+ rev: v0.4.3
+ hooks:
+ # Linter
+ - id: ruff
+ args: [--fix, --exit-non-zero-on-fix]
+ # Formatter
+ - id: ruff-format
+
+ - repo: https://github.com/Riverside-Healthcare/djLint
+ rev: v1.34.1
+ hooks:
+ - id: djlint-reformat-django
+ - id: djlint-django
+
+# sets up .pre-commit-ci.yaml to ensure pre-commit dependencies stay up to date
+ci:
+ autoupdate_schedule: weekly
+ skip: []
+ submodules: false
diff --git a/.readthedocs.yml b/.readthedocs.yml
new file mode 100644
index 0000000..5564388
--- /dev/null
+++ b/.readthedocs.yml
@@ -0,0 +1,20 @@
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required
+version: 2
+
+# Set the version of Python and other tools you might need
+build:
+ os: ubuntu-22.04
+ tools:
+ python: '3.12'
+
+# Build documentation in the docs/ directory with Sphinx
+sphinx:
+ configuration: docs/conf.py
+
+# Python requirements required to build your docs
+python:
+ install:
+ - requirements: requirements/local.txt
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
new file mode 100644
index 0000000..c6540fa
--- /dev/null
+++ b/CONTRIBUTORS.txt
@@ -0,0 +1 @@
+Hendrik Huyskens
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..97a4f76
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,9 @@
+
+The MIT License (MIT)
+Copyright (c) 2024, Hendrik Huyskens
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..81250ce
--- /dev/null
+++ b/README.md
@@ -0,0 +1,88 @@
+# Building Dialouge Webapp
+
+Webapp für die Wärmewende
+
+[![Built with Cookiecutter Django](https://img.shields.io/badge/built%20with-Cookiecutter%20Django-ff69b4.svg?logo=cookiecutter)](https://github.com/cookiecutter/cookiecutter-django/)
+[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
+
+License: MIT
+
+## Settings
+
+Moved to [settings](http://cookiecutter-django.readthedocs.io/en/latest/settings.html).
+
+## Basic Commands
+
+### Setting Up Your Users
+
+- To create a **normal user account**, just go to Sign Up and fill out the form. Once you submit it, you'll see a "Verify Your E-mail Address" page. Go to your console to see a simulated email verification message. Copy the link into your browser. Now the user's email should be verified and ready to go.
+
+- To create a **superuser account**, use this command:
+
+ $ python manage.py createsuperuser
+
+For convenience, you can keep your normal user logged in on Chrome and your superuser logged in on Firefox (or similar), so that you can see how the site behaves for both kinds of users.
+
+### Type checks
+
+Running type checks with mypy:
+
+ $ mypy building_dialouge_webapp
+
+### Test coverage
+
+To run the tests, check your test coverage, and generate an HTML coverage report:
+
+ $ coverage run -m pytest
+ $ coverage html
+ $ open htmlcov/index.html
+
+#### Running tests with pytest
+
+ $ pytest
+
+### Live reloading and Sass CSS compilation
+
+Moved to [Live reloading and SASS compilation](https://cookiecutter-django.readthedocs.io/en/latest/developing-locally.html#sass-compilation-live-reloading).
+
+### Celery
+
+This app comes with Celery.
+
+To run a celery worker:
+
+```bash
+cd building_dialouge_webapp
+celery -A config.celery_app worker -l info
+```
+
+Please note: For Celery's import magic to work, it is important _where_ the celery commands are run. If you are in the same folder with _manage.py_, you should be right.
+
+To run [periodic tasks](https://docs.celeryq.dev/en/stable/userguide/periodic-tasks.html), you'll need to start the celery beat scheduler service. You can start it as a standalone process:
+
+```bash
+cd building_dialouge_webapp
+celery -A config.celery_app beat
+```
+
+or you can embed the beat service inside a worker with the `-B` option (not recommended for production use):
+
+```bash
+cd building_dialouge_webapp
+celery -A config.celery_app worker -B -l info
+```
+
+### Sentry
+
+Sentry is an error logging aggregator service. You can sign up for a free account at or download and host it yourself.
+The system is set up with reasonable defaults, including 404 logging and integration with the WSGI application.
+
+You must set the DSN url in production.
+
+## Deployment
+
+The following details how to deploy this application.
+
+### Docker
+
+See detailed [cookiecutter-django Docker documentation](http://cookiecutter-django.readthedocs.io/en/latest/deployment-with-docker.html).
diff --git a/building_dialouge_webapp/__init__.py b/building_dialouge_webapp/__init__.py
new file mode 100644
index 0000000..3da9e5f
--- /dev/null
+++ b/building_dialouge_webapp/__init__.py
@@ -0,0 +1,5 @@
+__version__ = "0.1.0"
+__version_info__ = tuple(
+ int(num) if num.isdigit() else num
+ for num in __version__.replace("-", ".", 1).split(".")
+)
diff --git a/building_dialouge_webapp/conftest.py b/building_dialouge_webapp/conftest.py
new file mode 100644
index 0000000..a5c6d2f
--- /dev/null
+++ b/building_dialouge_webapp/conftest.py
@@ -0,0 +1,14 @@
+import pytest
+
+from building_dialouge_webapp.users.models import User
+from building_dialouge_webapp.users.tests.factories import UserFactory
+
+
+@pytest.fixture(autouse=True)
+def _media_storage(settings, tmpdir) -> None:
+ settings.MEDIA_ROOT = tmpdir.strpath
+
+
+@pytest.fixture()
+def user(db) -> User:
+ return UserFactory()
diff --git a/building_dialouge_webapp/contrib/__init__.py b/building_dialouge_webapp/contrib/__init__.py
new file mode 100644
index 0000000..1c7ecc8
--- /dev/null
+++ b/building_dialouge_webapp/contrib/__init__.py
@@ -0,0 +1,5 @@
+"""
+To understand why this file is here, please read:
+
+http://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django
+"""
diff --git a/building_dialouge_webapp/contrib/sites/__init__.py b/building_dialouge_webapp/contrib/sites/__init__.py
new file mode 100644
index 0000000..1c7ecc8
--- /dev/null
+++ b/building_dialouge_webapp/contrib/sites/__init__.py
@@ -0,0 +1,5 @@
+"""
+To understand why this file is here, please read:
+
+http://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django
+"""
diff --git a/building_dialouge_webapp/contrib/sites/migrations/0001_initial.py b/building_dialouge_webapp/contrib/sites/migrations/0001_initial.py
new file mode 100644
index 0000000..fd76afb
--- /dev/null
+++ b/building_dialouge_webapp/contrib/sites/migrations/0001_initial.py
@@ -0,0 +1,43 @@
+import django.contrib.sites.models
+from django.contrib.sites.models import _simple_domain_name_validator
+from django.db import migrations
+from django.db import models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = []
+
+ operations = [
+ migrations.CreateModel(
+ name="Site",
+ fields=[
+ (
+ "id",
+ models.AutoField(
+ verbose_name="ID",
+ serialize=False,
+ auto_created=True,
+ primary_key=True,
+ ),
+ ),
+ (
+ "domain",
+ models.CharField(
+ max_length=100,
+ verbose_name="domain name",
+ validators=[_simple_domain_name_validator],
+ ),
+ ),
+ ("name", models.CharField(max_length=50, verbose_name="display name")),
+ ],
+ options={
+ "ordering": ("domain",),
+ "db_table": "django_site",
+ "verbose_name": "site",
+ "verbose_name_plural": "sites",
+ },
+ bases=(models.Model,),
+ managers=[("objects", django.contrib.sites.models.SiteManager())],
+ ),
+ ]
diff --git a/building_dialouge_webapp/contrib/sites/migrations/0002_alter_domain_unique.py b/building_dialouge_webapp/contrib/sites/migrations/0002_alter_domain_unique.py
new file mode 100644
index 0000000..4a44a6a
--- /dev/null
+++ b/building_dialouge_webapp/contrib/sites/migrations/0002_alter_domain_unique.py
@@ -0,0 +1,21 @@
+import django.contrib.sites.models
+from django.db import migrations
+from django.db import models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [("sites", "0001_initial")]
+
+ operations = [
+ migrations.AlterField(
+ model_name="site",
+ name="domain",
+ field=models.CharField(
+ max_length=100,
+ unique=True,
+ validators=[django.contrib.sites.models._simple_domain_name_validator],
+ verbose_name="domain name",
+ ),
+ )
+ ]
diff --git a/building_dialouge_webapp/contrib/sites/migrations/0003_set_site_domain_and_name.py b/building_dialouge_webapp/contrib/sites/migrations/0003_set_site_domain_and_name.py
new file mode 100644
index 0000000..b879e9a
--- /dev/null
+++ b/building_dialouge_webapp/contrib/sites/migrations/0003_set_site_domain_and_name.py
@@ -0,0 +1,63 @@
+"""
+To understand why this file is here, please read:
+
+http://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django
+"""
+from django.conf import settings
+from django.db import migrations
+
+
+def _update_or_create_site_with_sequence(site_model, connection, domain, name):
+ """Update or create the site with default ID and keep the DB sequence in sync."""
+ site, created = site_model.objects.update_or_create(
+ id=settings.SITE_ID,
+ defaults={
+ "domain": domain,
+ "name": name,
+ },
+ )
+ if created:
+ # We provided the ID explicitly when creating the Site entry, therefore the DB
+ # sequence to auto-generate them wasn't used and is now out of sync. If we
+ # don't do anything, we'll get a unique constraint violation the next time a
+ # site is created.
+ # To avoid this, we need to manually update DB sequence and make sure it's
+ # greater than the maximum value.
+ max_id = site_model.objects.order_by("-id").first().id
+ with connection.cursor() as cursor:
+ cursor.execute("SELECT last_value from django_site_id_seq")
+ (current_id,) = cursor.fetchone()
+ if current_id <= max_id:
+ cursor.execute(
+ "alter sequence django_site_id_seq restart with %s",
+ [max_id + 1],
+ )
+
+
+def update_site_forward(apps, schema_editor):
+ """Set site domain and name."""
+ Site = apps.get_model("sites", "Site")
+ _update_or_create_site_with_sequence(
+ Site,
+ schema_editor.connection,
+ "rl-institut.de",
+ "Building Dialouge Webapp",
+ )
+
+
+def update_site_backward(apps, schema_editor):
+ """Revert site domain and name to default."""
+ Site = apps.get_model("sites", "Site")
+ _update_or_create_site_with_sequence(
+ Site,
+ schema_editor.connection,
+ "example.com",
+ "example.com",
+ )
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [("sites", "0002_alter_domain_unique")]
+
+ operations = [migrations.RunPython(update_site_forward, update_site_backward)]
diff --git a/building_dialouge_webapp/contrib/sites/migrations/0004_alter_options_ordering_domain.py b/building_dialouge_webapp/contrib/sites/migrations/0004_alter_options_ordering_domain.py
new file mode 100644
index 0000000..f7118ca
--- /dev/null
+++ b/building_dialouge_webapp/contrib/sites/migrations/0004_alter_options_ordering_domain.py
@@ -0,0 +1,21 @@
+# Generated by Django 3.1.7 on 2021-02-04 14:49
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("sites", "0003_set_site_domain_and_name"),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name="site",
+ options={
+ "ordering": ["domain"],
+ "verbose_name": "site",
+ "verbose_name_plural": "sites",
+ },
+ ),
+ ]
diff --git a/building_dialouge_webapp/contrib/sites/migrations/__init__.py b/building_dialouge_webapp/contrib/sites/migrations/__init__.py
new file mode 100644
index 0000000..1c7ecc8
--- /dev/null
+++ b/building_dialouge_webapp/contrib/sites/migrations/__init__.py
@@ -0,0 +1,5 @@
+"""
+To understand why this file is here, please read:
+
+http://cookiecutter-django.readthedocs.io/en/latest/faq.html#why-is-there-a-django-contrib-sites-directory-in-cookiecutter-django
+"""
diff --git a/building_dialouge_webapp/static/css/project.css b/building_dialouge_webapp/static/css/project.css
new file mode 100644
index 0000000..f1d543d
--- /dev/null
+++ b/building_dialouge_webapp/static/css/project.css
@@ -0,0 +1,13 @@
+/* These styles are generated from project.scss. */
+
+.alert-debug {
+ color: black;
+ background-color: white;
+ border-color: #d6e9c6;
+}
+
+.alert-error {
+ color: #b94a48;
+ background-color: #f2dede;
+ border-color: #eed3d7;
+}
diff --git a/building_dialouge_webapp/static/fonts/.gitkeep b/building_dialouge_webapp/static/fonts/.gitkeep
new file mode 100644
index 0000000..e69de29
diff --git a/building_dialouge_webapp/static/images/favicons/favicon.ico b/building_dialouge_webapp/static/images/favicons/favicon.ico
new file mode 100644
index 0000000..e1c1dd1
Binary files /dev/null and b/building_dialouge_webapp/static/images/favicons/favicon.ico differ
diff --git a/building_dialouge_webapp/static/js/project.js b/building_dialouge_webapp/static/js/project.js
new file mode 100644
index 0000000..d26d23b
--- /dev/null
+++ b/building_dialouge_webapp/static/js/project.js
@@ -0,0 +1 @@
+/* Project specific Javascript goes here. */
diff --git a/building_dialouge_webapp/templates/403.html b/building_dialouge_webapp/templates/403.html
new file mode 100644
index 0000000..5795603
--- /dev/null
+++ b/building_dialouge_webapp/templates/403.html
@@ -0,0 +1,13 @@
+{% extends "base.html" %}
+
+{% block title %}Forbidden (403){% endblock title %}
+{% block content %}
+
Forbidden (403)
+
+ {% if exception %}
+ {{ exception }}
+ {% else %}
+ You're not allowed to access this page.
+ {% endif %}
+
+{% endblock content %}
diff --git a/building_dialouge_webapp/templates/403_csrf.html b/building_dialouge_webapp/templates/403_csrf.html
new file mode 100644
index 0000000..5795603
--- /dev/null
+++ b/building_dialouge_webapp/templates/403_csrf.html
@@ -0,0 +1,13 @@
+{% extends "base.html" %}
+
+{% block title %}Forbidden (403){% endblock title %}
+{% block content %}
+
Forbidden (403)
+
+ {% if exception %}
+ {{ exception }}
+ {% else %}
+ You're not allowed to access this page.
+ {% endif %}
+
+{% endblock content %}
diff --git a/building_dialouge_webapp/templates/404.html b/building_dialouge_webapp/templates/404.html
new file mode 100644
index 0000000..5111d3a
--- /dev/null
+++ b/building_dialouge_webapp/templates/404.html
@@ -0,0 +1,13 @@
+{% extends "base.html" %}
+
+{% block title %}Page not found{% endblock title %}
+{% block content %}
+
Page not found
+
+ {% if exception %}
+ {{ exception }}
+ {% else %}
+ This is not the page you were looking for.
+ {% endif %}
+
+{% endblock content %}
diff --git a/building_dialouge_webapp/templates/500.html b/building_dialouge_webapp/templates/500.html
new file mode 100644
index 0000000..1add004
--- /dev/null
+++ b/building_dialouge_webapp/templates/500.html
@@ -0,0 +1,10 @@
+{% extends "base.html" %}
+
+{% block title %}Server Error{% endblock title %}
+{% block content %}
+
Ooops!!! 500
+
Looks like something went wrong!
+
+ We track these errors automatically, but if the problem persists feel free to contact us. In the meantime, try refreshing.
+