├── jawanndenn ├── tests │ ├── __init__.py │ ├── helpers.py │ ├── factories.py │ ├── test_middleware.py │ └── test_markup.py ├── views │ ├── __init__.py │ ├── tests │ │ ├── __init__.py │ │ ├── test_favicon.py │ │ ├── test_security_txt.py │ │ ├── test_static_files.py │ │ └── test_polls.py │ ├── security_txt.py │ ├── favicon.py │ ├── static_files.py │ └── polls.py ├── management │ ├── __init__.py │ └── commands │ │ ├── __init__.py │ │ ├── tests │ │ ├── __init__.py │ │ └── test_prune_expired_polls.py │ │ └── prune_expired_polls.py ├── migrations │ ├── __init__.py │ ├── 0005_remove_poll_equal_width.py │ ├── 0004_tribool_votes.py │ ├── 0003_poll_expires_at.py │ ├── 0002_django_extensions_3_0_0.py │ └── 0001_initial.py ├── .gitignore ├── static │ ├── css │ │ └── .gitignore │ ├── js │ │ └── .gitignore │ ├── favicon │ │ ├── favicon.ico │ │ ├── favicon-96x96.png │ │ ├── apple-touch-icon.png │ │ ├── web-app-manifest-192x192.png │ │ ├── web-app-manifest-512x512.png │ │ ├── site.webmanifest │ │ └── favicon.svg │ ├── well-known │ │ └── security.txt │ └── 3rdparty │ │ ├── roboto-20 │ │ ├── fonts │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100.eot │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100.ttf │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300.eot │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300.ttf │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500.eot │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500.ttf │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700.eot │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700.ttf │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900.eot │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900.ttf │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100.woff │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100.woff2 │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300.woff │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300.woff2 │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500.woff │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500.woff2 │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700.woff │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700.woff2 │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900.woff │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900.woff2 │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-italic.eot │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-italic.ttf │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-italic.woff │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-italic.woff2 │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-regular.eot │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-regular.ttf │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-regular.woff │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100italic.eot │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100italic.ttf │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100italic.woff │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100italic.woff2 │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300italic.eot │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300italic.ttf │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300italic.woff │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300italic.woff2 │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500italic.eot │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500italic.ttf │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500italic.woff │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500italic.woff2 │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700italic.eot │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700italic.ttf │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700italic.woff │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700italic.woff2 │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900italic.eot │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900italic.ttf │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900italic.woff │ │ │ ├── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900italic.woff2 │ │ │ └── roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-regular.woff2 │ │ ├── COPYING │ │ └── css │ │ │ └── roboto.css │ │ └── github-buttons-4.0.1 │ │ ├── LICENSE.md │ │ └── docs │ │ └── github-btn.html ├── frontend │ ├── .gitignore │ ├── .prettierignore │ ├── .prettierrc │ ├── src │ │ ├── env.d.ts │ │ ├── index.tsx │ │ ├── PollSetup.css │ │ ├── Footer.css │ │ ├── dedent.ts │ │ ├── Poll.css │ │ ├── Footer.tsx │ │ ├── PollPreview.tsx │ │ ├── TristateCheckbox.tsx │ │ ├── App.css │ │ ├── markup.ts │ │ ├── CheckboxIcons.tsx │ │ ├── App.tsx │ │ ├── PollSetup.tsx │ │ └── Poll.tsx │ ├── rsbuild.config.ts │ ├── tsconfig.json │ ├── package.json │ ├── eslint.config.mjs │ └── index_template.htm ├── __init__.py ├── metadata.py ├── asgi.py ├── wsgi.py ├── markup.py ├── models.py ├── middleware.py ├── serializers.py ├── urls.py ├── __main__.py └── settings.py ├── .gitignore ├── requirements.txt ├── jawanndenn-setup.png ├── crontab ├── .coveragerc ├── ruff.toml ├── .github ├── workflows │ ├── dockerignore_detect_out_of_sync.yml │ ├── run_pre_commit.yml │ ├── build_and_lint_frontend.yml │ ├── build_and_test_using_docker.yml │ ├── npm_detect_outdated.yml │ └── pre_commit_detect_outdated.yml └── dependabot.yml ├── .pre-commit-config.yaml ├── manage.py ├── generate_whitelist_dockerignore_file.sh ├── docker-entrypoint.sh ├── .dockerignore ├── Dockerfile ├── setup.py ├── docker-compose.yml └── README.md /jawanndenn/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /jawanndenn/views/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /jawanndenn/management/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /jawanndenn/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /jawanndenn/.gitignore: -------------------------------------------------------------------------------- 1 | /index.html 2 | -------------------------------------------------------------------------------- /jawanndenn/views/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /jawanndenn/management/commands/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /jawanndenn/static/css/.gitignore: -------------------------------------------------------------------------------- 1 | /*.css 2 | -------------------------------------------------------------------------------- /jawanndenn/management/commands/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /jawanndenn/frontend/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | -------------------------------------------------------------------------------- /jawanndenn/frontend/.prettierignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | -------------------------------------------------------------------------------- /jawanndenn/static/js/.gitignore: -------------------------------------------------------------------------------- 1 | /*.js 2 | /*.js.LICENSE.txt 3 | -------------------------------------------------------------------------------- /jawanndenn/frontend/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /build/ 3 | /dist/ 4 | /jawanndenn.egg-info/ 5 | *.pyc 6 | -------------------------------------------------------------------------------- /jawanndenn/frontend/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | -r requirements-direct.txt 2 | -r requirements-indirect.txt 3 | -------------------------------------------------------------------------------- /jawanndenn/__init__.py: -------------------------------------------------------------------------------- 1 | DEFAULT_MAX_POLLS = 1000 2 | DEFAULT_MAX_VOTES_PER_POLL = 40 3 | -------------------------------------------------------------------------------- /jawanndenn-setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn-setup.png -------------------------------------------------------------------------------- /jawanndenn/static/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/favicon/favicon.ico -------------------------------------------------------------------------------- /jawanndenn/static/favicon/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/favicon/favicon-96x96.png -------------------------------------------------------------------------------- /jawanndenn/static/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /jawanndenn/static/well-known/security.txt: -------------------------------------------------------------------------------- 1 | Contact: mailto:sebastian@pipping.org 2 | Expires: 9999-12-31T23:59:59.999Z 3 | Preferred-Languages: en, de 4 | -------------------------------------------------------------------------------- /crontab: -------------------------------------------------------------------------------- 1 | # Fox syntax see https://github.com/aptible/supercronic/tree/master/cronexpr#implementation 2 | @hourly python3 -m django prune_expired_polls 3 | -------------------------------------------------------------------------------- /jawanndenn/static/favicon/web-app-manifest-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/favicon/web-app-manifest-192x192.png -------------------------------------------------------------------------------- /jawanndenn/static/favicon/web-app-manifest-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/favicon/web-app-manifest-512x512.png -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | branch = True 3 | # Warning "already-imported" is silenced for https://github.com/nedbat/coveragepy/issues/905 4 | disable_warnings = already-imported 5 | source = ./ 6 | omit = 7 | ./asgi.py 8 | ./wsgi.py 9 | -------------------------------------------------------------------------------- /jawanndenn/metadata.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2016-2021 Sebastian Pipping 2 | # Licensed under GNU Affero GPL v3 or later 3 | 4 | APP_NAME = "jawanndenn" 5 | 6 | _VERSION = (4, 0, 0) 7 | VERSION_STR = ".".join(map(str, _VERSION)) 8 | -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100.eot -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100.ttf -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300.eot -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300.ttf -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500.eot -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500.ttf -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700.eot -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700.ttf -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900.eot -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900.ttf -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100.woff -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100.woff2 -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300.woff -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300.woff2 -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500.woff -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500.woff2 -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700.woff -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700.woff2 -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900.woff -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900.woff2 -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-italic.eot -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-italic.ttf -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-italic.woff -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-italic.woff2 -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-regular.eot -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-regular.ttf -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-regular.woff -------------------------------------------------------------------------------- /jawanndenn/tests/helpers.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2023 Sebastian Pipping 2 | # Licensed under GNU Affero GPL v3 or later 3 | 4 | # These are to allow annotated use of .assertNumQueries 5 | SAVEPOINT = 1 6 | RELEASE_SAVEPOINT = 1 7 | 8 | 9 | def SELECT(comment): 10 | return 1 11 | -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100italic.eot -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100italic.ttf -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100italic.woff -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-100italic.woff2 -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300italic.eot -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300italic.ttf -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300italic.woff -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-300italic.woff2 -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500italic.eot -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500italic.ttf -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500italic.woff -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-500italic.woff2 -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700italic.eot -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700italic.ttf -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700italic.woff -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-700italic.woff2 -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900italic.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900italic.eot -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900italic.ttf -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900italic.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900italic.woff -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900italic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-900italic.woff2 -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hartwork/jawanndenn/HEAD/jawanndenn/static/3rdparty/roboto-20/fonts/roboto-v20-vietnamese_latin-ext_latin_greek-ext_greek_cyrillic-ext_cyrillic-regular.woff2 -------------------------------------------------------------------------------- /jawanndenn/frontend/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import App from './App'; 4 | 5 | const rootEl = document.getElementById('root'); 6 | if (rootEl) { 7 | const root = ReactDOM.createRoot(rootEl); 8 | root.render( 9 | 10 | 11 | , 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /ruff.toml: -------------------------------------------------------------------------------- 1 | indent-width = 4 2 | line-length = 99 3 | target-version = "py311" 4 | 5 | [lint] 6 | select = [ 7 | "C90", # mccabe 8 | "E", # pycodestyle 9 | "F", # Pyflakes + flake8 10 | "I", # isort 11 | "UP", # pyupgrade 12 | "W", # pycodestyle 13 | ] 14 | ignore = [ 15 | "UP031", # Use format specifiers instead of percent format; TODO drop 16 | ] 17 | -------------------------------------------------------------------------------- /jawanndenn/migrations/0005_remove_poll_equal_width.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 5.2.2 on 2025-08-04 12:38 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("jawanndenn", "0004_tribool_votes"), 9 | ] 10 | 11 | operations = [ 12 | migrations.RemoveField( 13 | model_name="poll", 14 | name="equal_width", 15 | ), 16 | ] 17 | -------------------------------------------------------------------------------- /jawanndenn/frontend/rsbuild.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from '@rsbuild/core'; 2 | import { pluginReact } from '@rsbuild/plugin-react'; 3 | 4 | export default defineConfig({ 5 | html: { 6 | template: './index_template.htm', 7 | }, 8 | output: { 9 | assetPrefix: '.', // i.e. turn absolute "/static" into relative "./static" 10 | distPath: { 11 | root: '../', // this was "dist" before 12 | }, 13 | }, 14 | plugins: [pluginReact()], 15 | }); 16 | -------------------------------------------------------------------------------- /jawanndenn/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for jawanndenn project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "jawanndenn.settings") 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /jawanndenn/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for jawanndenn project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "jawanndenn.settings") 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /jawanndenn/migrations/0004_tribool_votes.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 5.2.1 on 2025-06-06 22:14 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("jawanndenn", "0003_poll_expires_at"), 9 | ] 10 | 11 | operations = [ 12 | migrations.AlterField( 13 | model_name="vote", 14 | name="yes", 15 | field=models.BooleanField(null=True), 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /jawanndenn/migrations/0003_poll_expires_at.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1 on 2020-08-15 23:54 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("jawanndenn", "0002_django_extensions_3_0_0"), 9 | ] 10 | 11 | operations = [ 12 | migrations.AddField( 13 | model_name="poll", 14 | name="expires_at", 15 | field=models.DateTimeField(null=True), 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /jawanndenn/management/commands/prune_expired_polls.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2020 Sebastian Pipping 2 | # Licensed under GNU Affero GPL v3 or later 3 | 4 | from django.core.management import BaseCommand 5 | 6 | from ...models import Poll 7 | 8 | 9 | class Command(BaseCommand): 10 | help = "Deletes expired polls" 11 | 12 | def handle(self, *args, **options): 13 | polls_deleted, _ = Poll.objects.expired().delete() 14 | self.stdout.write(self.style.SUCCESS(f"{polls_deleted} poll(s) deleted")) 15 | -------------------------------------------------------------------------------- /jawanndenn/frontend/src/PollSetup.css: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2025 Sebastian Pipping 2 | ** Licensed under GNU Affero GPL v3 or later 3 | */ 4 | .setup .valid textarea { 5 | background-color: #efe !important; 6 | } 7 | 8 | .setup .invalid textarea { 9 | background-color: #fee !important; 10 | } 11 | 12 | .setup .MuiFormControl-root { 13 | width: 100%; 14 | } 15 | 16 | .setup .MuiCardActions-root { 17 | padding: 16px; 18 | padding-top: 0px; 19 | } 20 | 21 | .setup .MuiCardContent-root { 22 | padding-bottom: 12px; 23 | } 24 | -------------------------------------------------------------------------------- /jawanndenn/frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["DOM", "ES2020"], 4 | "jsx": "react-jsx", 5 | "target": "ES2020", 6 | "noEmit": true, 7 | "skipLibCheck": true, 8 | "useDefineForClassFields": true, 9 | 10 | "module": "ESNext", 11 | "isolatedModules": true, 12 | "resolveJsonModule": true, 13 | "moduleResolution": "bundler", 14 | "allowImportingTsExtensions": true, 15 | 16 | "strict": true, 17 | "noUnusedLocals": true, 18 | "noUnusedParameters": true 19 | }, 20 | "include": ["src"] 21 | } 22 | -------------------------------------------------------------------------------- /jawanndenn/migrations/0002_django_extensions_3_0_0.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1 on 2020-08-15 23:45 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("jawanndenn", "0001_initial"), 9 | ] 10 | 11 | operations = [ 12 | migrations.AlterModelOptions( 13 | name="ballot", 14 | options={"get_latest_by": "modified"}, 15 | ), 16 | migrations.AlterModelOptions( 17 | name="poll", 18 | options={"get_latest_by": "modified"}, 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /jawanndenn/static/favicon/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jawanndenn", 3 | "short_name": "jawanndenn", 4 | "icons": [ 5 | { 6 | "src": "/static/favicon/web-app-manifest-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png", 9 | "purpose": "maskable" 10 | }, 11 | { 12 | "src": "/static/favicon/web-app-manifest-512x512.png", 13 | "sizes": "512x512", 14 | "type": "image/png", 15 | "purpose": "maskable" 16 | } 17 | ], 18 | "theme_color": "#ffffff", 19 | "background_color": "#ffffff", 20 | "display": "standalone" 21 | } 22 | -------------------------------------------------------------------------------- /jawanndenn/static/3rdparty/github-buttons-4.0.1/LICENSE.md: -------------------------------------------------------------------------------- 1 | Licensed under the Apache License, Version 2.0 (the "License"); 2 | you may not use this work except in compliance with the License. 3 | You may obtain a copy of the License in the LICENSE file, or at: 4 | 5 | http://www.apache.org/licenses/LICENSE-2.0 6 | 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | -------------------------------------------------------------------------------- /.github/workflows/dockerignore_detect_out_of_sync.yml: -------------------------------------------------------------------------------- 1 | name: Detect .dockerignore out-of-sync with git ls-files 2 | 3 | on: 4 | pull_request: 5 | push: 6 | schedule: 7 | - cron: '0 16 * * 5' # Every Friday 4pm 8 | workflow_dispatch: 9 | 10 | jobs: 11 | dockerignore_detect_out_of_sync: 12 | name: Detect .dockerignore out-of-sync with git ls-files 13 | runs-on: ubuntu-22.04 14 | steps: 15 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 16 | 17 | - name: Check for out-of-sync .dockerignore 18 | run: |- 19 | diff -U0 <(./generate_whitelist_dockerignore_file.sh) .dockerignore 20 | -------------------------------------------------------------------------------- /jawanndenn/views/tests/test_favicon.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2025 Sebastian Pipping 2 | # Licensed under GNU Affero GPL v3 or later 3 | 4 | from django.http import FileResponse 5 | from django.test import TestCase 6 | from django.urls import reverse 7 | from parameterized import parameterized 8 | 9 | from ..favicon import FAVICON_FILES 10 | 11 | 12 | class FaviconTest(TestCase): 13 | @parameterized.expand(FAVICON_FILES) 14 | def test_file_served_properly(self, path): 15 | url = reverse("favicon", kwargs={"path": path}) 16 | response = self.client.get(url) 17 | self.assertIsInstance(response, FileResponse) 18 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | exclude: '^jawanndenn/static/3rdparty/' 2 | 3 | repos: 4 | - repo: https://github.com/pre-commit/pre-commit-hooks 5 | rev: v6.0.0 6 | hooks: 7 | - id: check-json 8 | - id: check-yaml 9 | - id: check-merge-conflict 10 | - id: end-of-file-fixer 11 | - id: trailing-whitespace 12 | 13 | - repo: https://github.com/Lucas-C/pre-commit-hooks-markup 14 | rev: v1.0.1 15 | hooks: 16 | - id: rst-linter 17 | 18 | - repo: https://github.com/astral-sh/ruff-pre-commit 19 | rev: v0.14.9 20 | hooks: 21 | - id: ruff 22 | args: 23 | - --fix 24 | - id: ruff-format 25 | -------------------------------------------------------------------------------- /jawanndenn/frontend/src/Footer.css: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2025 Sebastian Pipping 2 | ** Licensed under GNU Affero GPL v3 or later 3 | */ 4 | footer { 5 | margin: 0; 6 | background-color: #848484; 7 | padding: 6px 20px 24px 20px; 8 | } 9 | 10 | footer * { 11 | color: #ccc; 12 | } 13 | 14 | footer p { 15 | margin: 0; 16 | text-align: center; 17 | } 18 | 19 | footer a { 20 | color: #ddd; 21 | font-weight: bold; 22 | text-decoration: none; 23 | } 24 | 25 | footer a:hover { 26 | text-decoration: underline; 27 | } 28 | 29 | footer #github-star-button { 30 | position: relative; 31 | top: 5px; 32 | margin-left: 10px; 33 | width: 90px; 34 | } 35 | -------------------------------------------------------------------------------- /jawanndenn/views/security_txt.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024 Sebastian Pipping 2 | # Licensed under GNU Affero GPL v3 or later 3 | 4 | from importlib import resources 5 | 6 | from django.urls import re_path 7 | from django.views.static import serve 8 | 9 | 10 | def security_txt_urlpatterns(name="security_txt"): 11 | return [ 12 | re_path( 13 | "^(?:\\.well-known/)?(?Psecurity\\.txt)$", 14 | serve, 15 | kwargs={ 16 | "document_root": str( 17 | resources.files("jawanndenn").joinpath("static", "well-known") 18 | ), 19 | }, 20 | name=name, 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Django's command-line utility for administrative tasks.""" 3 | 4 | import os 5 | import sys 6 | 7 | 8 | def main(): 9 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "jawanndenn.settings") 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == "__main__": 22 | main() 23 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | 4 | - package-ecosystem: "github-actions" 5 | commit-message: 6 | include: "scope" 7 | prefix: "Actions" 8 | directory: "/" 9 | labels: 10 | - "enhancement" 11 | schedule: 12 | interval: "weekly" 13 | 14 | - package-ecosystem: "pip" 15 | commit-message: 16 | include: "scope" 17 | prefix: "requirements" 18 | directory: "/" 19 | labels: 20 | - "dependencies" 21 | - "enhancement" 22 | schedule: 23 | interval: "daily" 24 | 25 | - package-ecosystem: "npm" 26 | commit-message: 27 | include: "scope" 28 | prefix: "requirements" 29 | directory: "/jawanndenn/frontend/" 30 | labels: 31 | - "dependencies" 32 | - "enhancement" 33 | schedule: 34 | interval: "daily" 35 | -------------------------------------------------------------------------------- /generate_whitelist_dockerignore_file.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | # Copyright (C) 2020 Sebastian Pipping 3 | # Licensed under GNU Affero GPL v3 or later 4 | 5 | cat < .dockerignore 11 | ################################################################################## 12 | 13 | # Ignore everything 14 | * 15 | 16 | # Unignore files based on "git ls-files" 17 | !.coveragerc 18 | EOF 19 | 20 | git ls-files \ 21 | | sed -r \ 22 | -e 's,(^|/)[^.][^/]*(\.[^/]+)$,\1*\2,' \ 23 | -e '/(^|\/)\./d' \ 24 | | sort -u -V \ 25 | | sort -V -f \ 26 | | sed 's,^,!,' 27 | -------------------------------------------------------------------------------- /jawanndenn/views/favicon.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2025 Sebastian Pipping 2 | # Licensed under GNU Affero GPL v3 or later 3 | 4 | import re 5 | from importlib import resources 6 | 7 | from django.urls import re_path 8 | from django.views.static import serve 9 | 10 | FAVICON_FILES = [ 11 | "apple-touch-icon.png", 12 | "favicon-96x96.png", 13 | "favicon.ico", 14 | "favicon.svg", 15 | "site.webmanifest", 16 | "web-app-manifest-192x192.png", 17 | "web-app-manifest-512x512.png", 18 | ] 19 | 20 | _FAVICON_FILES_PATTERN = "|".join(re.escape(filename) for filename in FAVICON_FILES) 21 | 22 | 23 | def favicon_urlpatterns(name="favicon"): 24 | return [ 25 | re_path( 26 | "^(?P%s)$" % _FAVICON_FILES_PATTERN, 27 | serve, 28 | kwargs={ 29 | "document_root": str(resources.files("jawanndenn").joinpath("static", "favicon")), 30 | }, 31 | name=name, 32 | ), 33 | ] 34 | -------------------------------------------------------------------------------- /jawanndenn/frontend/src/dedent.ts: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Sebastian Pipping 2 | // Licensed under GNU Affero GPL v3 or later 3 | 4 | const longestCommonPrefix = (s1: string, s2: string): string => { 5 | const minLength = Math.min(s1.length, s2.length); 6 | 7 | let i = 0; 8 | for (; i < minLength; i++) { 9 | if (s1[i] != s2[i]) { 10 | break; 11 | } 12 | } 13 | 14 | return s1.substring(0, i); 15 | }; 16 | 17 | const indentOf = (line: string): string => { 18 | return line.substring(0, line.length - line.trimStart().length); 19 | }; 20 | 21 | const dedent = (text: string): string => { 22 | const lines = text.split('\n'); 23 | const longestSharedIndent = lines.reduce( 24 | (sharedIndent, line) => 25 | longestCommonPrefix(indentOf(line) + sharedIndent, sharedIndent), 26 | indentOf(lines[0]), 27 | ); 28 | return lines 29 | .map((line) => line.substring(longestSharedIndent.length)) 30 | .join('\n'); 31 | }; 32 | 33 | export default dedent; 34 | -------------------------------------------------------------------------------- /jawanndenn/tests/factories.py: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2019 Sebastian Pipping 2 | # Licensed under GNU Affero GPL v3 or later 3 | 4 | from factory import Sequence, SubFactory 5 | from factory.django import DjangoModelFactory 6 | 7 | from jawanndenn.models import Ballot, Poll, PollOption, Vote 8 | 9 | 10 | class PollFactory(DjangoModelFactory): 11 | class Meta: 12 | model = Poll 13 | 14 | title = Sequence(lambda n: f"Title {n}") 15 | 16 | 17 | class PollOptionFactory(DjangoModelFactory): 18 | class Meta: 19 | model = PollOption 20 | 21 | poll = SubFactory(PollFactory) 22 | position = Sequence(int) 23 | name = Sequence(lambda n: f"Option {n}") 24 | 25 | 26 | class BallotFactory(DjangoModelFactory): 27 | class Meta: 28 | model = Ballot 29 | 30 | poll = SubFactory(PollFactory) 31 | voter_name = Sequence(lambda n: f"User {n}") 32 | 33 | 34 | class VoteFactory(DjangoModelFactory): 35 | class Meta: 36 | model = Vote 37 | 38 | option = SubFactory(PollOptionFactory) 39 | -------------------------------------------------------------------------------- /jawanndenn/frontend/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "frontend", 3 | "version": "1.0.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "build": "rm -fv ../static/{css,js}/* && rsbuild build", 8 | "dev": "rsbuild dev --open", 9 | "format": "prettier --write .", 10 | "lint": "eslint .", 11 | "preview": "rsbuild preview" 12 | }, 13 | "dependencies": { 14 | "@emotion/react": ">=11.14.0", 15 | "@emotion/styled": ">=11.14.1", 16 | "@mui/material": ">=7.3.5", 17 | "react": ">=19.2.0", 18 | "react-dom": ">=19.2.0", 19 | "yaml": ">=2.8.1" 20 | }, 21 | "devDependencies": { 22 | "@eslint/compat": ">=2.0.0", 23 | "@eslint/js": ">=9.39.1", 24 | "@rsbuild/core": ">=1.6.8", 25 | "@rsbuild/plugin-react": ">=1.4.2", 26 | "@types/react": ">=19.2.7", 27 | "@types/react-dom": ">=19.2.3", 28 | "eslint": ">=9.39.1", 29 | "eslint-plugin-react": ">=7.37.4", 30 | "eslint-plugin-react-hooks": ">=7.0.0", 31 | "globals": ">=16.4.0", 32 | "prettier": ">=3.6.2", 33 | "typescript": ">=5.9.3", 34 | "typescript-eslint": ">=8.48.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /jawanndenn/views/tests/test_security_txt.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024 Sebastian Pipping 2 | # Licensed under GNU Affero GPL v3 or later 3 | 4 | from django.http import FileResponse 5 | from django.test import TestCase 6 | from django.urls import reverse_lazy 7 | from parameterized import parameterized 8 | 9 | 10 | class SecurityTxtTest(TestCase): 11 | @parameterized.expand( 12 | [ 13 | ( 14 | "default location", 15 | "/.well-known/security.txt", 16 | ), 17 | ( 18 | "legacy location", 19 | "/security.txt", 20 | ), 21 | ( 22 | "through reverse", 23 | reverse_lazy("security_txt", kwargs={"path": "security.txt"}), 24 | ), 25 | ] 26 | ) 27 | def test_file_served_properly(self, _label, url): 28 | self.assertTrue(url.endswith("/security.txt")) 29 | 30 | response = self.client.get(url) 31 | 32 | self.assertIsInstance(response, FileResponse) 33 | self.assertEqual(response.headers["Content-Type"], "text/plain") 34 | -------------------------------------------------------------------------------- /.github/workflows/run_pre_commit.yml: -------------------------------------------------------------------------------- 1 | name: Run pre-commit on all files 2 | 3 | on: 4 | pull_request: 5 | push: 6 | schedule: 7 | - cron: '0 16 * * 5' # Every Friday 4pm 8 | workflow_dispatch: 9 | 10 | jobs: 11 | run_pre_commit: 12 | name: Run pre-commit on all files 13 | runs-on: ubuntu-22.04 14 | steps: 15 | - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 16 | 17 | - name: Set up Python 3.14 18 | uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 19 | with: 20 | python-version: 3.14 21 | 22 | - name: Install pre-commit 23 | run: |- 24 | pip install \ 25 | --disable-pip-version-check \ 26 | --user \ 27 | --no-warn-script-location \ 28 | pre-commit 29 | echo "PATH=${HOME}/.local/bin:${PATH}" >> "${GITHUB_ENV}" 30 | 31 | - name: Install pre-commit hooks 32 | run: |- 33 | pre-commit install --install-hooks 34 | 35 | - name: Run pre-commit on all files 36 | run: |- 37 | pre-commit run --all-files --show-diff-on-failure 38 | -------------------------------------------------------------------------------- /jawanndenn/views/tests/test_static_files.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019-2024 Sebastian Pipping 2 | # Licensed under GNU Affero GPL v3 or later 3 | 4 | from http import HTTPStatus 5 | 6 | from django.test import TestCase 7 | from django.urls import reverse 8 | from parameterized import parameterized 9 | 10 | 11 | class ServeUsingFindersTest(TestCase): 12 | @parameterized.expand( 13 | [ 14 | # Our app, some arbitrary asset 15 | ("jawanndenn", "well-known/security.txt", "DENY"), 16 | # Our app, asset used in 34 |

35 | 36 | ); 37 | }; 38 | 39 | export default Footer; 40 | -------------------------------------------------------------------------------- /jawanndenn/frontend/src/PollPreview.tsx: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025 Sebastian Pipping 2 | // Licensed under GNU Affero GPL v3 or later 3 | 4 | import { Poll, PollConfig } from './Poll.tsx'; 5 | 6 | const EXAMPLE_PEOPLE = ['Dmitri', 'Jule', 'Vered', 'Matthieu']; 7 | 8 | const randomVoteCache = {}; 9 | let randomVotesAny = 0; 10 | let randomVotesNull = 0; 11 | 12 | const getCachedRandomVote = (person, option) => { 13 | const key = `${person}@${option}`; 14 | let value: bool | undefined = randomVoteCache[key]; 15 | if (value === undefined) { 16 | const commonCoiceCount = 4; 17 | const forceOneMaybeAfter = (EXAMPLE_PEOPLE.length * commonCoiceCount) / 2; 18 | if (randomVotesAny > forceOneMaybeAfter && randomVotesNull == 0) { 19 | value = null; 20 | } else { 21 | const zeroToOne = Math.random(); 22 | value = zeroToOne > 0.95 ? null : zeroToOne > 0.95 / 2 ? true : false; 23 | } 24 | 25 | randomVotesAny += 1; 26 | if (value === null) { 27 | randomVotesNull += 1; 28 | } 29 | 30 | randomVoteCache[key] = value; 31 | } 32 | return value; 33 | }; 34 | 35 | const PollPreview = ({ config }: { config: PollConfig }) => { 36 | const votes = EXAMPLE_PEOPLE.map((person, personIndex) => [ 37 | person, 38 | config.options.map((_option, optionIndex) => 39 | getCachedRandomVote(personIndex, optionIndex), 40 | ), 41 | ]); 42 | 43 | return ; 44 | }; 45 | 46 | export default PollPreview; 47 | -------------------------------------------------------------------------------- /jawanndenn/views/static_files.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2019-2024 Sebastian Pipping 2 | # Licensed under GNU Affero GPL v3 or later 3 | 4 | import re 5 | 6 | from django.conf import settings 7 | from django.contrib.staticfiles.views import serve 8 | from django.urls import re_path 9 | 10 | 11 | def _serve_with_headers_fixed(request, path, insecure=False, **kwargs): 12 | response = serve(request, path, insecure=insecure, **kwargs) 13 | 14 | # Allow loading of github-btn.html in an