This commit is contained in:
@@ -4,6 +4,7 @@ DJANGO_DEBUG=1
|
|||||||
DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1
|
DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1
|
||||||
DJANGO_CSRF_TRUSTED_ORIGINS=http://localhost:1226
|
DJANGO_CSRF_TRUSTED_ORIGINS=http://localhost:1226
|
||||||
DJANGO_TIME_ZONE=Europe/Brussels
|
DJANGO_TIME_ZONE=Europe/Brussels
|
||||||
|
VACATURERADAR_OWNER_NAME=Jens
|
||||||
|
|
||||||
# Gebruik DATABASE_URL niet voor SQLite. Laat leeg voor lokale sqlite-ontwikkeling.
|
# Gebruik DATABASE_URL niet voor SQLite. Laat leeg voor lokale sqlite-ontwikkeling.
|
||||||
POSTGRES_DB=vacatureradar
|
POSTGRES_DB=vacatureradar
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ Alle betekenisvolle wijzigingen worden hier bijgehouden. Het project volgt voorl
|
|||||||
|
|
||||||
### Gewijzigd
|
### Gewijzigd
|
||||||
|
|
||||||
|
- De ultrawide cockpit gebruikt één links verankerd grid tot 2800 px; headers, filters, pipeline, KPI's en detailpanelen delen daardoor op brede schermen hetzelfde startpunt zonder toevallige lege linkerkolom.
|
||||||
|
- De officiële ITWorx.tech-wordmark en het cloud-check-symbool uit het door de eigenaar aangeleverde asset pack vormen nu de merklaag van sidebar, bovenbalk, login, favicon en Dockermanicoon; VacatureRadar blijft zichtbaar als productnaam.
|
||||||
|
- VacatureRadar gebruikt nu één scherper radarbeeldmerk voor favicon, login en applicatieshell; de persoonlijke eigenaar is via `VACATURERADAR_OWNER_NAME` configureerbaar.
|
||||||
|
- De bovenbalk geeft naast zoeken ook eigenaar en actuele werkcontext aan; navigatie-, focus- en hoverstates zijn verfijnd zonder de compacte mobiele cockpit te verzwaren.
|
||||||
- Het zoekprofiel bevat een lokale interactieve radarillustratie met pointerparallax, een rustige scansweep, light/dark-kleuren en een statische reduced-motionvariant; de illustratie is decoratief en introduceert geen fictieve data.
|
- Het zoekprofiel bevat een lokale interactieve radarillustratie met pointerparallax, een rustige scansweep, light/dark-kleuren en een statische reduced-motionvariant; de illustratie is decoratief en introduceert geen fictieve data.
|
||||||
- De Unraid-heruitrol gebruikt een gevalideerde SSH-hostalias met afzonderlijke deploysleutel en voert synchronisatie, build, healthwait en readiness-smoke als één reproduceerbaar commando uit.
|
- De Unraid-heruitrol gebruikt een gevalideerde SSH-hostalias met afzonderlijke deploysleutel en voert synchronisatie, build, healthwait en readiness-smoke als één reproduceerbaar commando uit.
|
||||||
- De cockpit heeft een premium “calm intelligence”-laag met zachtere oppervlaktescheidingen, selectief cyan, humane navigatietypografie en een duidelijkere componenthiërarchie in donker en licht thema.
|
- De cockpit heeft een premium “calm intelligence”-laag met zachtere oppervlaktescheidingen, selectief cyan, humane navigatietypografie en een duidelijkere componenthiërarchie in donker en licht thema.
|
||||||
@@ -14,6 +18,7 @@ Alle betekenisvolle wijzigingen worden hier bijgehouden. Het project volgt voorl
|
|||||||
|
|
||||||
### Hersteld
|
### Hersteld
|
||||||
|
|
||||||
|
- De Unraid-synchelper negeert verwijderde indexpaden bij een release vanuit een geldige dirty worktree; vervangen merkassets blokkeren de archiefopbouw daardoor niet meer.
|
||||||
- Rechtstreekse SSH naar het Unraid-IP koos lokaal de verkeerde gebruiker en identiteit; het gedocumenteerde aliasprofiel selecteert nu reproduceerbaar `root` met de afzonderlijke deploysleutel.
|
- Rechtstreekse SSH naar het Unraid-IP koos lokaal de verkeerde gebruiker en identiteit; het gedocumenteerde aliasprofiel selecteert nu reproduceerbaar `root` met de afzonderlijke deploysleutel.
|
||||||
- Inloginteracties laden nu als lokale externe JavaScriptasset; de eigen Content Security Policy blokkeert wachtwoordweergave en submitfeedback niet langer.
|
- Inloginteracties laden nu als lokale externe JavaScriptasset; de eigen Content Security Policy blokkeert wachtwoordweergave en submitfeedback niet langer.
|
||||||
- Het Unraid/Dockerman-containericoon gebruikt nu een lokale 256×256 PNG via de gepubliceerde webpoort in plaats van de fragiele SVG-favicon-URL.
|
- Het Unraid/Dockerman-containericoon gebruikt nu een lokale 256×256 PNG via de gepubliceerde webpoort in plaats van de fragiele SVG-favicon-URL.
|
||||||
|
|||||||
@@ -2,15 +2,36 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
|
|
||||||
from apps.profiles.models import SearchProfile
|
from apps.profiles.models import SearchProfile
|
||||||
|
|
||||||
|
|
||||||
def navigation_context(request: HttpRequest) -> dict[str, Any]:
|
def navigation_context(request: HttpRequest) -> dict[str, Any]:
|
||||||
|
match = request.resolver_match
|
||||||
|
route_key = (match.namespace, match.url_name) if match else (None, None)
|
||||||
|
page_contexts = {
|
||||||
|
("dashboard", "today"): "Dagoverzicht",
|
||||||
|
("dashboard", "system"): "Automatisering",
|
||||||
|
("jobs", "list"): "Vacatureverkenner",
|
||||||
|
("jobs", "detail"): "Vacatureanalyse",
|
||||||
|
("jobs", "applications"): "Sollicitatiepipeline",
|
||||||
|
("jobs", "application-edit"): "Sollicitatiedossier",
|
||||||
|
("jobs", "skill-insights"): "Skillsradar",
|
||||||
|
("jobs", "activity"): "Activiteit",
|
||||||
|
("jobs", "employers"): "Werkgevers",
|
||||||
|
("jobs", "employer-detail"): "Werkgeveranalyse",
|
||||||
|
("profiles", "list"): "Zoekprofiel",
|
||||||
|
("profiles", "edit"): "Radarconfiguratie",
|
||||||
|
("sources", "list"): "Bronbeheer",
|
||||||
|
}
|
||||||
context = {
|
context = {
|
||||||
"app_name": "VacatureRadar",
|
"app_name": "VacatureRadar",
|
||||||
"app_version": "0.3.0",
|
"app_version": "0.3.3",
|
||||||
|
"app_brand_name": "ITWorx.tech",
|
||||||
|
"app_owner_name": settings.VACATURERADAR_OWNER_NAME,
|
||||||
|
"page_context_label": page_contexts.get(route_key, "Persoonlijke cockpit"),
|
||||||
}
|
}
|
||||||
if request.user.is_authenticated:
|
if request.user.is_authenticated:
|
||||||
context["navigation_profile"] = (
|
context["navigation_profile"] = (
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ DEBUG = env_bool("DJANGO_DEBUG", True)
|
|||||||
ALLOWED_HOSTS = env_list("DJANGO_ALLOWED_HOSTS", "localhost,127.0.0.1,testserver")
|
ALLOWED_HOSTS = env_list("DJANGO_ALLOWED_HOSTS", "localhost,127.0.0.1,testserver")
|
||||||
CSRF_TRUSTED_ORIGINS = env_list("DJANGO_CSRF_TRUSTED_ORIGINS")
|
CSRF_TRUSTED_ORIGINS = env_list("DJANGO_CSRF_TRUSTED_ORIGINS")
|
||||||
TIME_ZONE = os.getenv("DJANGO_TIME_ZONE", "Europe/Brussels")
|
TIME_ZONE = os.getenv("DJANGO_TIME_ZONE", "Europe/Brussels")
|
||||||
|
VACATURERADAR_OWNER_NAME = os.getenv("VACATURERADAR_OWNER_NAME", "Jens").strip()[:40] or "Jens"
|
||||||
LANGUAGE_CODE = "nl-be"
|
LANGUAGE_CODE = "nl-be"
|
||||||
USE_I18N = True
|
USE_I18N = True
|
||||||
USE_TZ = True
|
USE_TZ = True
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ from apps.core.views import (
|
|||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path(
|
path(
|
||||||
"favicon.ico",
|
"favicon.ico",
|
||||||
RedirectView.as_view(url=static_url("favicon.svg"), permanent=True),
|
RedirectView.as_view(url=static_url("img/itworx-app-icon.png"), permanent=True),
|
||||||
name="favicon",
|
name="favicon",
|
||||||
),
|
),
|
||||||
path("admin/", admin.site.urls),
|
path("admin/", admin.site.urls),
|
||||||
|
|||||||
@@ -1880,6 +1880,120 @@ tasks:
|
|||||||
fail-fast deployhelper toegevoegd. Interactieve lokale SVG-radar met pointerparallax, dark/light en reduced-motionfallback
|
fail-fast deployhelper toegevoegd. Interactieve lokale SVG-radar met pointerparallax, dark/light en reduced-motionfallback
|
||||||
toegevoegd. Browsermatrix 390/1280 zonder overflow of consolefouten; 265 tests groen. Live image sha256:4d30e01e778777d5a2cde4339a9b2ad006edb25cae387293737420152d65069d
|
toegevoegd. Browsermatrix 390/1280 zonder overflow of consolefouten; 265 tests groen. Live image sha256:4d30e01e778777d5a2cde4339a9b2ad006edb25cae387293737420152d65069d
|
||||||
healthy en readiness/CSS/JS HTTP 200.
|
healthy en readiness/CSS/JS HTTP 200.
|
||||||
|
- id: VR-218
|
||||||
|
title: Personaliseer merkidentiteit en verfijn de globale UX
|
||||||
|
status: done
|
||||||
|
priority: P1
|
||||||
|
requirement_ids:
|
||||||
|
- NFR-004
|
||||||
|
- NFR-008
|
||||||
|
- NFR-009
|
||||||
|
depends_on:
|
||||||
|
- VR-217
|
||||||
|
summary: Vervang het generieke favicon door een herkenbaar radarsymbool, voeg configureerbare eigenaarssignatuur
|
||||||
|
toe en verfijn shell, oriëntatie, navigatie en micro-interacties tot een coherente persoonlijke premiumervaring.
|
||||||
|
acceptance_criteria:
|
||||||
|
- Favicon en hoofdlogo delen één scherp, lokaal en op 16 px herkenbaar radarsymbool met passende light/dark browsermetadata
|
||||||
|
en zonder externe assets.
|
||||||
|
- De shell en authenticatieschermen tonen VacatureRadar als product en een configureerbare eigenaarssignatuur
|
||||||
|
met veilige standaardwaarde Jens; deze branding wordt niet uit gebruikersdata of nepdata afgeleid.
|
||||||
|
- De topbar geeft compacte paginaoriëntatie, navigatie-/zoekinteracties hebben duidelijkere focus- en hoverstates
|
||||||
|
en mobiele bruikbaarheid blijft intact zonder extra bediening of JavaScriptafhankelijkheid.
|
||||||
|
- Browsercontrole op dashboard, verkenner, profiel en login bij 390 en 1280 px in donker en licht thema toont
|
||||||
|
geen overflow, consolefout of onduidelijke hiërarchie; live container en assets zijn healthy na deployment.
|
||||||
|
verification:
|
||||||
|
- uv run pytest tests/e2e/test_vr114_browser_and_accessibility.py tests/integration/test_auth_login.py tests/integration/test_views.py
|
||||||
|
- Browsermatrix 390x844 en 1280x800 in donker en licht thema
|
||||||
|
- Live favicon-, logo-, readiness- en containerhealth-smoke
|
||||||
|
- ./scripts/codex_verify.sh
|
||||||
|
primary_paths:
|
||||||
|
- apps/core/context_processors.py
|
||||||
|
- static/favicon.svg
|
||||||
|
- static/img/vacatureradar-logo.svg
|
||||||
|
- templates/base.html
|
||||||
|
- templates/registration
|
||||||
|
- static/css/premium.css
|
||||||
|
- static/css/auth.css
|
||||||
|
result:
|
||||||
|
completed_at: '2026-07-26'
|
||||||
|
note: Persoonlijke Jens-branding, vernieuwd radarbeeldmerk en favicon, contextuele bovenbalk en verfijnde navigatie/zoekfocus
|
||||||
|
zijn regressiegedekt, responsief in de browser gevalideerd en live uitgerold als healthy image sha256:5f25f00c9b7efb166587901ff39b02c56c98fb9946ddef0a4546a22f18dc0802.
|
||||||
|
- id: VR-219
|
||||||
|
title: Herstel ultrawide uitlijning en versterk persoonlijke merklock-up
|
||||||
|
status: done
|
||||||
|
priority: P1
|
||||||
|
requirement_ids:
|
||||||
|
- NFR-004
|
||||||
|
- NFR-008
|
||||||
|
depends_on:
|
||||||
|
- VR-218
|
||||||
|
summary: Breng de cockpit op brede schermen terug naar één voorspelbaar horizontaal grid en maak de persoonlijke
|
||||||
|
Jens-signatuur tot een herkenbaar onderdeel van de productbranding in plaats van losse metadata.
|
||||||
|
acceptance_criteria:
|
||||||
|
- Header, filters, hoofdpanelen en onderliggende secties delen op desktop en ultrawide hetzelfde startpunt en
|
||||||
|
dezelfde contentbreedte; er ontstaat geen grote toevallige lege linkerkolom.
|
||||||
|
- Verkenner en automatisering benutten 1920- en 3840-pixelbreedtes evenwichtig zonder uitgerekte leesregels, losgekoppelde
|
||||||
|
panelen of documentoverflow.
|
||||||
|
- Sidebar en bovenbalk tonen één consistente VacatureRadar-by-Jens-merklock-up; authenticatie en mobiele shell
|
||||||
|
behouden dezelfde eigenaarssignatuur zonder gebruikersnaam als merk te presenteren.
|
||||||
|
- Browsercontrole op 390, 1280, 1920 en 3840 px bevestigt consistente ankers, bruikbare paneelverhoudingen, schone
|
||||||
|
console en intacte toetsenbord-/mobiele flows.
|
||||||
|
verification:
|
||||||
|
- Browsermatrix dashboard, verkenner, automatisering en login op 390/1280/1920/3840 px
|
||||||
|
- uv run pytest tests/integration/test_auth_login.py tests/integration/test_views.py
|
||||||
|
- ./scripts/codex_verify.sh
|
||||||
|
primary_paths:
|
||||||
|
- templates/base.html
|
||||||
|
- static/css/layout.css
|
||||||
|
- static/css/premium.css
|
||||||
|
- static/css/responsive.css
|
||||||
|
result:
|
||||||
|
completed_at: '2026-07-26'
|
||||||
|
note: Ultrawide hoofdsecties delen één links verankerd 2800px-grid; explorer- en automationverhoudingen zijn
|
||||||
|
begrensd en Personal intelligence by Jens is de consistente lock-up. Browsermatrix 390/1280/1920/3840 schoon;
|
||||||
|
267 tests groen; live image sha256:86836f82cc543a7adb414e47b9667e9123bb9ceba10d629a53086273aaaae03f healthy
|
||||||
|
met readiness en asset-smokes.
|
||||||
|
- id: VR-220
|
||||||
|
title: Integreer de officiële ITWorx-merkidentiteit
|
||||||
|
status: done
|
||||||
|
priority: P1
|
||||||
|
requirement_ids:
|
||||||
|
- NFR-004
|
||||||
|
- NFR-008
|
||||||
|
- NFR-009
|
||||||
|
depends_on:
|
||||||
|
- VR-219
|
||||||
|
summary: Vervang de tijdelijke tekstuele Jens-branding door de door de eigenaar aangeleverde officiële ITWorx.tech-wordmark
|
||||||
|
en cloud-check-identiteit, met VacatureRadar herkenbaar als product binnen dat merk.
|
||||||
|
acceptance_criteria:
|
||||||
|
- Sidebar, login en herstelpagina's gebruiken de transparante officiële ITWorx.tech-wordmark uit het aangeleverde
|
||||||
|
asset pack; VacatureRadar blijft duidelijk als productnaam aanwezig.
|
||||||
|
- Browserfavicon en app-/Dockericoon gebruiken de officiële cloud-check-symboliek in een compacte transparante,
|
||||||
|
lokaal gehoste en voor klein formaat geoptimaliseerde variant.
|
||||||
|
- Merkassets hebben betekenisvolle alt-/toegankelijkheidslabels, laden zonder externe runtimebron en blijven scherp
|
||||||
|
en leesbaar in donker/licht thema en op mobiel.
|
||||||
|
- Browsercontrole op login, dashboard en verkenner bij 390, 1280 en 1920 px toont correcte assets, geen overflow
|
||||||
|
of consolefouten; de live container levert brandingassets en readiness met HTTP 200.
|
||||||
|
verification:
|
||||||
|
- Controleer afmetingen, transparantie en bestandsgrootte van de afgeleide merkassets
|
||||||
|
- uv run pytest tests/integration/test_auth_login.py tests/integration/test_views.py tests/unit/test_deployment_configuration.py
|
||||||
|
- Browsermatrix 390/1280/1920 voor login, dashboard en verkenner
|
||||||
|
- Live asset-, favicon-, readiness- en containerhealth-smoke
|
||||||
|
- ./scripts/codex_verify.sh
|
||||||
|
primary_paths:
|
||||||
|
- static/img/itworx-wordmark.png
|
||||||
|
- static/img/itworx-app-icon.png
|
||||||
|
- static/img/vacatureradar-docker.png
|
||||||
|
- templates/base.html
|
||||||
|
- templates/registration
|
||||||
|
- static/css/premium.css
|
||||||
|
- static/css/auth.css
|
||||||
|
result:
|
||||||
|
completed_at: '2026-07-26'
|
||||||
|
note: Officiële aangeleverde ITWorx.tech-wordmark geïntegreerd in sidebar, topbar, login en herstel; cloud-check
|
||||||
|
exact afgeleid voor 512px favicon/app-icon en 256px Dockermanicoon. Browsermatrix 390/1280/1920 schoon, 267
|
||||||
|
tests groen en live image sha256:daf34407813b37cdf2d0fc65a482ded65375f89eedd3f0144a8c0ce206d41565 healthy
|
||||||
|
met readiness/PNG-smokes.
|
||||||
- id: VR-301
|
- id: VR-301
|
||||||
title: Multi-tenant SaaS, teams en billing
|
title: Multi-tenant SaaS, teams en billing
|
||||||
status: deferred
|
status: deferred
|
||||||
|
|||||||
@@ -34,6 +34,34 @@ Het volledige scherm- en afwijkingsrapport staat in `docs/design/STITCH_INTEGRAT
|
|||||||
|
|
||||||
## Laatste onderhoudsaudit
|
## Laatste onderhoudsaudit
|
||||||
|
|
||||||
|
VR-220 op 2026-07-26:
|
||||||
|
|
||||||
|
- “eigen branding” is gecorrigeerd naar de door de eigenaar aangeleverde officiële ITWorx.tech-identiteit in plaats van een tijdelijke tekstuele Jens-signatuur;
|
||||||
|
- sidebar, bovenbalk, login en wachtwoordherstel gebruiken de transparante opgeschoonde ITWorx.tech-wordmark; VacatureRadar blijft herkenbaar als product en intelligence cockpit;
|
||||||
|
- favicon/app-icon (512×512) en Dockermanicoon (256×256) zijn exact uit het officiële cloud-check-symbool gecropt en Lanczos geschaald, zonder generatieve wijziging;
|
||||||
|
- merkassets zijn lokaal, transparant, geoptimaliseerd en met herkomst vastgelegd in `static/img/README.md`;
|
||||||
|
- browsercontrole op 390, 1280 en 1920 px toont correcte assets, geen overflow en een schone console; 29 gerichte regressies en de volledige gate zijn groen met 267 geslaagde tests, 2 optionele skips en 83,45% branch-aware dekking;
|
||||||
|
- de deployhelper negeert nu veilig verwijderde indexpaden; de twee vervangen SVG-assets zijn expliciet uit de gevalideerde remote sourceboom verwijderd en de uiteindelijke image bevat 147 in plaats van 149 static files;
|
||||||
|
- live image `sha256:daf34407813b37cdf2d0fc65a482ded65375f89eedd3f0144a8c0ce206d41565` via `unraid-itworx` uitgerold; container healthy, readiness HTTP 200 en wordmark-, app-icon- en Dockermanassets leveren `image/png` met HTTP 200. Volgende uitvoerbare taak: geen.
|
||||||
|
|
||||||
|
VR-219 op 2026-07-26:
|
||||||
|
|
||||||
|
- de door gebruikersscreenshots aangetoonde ultrawide-uitlijningsfout is hersteld: directe hoofdsecties zijn niet langer afzonderlijk gecentreerd op 1860 px, maar delen één links verankerd grid tot 2800 px;
|
||||||
|
- op 3840 px beginnen heading, filters, explorer, systeemstatus, pipeline, KPI's en automationdetail op x=296; dezelfde gridbreedte schaalt zonder overflow naar 1920, 1280 en 390 px;
|
||||||
|
- de resultatenkolom en automationlograil hebben begrensde ultrawide-verhoudingen zodat primaire inhoud niet onnodig uitrekt;
|
||||||
|
- sidebar, bovenbalk, login en herstelpagina's gebruiken consistent `Personal intelligence by Jens` en `Jens Intelligence`, los van de accountgebruikersnaam;
|
||||||
|
- browsermatrix schoon zonder consolewaarschuwingen; gerichte regressies 23 tests groen en volledige gate groen met 267 geslaagde tests, 2 optionele skips en 83,45% branch-aware dekking;
|
||||||
|
- live image `sha256:86836f82cc543a7adb414e47b9667e9123bb9ceba10d629a53086273aaaae03f` via `unraid-itworx` uitgerold; container healthy, readiness HTTP 200 en de nieuwe branding plus 2800px-grid-CSS live gevalideerd. Volgende uitvoerbare taak: geen.
|
||||||
|
|
||||||
|
VR-218 op 2026-07-26:
|
||||||
|
|
||||||
|
- favicon, login en applicatieshell delen één verfijnd lokaal radarbeeldmerk met een sterker silhouet op klein formaat;
|
||||||
|
- de persoonlijke signatuur `Jens · private intelligence` is zichtbaar op publieke en ingelogde schermen en via `VACATURERADAR_OWNER_NAME` configureerbaar;
|
||||||
|
- de desktopbovenbalk toont eigenaar plus actuele routecontext; navigatie- en zoekfocus zijn verfijnd en de aanvullende context verdwijnt doelbewust op mobiel;
|
||||||
|
- gerichte regressies: Ruff groen, 29 tests geslaagd en 2 optionele skips; browsercontrole van dashboard, verkenner, profiel en login op 1280×850 en 390×844 zonder documentoverflow of consolewaarschuwingen;
|
||||||
|
- live image `sha256:5f25f00c9b7efb166587901ff39b02c56c98fb9946ddef0a4546a22f18dc0802` via `unraid-itworx` uitgerold; container healthy, readiness HTTP 200 en persoonlijke loginbranding plus SVG-favicon live gevalideerd;
|
||||||
|
- volledige gate groen met 266 geslaagde tests, 2 optionele skips en 83,45% branch-aware dekking; volgende uitvoerbare taak: geen, alleen bestaande externe blokkades en uitgestelde productkeuzes resteren.
|
||||||
|
|
||||||
VR-217 op 2026-07-26:
|
VR-217 op 2026-07-26:
|
||||||
|
|
||||||
- de vermeende Unraid-authenticatiefout bleek een clientprofielkeuze: rechtstreeks IP gebruikte gebruiker `jens`, terwijl `unraid-itworx` correct `root`, `IdentitiesOnly` en de afzonderlijke deploysleutel selecteert;
|
- de vermeende Unraid-authenticatiefout bleek een clientprofielkeuze: rechtstreeks IP gebruikte gebruiker `jens`, terwijl `unraid-itworx` correct `root`, `IdentitiesOnly` en de afzonderlijke deploysleutel selecteert;
|
||||||
|
|||||||
@@ -104,3 +104,21 @@ De geïntegreerde browsercontrole dekte dashboard, verkenner, pipeline en profie
|
|||||||
### Interactieve illustratielaag
|
### Interactieve illustratielaag
|
||||||
|
|
||||||
Het zoekprofiel gebruikt een herbruikbare lokale SVG-radar als projectillustratie. Scan, signalen en orbitale details bewegen langzaam; pointerbeweging geeft maximaal tien pixels parallax. De visual is `aria-hidden`, bevat geen metric of statusclaim en laat alle profielinformatie en acties zelfstandig intact. Zonder JavaScript blijft de compositie bruikbaar en `prefers-reduced-motion: reduce` verwijdert animatie en parallax volledig. Op 390 px staat de illustratie onder de primaire profielactie, zodat zij de kernflow niet uit de eerste leesvolgorde verdringt.
|
Het zoekprofiel gebruikt een herbruikbare lokale SVG-radar als projectillustratie. Scan, signalen en orbitale details bewegen langzaam; pointerbeweging geeft maximaal tien pixels parallax. De visual is `aria-hidden`, bevat geen metric of statusclaim en laat alle profielinformatie en acties zelfstandig intact. Zonder JavaScript blijft de compositie bruikbaar en `prefers-reduced-motion: reduce` verwijdert animatie en parallax volledig. Op 390 px staat de illustratie onder de primaire profielactie, zodat zij de kernflow niet uit de eerste leesvolgorde verdringt.
|
||||||
|
|
||||||
|
## Persoonlijke merklaag (VR-218)
|
||||||
|
|
||||||
|
Favicon, login en shell gebruiken één compact radarbeeldmerk met een donker fundament, cyan scansignaal en emerald detectiepunt. De tekstsignatuur noemt standaard `Jens · private intelligence`; `VACATURERADAR_OWNER_NAME` maakt deze eigenaar expliciet configureerbaar zonder templatefork. De bovenbalk combineert eigenaar en routecontext met de bestaande zoekactie, zodat gebruikers sneller herkennen in welke werkruimte en flow zij zich bevinden.
|
||||||
|
|
||||||
|
De actieve navigatie, merklock-up en zoekfocus hebben preciezere gewicht-, contrast- en motionstates gekregen. Op smalle viewports verdwijnt de aanvullende werkruimtecontext zodat zoeken en primaire navigatie voorrang houden. De browsercontrole van dashboard, verkenner, profiel en login op 1280×850 en 390×844 bevestigt een schone console, geladen lokale assets en geen documentoverflow.
|
||||||
|
|
||||||
|
## Ultrawide gridcorrectie (VR-219)
|
||||||
|
|
||||||
|
De eerdere premiumlaag centreerde ieder direct hoofdonderdeel afzonderlijk op maximaal 1860 px. Op een 3840-pixelviewport ontstond daardoor links van de inhoud ruim 1100 px lege ruimte, terwijl de vaste bovenbalk een ander anker gebruikte. Alle directe hoofdsecties delen nu één links verankerde contentzone van maximaal 2800 px. Op 3840 px beginnen heading, filters, explorer, systeemstatus, pipeline, KPI's en automationdetail exact op x=296; op 1920 px vullen zij de beschikbare 1576 px en op 390 px de beschikbare 350 px.
|
||||||
|
|
||||||
|
De verkenner begrenst zijn resultatenkolom op ultrawide tot 880 px en geeft de resterende ruimte aan vacature-intelligence. De automationlograil blijft tussen 340 en 430 px, zodat tabellen en logs een voorspelbare verhouding houden. De merklock-up is tegelijk geharmoniseerd tot `VacatureRadar — Personal intelligence by Jens` en de desktopwerkruimte tot `Jens Intelligence`; login en herstelpagina's gebruiken dezelfde eigenaarssignatuur.
|
||||||
|
|
||||||
|
## Officiële ITWorx-merklaag (VR-220)
|
||||||
|
|
||||||
|
De projecteigenaar verduidelijkte dat “eigen branding” verwijst naar de officiële ITWorx.tech-identiteit. De tijdelijke tekstuele Jens-lock-up is daarom vervangen door de transparante, opgeschoonde wordmark uit het aangeleverde `ITWorx_Logo_Asset_Pack_2026-07-25.zip`. In de sidebar staat ITWorx.tech als hoofdmerk met `VacatureRadar · intelligence cockpit` als productdescriptor; de bovenbalk combineert ITWorx.tech met de bestaande routecontext. Login en wachtwoordherstel tonen eerst de officiële wordmark en vervolgens VacatureRadar als product.
|
||||||
|
|
||||||
|
Het favicon/app-icon en Dockermanicoon zijn deterministische crops van het cloud-check-symbool uit dezelfde goedgekeurde wordmark, op respectievelijk 512×512 en 256×256. Er is geen nieuw beeldmerk gegenereerd of nagetekend. Alle assets zijn lokaal, transparant en gedocumenteerd in `static/img/README.md`. De browsermatrix op 390, 1280 en 1920 px bevestigt correcte wordmarkverhoudingen, geladen PNG-assets, geen documentoverflow en een schone console.
|
||||||
|
|||||||
@@ -63,8 +63,8 @@ Legenda: **I** = geïmplementeerd en getest in de huidige MVP; **P** = gedeeltel
|
|||||||
| NFR-005 | I | domeinapps/services/adapters/ADRs | continue review |
|
| NFR-005 | I | domeinapps/services/adapters/ADRs | continue review |
|
||||||
| NFR-006 | I | offline pytest + coveragegate | VR-114 verbreedt e2e |
|
| NFR-006 | I | offline pytest + coveragegate | VR-114 verbreedt e2e |
|
||||||
| NFR-007 | P | `scripts/benchmark.py`, `tests/benchmark/test_benchmark.py` | VR-116 |
|
| NFR-007 | P | `scripts/benchmark.py`, `tests/benchmark/test_benchmark.py` | VR-116 |
|
||||||
| NFR-008 | I | volledige negen-schermen-Stitch-cockpit, acht viewports, dark/light, toetsenborddrawer, premium visuele hiërarchie en toegankelijke interactieve radarillustratie | `tests/e2e/test_vr114_browser_and_accessibility.py`, `tests/integration/test_intelligence_views.py`, `artifacts/visual-validation/`, VR-209–213, VR-216/217 |
|
| NFR-008 | I | volledige negen-schermen-Stitch-cockpit, acht viewports, dark/light, toetsenborddrawer, premium visuele hiërarchie, officiële lokale ITWorx.tech-merklaag en toegankelijke interactieve radarillustratie | `tests/e2e/test_vr114_browser_and_accessibility.py`, `tests/integration/test_intelligence_views.py`, `tests/integration/test_views.py`, `artifacts/visual-validation/`, VR-209–213, VR-216–220 |
|
||||||
| NFR-009 | I | lokale SQLite, Docker/Unraidconfig, gevalideerde SSH-deployalias, release-smoke en restore | VR-117 en VR-217 afgerond |
|
| NFR-009 | I | lokale SQLite, configureerbare eigenaarbranding, Docker/Unraidconfig, gevalideerde SSH-deployalias, release-smoke en restore | `tests/unit/test_deployment_configuration.py`, VR-117, VR-217/218 afgerond |
|
||||||
| NFR-010 | I | `apps/sources/services/health.py`, `apps/sources/tasks.py`, `apps/core/views.py`, `config/settings.py` | `tests/integration/test_source_health.py` | VR-112 observability |
|
| NFR-010 | I | `apps/sources/services/health.py`, `apps/sources/tasks.py`, `apps/core/views.py`, `config/settings.py` | `tests/integration/test_source_health.py` | VR-112 observability |
|
||||||
|
|
||||||
## Systeemacceptatie
|
## Systeemacceptatie
|
||||||
@@ -106,3 +106,6 @@ Iedere backlogtaak die een requirement wijzigt, werkt in dezelfde commit deze ma
|
|||||||
- VR-215 corrigeert het Dockerman-downloadcontract: het icoonlabel gebruikt een concrete loopback-URL omdat Dockerman placeholders alleen voor WebUI resolveert; live bewijs omvat de aangemaakte `VacatureRadar-icon.png`-cache.
|
- VR-215 corrigeert het Dockerman-downloadcontract: het icoonlabel gebruikt een concrete loopback-URL omdat Dockerman placeholders alleen voor WebUI resolveert; live bewijs omvat de aangemaakte `VacatureRadar-icon.png`-cache.
|
||||||
- VR-216 verfijnt de Stitch-cockpit naar “calm intelligence”: minder visuele ruis, selectief cyan, compactere mobiele KPI's, responsieve filters, intern scrollende pipeline en een CSP-veilige logininteractie.
|
- VR-216 verfijnt de Stitch-cockpit naar “calm intelligence”: minder visuele ruis, selectief cyan, compactere mobiele KPI's, responsieve filters, intern scrollende pipeline en een CSP-veilige logininteractie.
|
||||||
- VR-217 borgt de werkende Unraid-hostalias en afzonderlijke deploysleutel in een fail-fast releasehelper en voegt een lokale decoratieve radarillustratie met pointerrespons en reduced-motionfallback toe.
|
- VR-217 borgt de werkende Unraid-hostalias en afzonderlijke deploysleutel in een fail-fast releasehelper en voegt een lokale decoratieve radarillustratie met pointerrespons en reduced-motionfallback toe.
|
||||||
|
- VR-218 verenigt favicon, login en shell onder één radarbeeldmerk, maakt de persoonlijke eigenaarssignatuur configureerbaar en voegt contextuele oriëntatie aan de bovenbalk toe zonder mobiele overflow.
|
||||||
|
- VR-219 verankert alle hoofdsecties op één ultrawide grid, begrenst paneelverhoudingen voor leesbaarheid en maakt `Personal intelligence by Jens` tot de consistente productlock-up op publieke en ingelogde schermen.
|
||||||
|
- VR-220 vervangt die tijdelijke tekstlock-up door de aangeleverde officiële ITWorx.tech-wordmark en een exact daaruit afgeleid cloud-check-appicoon voor browser, shell en Dockerman; VacatureRadar blijft de productnaam.
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ fi
|
|||||||
ssh -o BatchMode=yes -o ConnectTimeout=8 "$unraid_host" "test \"\$(id -un)\" = root && docker info >/dev/null"
|
ssh -o BatchMode=yes -o ConnectTimeout=8 "$unraid_host" "test \"\$(id -un)\" = root && docker info >/dev/null"
|
||||||
|
|
||||||
git ls-files --cached --others --exclude-standard -z \
|
git ls-files --cached --others --exclude-standard -z \
|
||||||
|
| while IFS= read -r -d '' tracked_path; do
|
||||||
|
[[ -e "$tracked_path" ]] && printf '%s\0' "$tracked_path"
|
||||||
|
done \
|
||||||
| tar --null --files-from=- --create --gzip --file="$local_archive"
|
| tar --null --files-from=- --create --gzip --file="$local_archive"
|
||||||
|
|
||||||
scp -q "$local_archive" "$unraid_host:/tmp/$archive_name"
|
scp -q "$local_archive" "$unraid_host:/tmp/$archive_name"
|
||||||
|
|||||||
+9
-8
@@ -125,11 +125,9 @@ body.auth-page {
|
|||||||
|
|
||||||
.auth-brand-logo {
|
.auth-brand-logo {
|
||||||
display: block;
|
display: block;
|
||||||
width: 64px;
|
width: min(274px, 78vw);
|
||||||
height: 64px;
|
height: auto;
|
||||||
margin-bottom: 16px;
|
margin-bottom: 18px;
|
||||||
border-radius: 16px;
|
|
||||||
box-shadow: 0 10px 24px rgba(0, 124, 131, 0.28), 0 2px 6px rgba(18, 38, 43, 0.08);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.auth-brand-name {
|
.auth-brand-name {
|
||||||
@@ -142,9 +140,12 @@ body.auth-page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.auth-brand-tagline {
|
.auth-brand-tagline {
|
||||||
margin: 4px 0 0;
|
margin: 6px 0 0;
|
||||||
font-size: 14px;
|
font-size: 11px;
|
||||||
line-height: 20px;
|
line-height: 18px;
|
||||||
|
font-weight: 700;
|
||||||
|
letter-spacing: .12em;
|
||||||
|
text-transform: uppercase;
|
||||||
color: var(--on-surface-variant);
|
color: var(--on-surface-variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+18
-1
@@ -34,7 +34,13 @@ body::before {
|
|||||||
|
|
||||||
.cockpit-sidebar { background: color-mix(in srgb, var(--surface-lowest) 97%, black); }
|
.cockpit-sidebar { background: color-mix(in srgb, var(--surface-lowest) 97%, black); }
|
||||||
.cockpit-main { padding-top: calc(var(--topbar-height) + 42px); }
|
.cockpit-main { padding-top: calc(var(--topbar-height) + 42px); }
|
||||||
.cockpit-main > * { max-width: 1860px; }
|
.cockpit-main > * { max-width: 2800px; margin-right: auto; margin-left: 0; }
|
||||||
|
.brand-lockup { display: grid; min-width: 0; gap: 5px; }
|
||||||
|
.brand-wordmark { display: block; width: 174px; height: auto; padding: 5px 8px; border-radius: 7px; background: rgba(255, 255, 255, .94); }
|
||||||
|
.cockpit-brand small { margin: 0 2px; color: var(--text-faint); font-size: 8px; font-weight: 700; letter-spacing: .08em; }
|
||||||
|
.workspace-identity { display: grid; min-width: 176px; padding-right: 18px; border-right: 1px solid var(--divider); line-height: 1.1; }
|
||||||
|
.workspace-identity span { color: var(--text-strong); font-size: 14px; font-weight: 740; letter-spacing: -.015em; }
|
||||||
|
.workspace-identity small { margin-top: 5px; color: var(--text-faint); font: 650 9px var(--font-body); letter-spacing: .075em; text-transform: uppercase; }
|
||||||
|
|
||||||
.nav-caption,
|
.nav-caption,
|
||||||
.nav-item,
|
.nav-item,
|
||||||
@@ -45,6 +51,9 @@ body::before {
|
|||||||
.nav-item:hover { transform: none; background: color-mix(in srgb, var(--surface-high) 70%, transparent); }
|
.nav-item:hover { transform: none; background: color-mix(in srgb, var(--surface-high) 70%, transparent); }
|
||||||
.nav-item.is-active { background: var(--surface-high); box-shadow: inset 0 0 0 1px var(--divider); }
|
.nav-item.is-active { background: var(--surface-high); box-shadow: inset 0 0 0 1px var(--divider); }
|
||||||
.nav-item.is-active::after { inset: 9px auto 9px 0; width: 3px; border-radius: 0 3px 3px 0; box-shadow: none; }
|
.nav-item.is-active::after { inset: 9px auto 9px 0; width: 3px; border-radius: 0 3px 3px 0; box-shadow: none; }
|
||||||
|
.nav-item .icon { transition: color .16s ease, transform .16s ease; }
|
||||||
|
.nav-item:hover .icon { transform: scale(1.06); color: var(--text-strong); }
|
||||||
|
.nav-item.is-active span { font-weight: 680; }
|
||||||
|
|
||||||
.cockpit-heading { margin-bottom: 30px; }
|
.cockpit-heading { margin-bottom: 30px; }
|
||||||
.cockpit-heading h1 { max-width: 900px; }
|
.cockpit-heading h1 { max-width: 900px; }
|
||||||
@@ -65,6 +74,8 @@ input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
|
|||||||
select,
|
select,
|
||||||
textarea,
|
textarea,
|
||||||
.command-search { border-color: var(--divider-strong); border-radius: 9px; background: color-mix(in srgb, var(--surface-low) 90%, transparent); }
|
.command-search { border-color: var(--divider-strong); border-radius: 9px; background: color-mix(in srgb, var(--surface-low) 90%, transparent); }
|
||||||
|
.command-search { transition: width .2s ease, border-color .16s ease, background .16s ease, box-shadow .16s ease; }
|
||||||
|
.command-search:focus-within { width: min(620px, 65vw); border-color: color-mix(in srgb, var(--cyan) 58%, var(--outline)); background: var(--surface-container); box-shadow: 0 0 0 3px color-mix(in srgb, var(--cyan) 8%, transparent); }
|
||||||
.field-label,
|
.field-label,
|
||||||
label > span:first-child { font-family: var(--font-body); font-weight: 700; letter-spacing: .065em; }
|
label > span:first-child { font-family: var(--font-body); font-weight: 700; letter-spacing: .065em; }
|
||||||
|
|
||||||
@@ -151,6 +162,11 @@ label > span:first-child { font-family: var(--font-body); font-weight: 700; lett
|
|||||||
.pill { border-color: transparent; border-radius: 999px; }
|
.pill { border-color: transparent; border-radius: 999px; }
|
||||||
.empty-state { border-color: var(--divider-strong); border-radius: var(--radius-md); }
|
.empty-state { border-color: var(--divider-strong); border-radius: var(--radius-md); }
|
||||||
|
|
||||||
|
@media (min-width: 1800px) {
|
||||||
|
.explorer-shell { grid-template-columns: minmax(650px, 880px) minmax(760px, 1fr); }
|
||||||
|
.automation-layout { grid-template-columns: minmax(0, 1fr) minmax(340px, 430px); }
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 1450px) {
|
@media (max-width: 1450px) {
|
||||||
.filter-console { grid-template-columns: minmax(250px, 1.5fr) repeat(3, minmax(135px, 1fr)); }
|
.filter-console { grid-template-columns: minmax(250px, 1.5fr) repeat(3, minmax(135px, 1fr)); }
|
||||||
.filter-console > :nth-last-child(-n+3) { grid-row: 2; }
|
.filter-console > :nth-last-child(-n+3) { grid-row: 2; }
|
||||||
@@ -171,6 +187,7 @@ label > span:first-child { font-family: var(--font-body); font-weight: 700; lett
|
|||||||
.profile-index-card { grid-template-columns: 1fr; }
|
.profile-index-card { grid-template-columns: 1fr; }
|
||||||
.profile-index-art { min-height: 230px; border-top: 1px solid var(--divider); border-left: 0; }
|
.profile-index-art { min-height: 230px; border-top: 1px solid var(--divider); border-left: 0; }
|
||||||
.profile-index-art .radar-illustration { width: 220px; }
|
.profile-index-art .radar-illustration { width: 220px; }
|
||||||
|
.command-search:focus-within { width: min(100%, 510px); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 560px) {
|
@media (max-width: 560px) {
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
|
||||||
<rect width="64" height="64" rx="10" fill="#00f5ff"/>
|
|
||||||
<g fill="none" stroke="#003739" stroke-linecap="round" stroke-linejoin="round" stroke-width="4">
|
|
||||||
<circle cx="32" cy="32" r="20"/>
|
|
||||||
<circle cx="32" cy="32" r="11"/>
|
|
||||||
<path d="m32 32 15-15M32 8v5M8 32h5M32 51v5M51 32h5"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 363 B |
@@ -0,0 +1,7 @@
|
|||||||
|
# Lokale merkassets
|
||||||
|
|
||||||
|
`itworx-wordmark.png` is de transparante, opgeschoonde officiële ITWorx.tech-wordmark uit `ITWorx_Logo_Asset_Pack_2026-07-25.zip`, door de projecteigenaar aangeleverd op 2026-07-26.
|
||||||
|
|
||||||
|
`itworx-app-icon.png` en `vacatureradar-docker.png` zijn deterministisch uitgesneden en met Lanczos geschaalde varianten van het cloud-check-symbool uit dezelfde goedgekeurde wordmark. Ze bevatten geen nieuw of gegenereerd beeldmerk. Het app-icon is 512×512; de Dockermanvariant is 256×256.
|
||||||
|
|
||||||
|
Deze assets zijn uitsluitend voor de eigen VacatureRadar-installatie en worden niet als generiek herbruikbare of publiek gelicenseerde merkset aangeboden.
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 114 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 85 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 31 KiB |
@@ -1,8 +0,0 @@
|
|||||||
<svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="VacatureRadar">
|
|
||||||
<rect width="64" height="64" rx="12" fill="#007c83"/>
|
|
||||||
<g fill="none" stroke="#f2ffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4">
|
|
||||||
<circle cx="32" cy="32" r="20"/>
|
|
||||||
<circle cx="32" cy="32" r="11"/>
|
|
||||||
<path d="m32 32 15-15M32 8v5M8 32h5M32 51v5M51 32h5"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 424 B |
+8
-6
@@ -5,9 +5,11 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta name="color-scheme" content="dark light">
|
<meta name="color-scheme" content="dark light">
|
||||||
<meta name="theme-color" content="#060e20">
|
<meta name="theme-color" content="#071327" media="(prefers-color-scheme: dark)">
|
||||||
|
<meta name="theme-color" content="#f4f7f7" media="(prefers-color-scheme: light)">
|
||||||
|
<meta name="application-name" content="VacatureRadar · {{ app_brand_name }}">
|
||||||
<title>{% block title %}{{ app_name }}{% endblock %}</title>
|
<title>{% block title %}{{ app_name }}{% endblock %}</title>
|
||||||
<link rel="icon" href="{% static 'favicon.svg' %}" type="image/svg+xml">
|
<link rel="icon" href="{% static 'img/itworx-app-icon.png' %}?v={{ app_version }}" type="image/png" sizes="512x512">
|
||||||
<link rel="stylesheet" href="{% static 'css/app.css' %}?v={{ app_version }}">
|
<link rel="stylesheet" href="{% static 'css/app.css' %}?v={{ app_version }}">
|
||||||
<script src="{% static 'js/app.js' %}?v={{ app_version }}" defer></script>
|
<script src="{% static 'js/app.js' %}?v={{ app_version }}" defer></script>
|
||||||
{% block extra_head %}{% endblock %}
|
{% block extra_head %}{% endblock %}
|
||||||
@@ -19,9 +21,8 @@
|
|||||||
<div class="cockpit" data-app-frame>
|
<div class="cockpit" data-app-frame>
|
||||||
<aside class="cockpit-sidebar" data-sidebar aria-label="Hoofdnavigatie">
|
<aside class="cockpit-sidebar" data-sidebar aria-label="Hoofdnavigatie">
|
||||||
<div class="sidebar-heading">
|
<div class="sidebar-heading">
|
||||||
<a class="cockpit-brand" href="{% url 'dashboard:today' %}" aria-label="VacatureRadar dashboard">
|
<a class="cockpit-brand" href="{% url 'dashboard:today' %}" aria-label="ITWorx.tech VacatureRadar dashboard">
|
||||||
<span class="brand-radar" aria-hidden="true"><svg class="icon"><use href="#icon-radar"></use></svg></span>
|
<span class="brand-lockup"><img class="brand-wordmark" src="{% static 'img/itworx-wordmark.png' %}" alt="ITWorx.tech"><small>VacatureRadar · intelligence cockpit</small></span>
|
||||||
<span><strong>VacatureRadar</strong><small>Intelligence cockpit</small></span>
|
|
||||||
</a>
|
</a>
|
||||||
<button class="icon-button nav-close mobile-only" type="button" data-nav-close aria-label="Menu sluiten"><svg class="icon"><use href="#icon-close"></use></svg></button>
|
<button class="icon-button nav-close mobile-only" type="button" data-nav-close aria-label="Menu sluiten"><svg class="icon"><use href="#icon-close"></use></svg></button>
|
||||||
</div>
|
</div>
|
||||||
@@ -48,7 +49,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="sidebar-account">
|
<div class="sidebar-account">
|
||||||
<span class="avatar" aria-hidden="true">{{ user.first_name|default:user.username|slice:":1"|upper }}</span>
|
<span class="avatar" aria-hidden="true">{{ user.first_name|default:user.username|slice:":1"|upper }}</span>
|
||||||
<span><strong>{{ user.get_full_name|default:user.username }}</strong><small>Persoonlijke radar</small></span>
|
<span><strong>{{ user.get_full_name|default:user.username }}</strong><small>Eigen werkruimte</small></span>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
@@ -57,6 +58,7 @@
|
|||||||
<header class="cockpit-topbar">
|
<header class="cockpit-topbar">
|
||||||
<div class="topbar-start">
|
<div class="topbar-start">
|
||||||
<button class="icon-button mobile-only" type="button" data-nav-toggle aria-label="Menu openen" aria-expanded="false"><svg class="icon"><use href="#icon-menu"></use></svg></button>
|
<button class="icon-button mobile-only" type="button" data-nav-toggle aria-label="Menu openen" aria-expanded="false"><svg class="icon"><use href="#icon-menu"></use></svg></button>
|
||||||
|
<div class="workspace-identity desktop-label"><span>{{ app_brand_name }}</span><small>VacatureRadar · {{ page_context_label }}</small></div>
|
||||||
<form class="command-search" method="get" action="{% url 'jobs:list' %}" role="search">
|
<form class="command-search" method="get" action="{% url 'jobs:list' %}" role="search">
|
||||||
<label class="sr-only" for="global-search">Zoek door vacatures</label>
|
<label class="sr-only" for="global-search">Zoek door vacatures</label>
|
||||||
<svg class="icon" aria-hidden="true"><use href="#icon-search"></use></svg>
|
<svg class="icon" aria-hidden="true"><use href="#icon-search"></use></svg>
|
||||||
|
|||||||
@@ -4,18 +4,19 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta name="color-scheme" content="light">
|
<meta name="color-scheme" content="light">
|
||||||
<meta name="theme-color" content="#fbf8ff">
|
<meta name="theme-color" content="#071327">
|
||||||
|
<meta name="application-name" content="VacatureRadar · {{ app_brand_name }}">
|
||||||
<title>Inloggen · VacatureRadar</title>
|
<title>Inloggen · VacatureRadar</title>
|
||||||
<link rel="icon" href="{% static 'favicon.svg' %}" type="image/svg+xml">
|
<link rel="icon" href="{% static 'img/itworx-app-icon.png' %}?v={{ app_version }}" type="image/png" sizes="512x512">
|
||||||
<link rel="stylesheet" href="{% static 'css/auth.css' %}?v={{ app_version }}">
|
<link rel="stylesheet" href="{% static 'css/auth.css' %}?v={{ app_version }}">
|
||||||
</head>
|
</head>
|
||||||
<body class="auth-page">
|
<body class="auth-page">
|
||||||
{% include "components/icon_sprite.html" %}
|
{% include "components/icon_sprite.html" %}
|
||||||
<main class="auth-shell">
|
<main class="auth-shell">
|
||||||
<div class="auth-brand">
|
<div class="auth-brand">
|
||||||
<img class="auth-brand-logo" src="{% static 'img/vacatureradar-logo.svg' %}" alt="VacatureRadar logo" width="64" height="64">
|
<img class="auth-brand-logo" src="{% static 'img/itworx-wordmark.png' %}" alt="ITWorx.tech" width="274" height="60">
|
||||||
<p class="auth-brand-name">VacatureRadar</p>
|
<p class="auth-brand-name">VacatureRadar</p>
|
||||||
<p class="auth-brand-tagline">Intelligence cockpit</p>
|
<p class="auth-brand-tagline">Persoonlijke intelligence cockpit</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="auth-card">
|
<div class="auth-card">
|
||||||
|
|||||||
@@ -5,16 +5,16 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta name="color-scheme" content="light">
|
<meta name="color-scheme" content="light">
|
||||||
<title>Wachtwoord gewijzigd · VacatureRadar</title>
|
<title>Wachtwoord gewijzigd · VacatureRadar</title>
|
||||||
<link rel="icon" href="{% static 'favicon.svg' %}" type="image/svg+xml">
|
<link rel="icon" href="{% static 'img/itworx-app-icon.png' %}?v={{ app_version }}" type="image/png" sizes="512x512">
|
||||||
<link rel="stylesheet" href="{% static 'css/auth.css' %}?v={{ app_version }}">
|
<link rel="stylesheet" href="{% static 'css/auth.css' %}?v={{ app_version }}">
|
||||||
</head>
|
</head>
|
||||||
<body class="auth-page">
|
<body class="auth-page">
|
||||||
{% include "components/icon_sprite.html" %}
|
{% include "components/icon_sprite.html" %}
|
||||||
<main class="auth-shell">
|
<main class="auth-shell">
|
||||||
<div class="auth-brand">
|
<div class="auth-brand">
|
||||||
<img class="auth-brand-logo" src="{% static 'img/vacatureradar-logo.svg' %}" alt="VacatureRadar logo" width="64" height="64">
|
<img class="auth-brand-logo" src="{% static 'img/itworx-wordmark.png' %}" alt="ITWorx.tech" width="274" height="60">
|
||||||
<p class="auth-brand-name">VacatureRadar</p>
|
<p class="auth-brand-name">VacatureRadar</p>
|
||||||
<p class="auth-brand-tagline">Intelligence cockpit</p>
|
<p class="auth-brand-tagline">Persoonlijke intelligence cockpit</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="auth-card">
|
<div class="auth-card">
|
||||||
|
|||||||
@@ -5,16 +5,16 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta name="color-scheme" content="light">
|
<meta name="color-scheme" content="light">
|
||||||
<title>Nieuw wachtwoord · VacatureRadar</title>
|
<title>Nieuw wachtwoord · VacatureRadar</title>
|
||||||
<link rel="icon" href="{% static 'favicon.svg' %}" type="image/svg+xml">
|
<link rel="icon" href="{% static 'img/itworx-app-icon.png' %}?v={{ app_version }}" type="image/png" sizes="512x512">
|
||||||
<link rel="stylesheet" href="{% static 'css/auth.css' %}?v={{ app_version }}">
|
<link rel="stylesheet" href="{% static 'css/auth.css' %}?v={{ app_version }}">
|
||||||
</head>
|
</head>
|
||||||
<body class="auth-page">
|
<body class="auth-page">
|
||||||
{% include "components/icon_sprite.html" %}
|
{% include "components/icon_sprite.html" %}
|
||||||
<main class="auth-shell">
|
<main class="auth-shell">
|
||||||
<div class="auth-brand">
|
<div class="auth-brand">
|
||||||
<img class="auth-brand-logo" src="{% static 'img/vacatureradar-logo.svg' %}" alt="VacatureRadar logo" width="64" height="64">
|
<img class="auth-brand-logo" src="{% static 'img/itworx-wordmark.png' %}" alt="ITWorx.tech" width="274" height="60">
|
||||||
<p class="auth-brand-name">VacatureRadar</p>
|
<p class="auth-brand-name">VacatureRadar</p>
|
||||||
<p class="auth-brand-tagline">Intelligence cockpit</p>
|
<p class="auth-brand-tagline">Persoonlijke intelligence cockpit</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="auth-card">
|
<div class="auth-card">
|
||||||
|
|||||||
@@ -5,16 +5,16 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta name="color-scheme" content="light">
|
<meta name="color-scheme" content="light">
|
||||||
<title>Herstel-link verstuurd · VacatureRadar</title>
|
<title>Herstel-link verstuurd · VacatureRadar</title>
|
||||||
<link rel="icon" href="{% static 'favicon.svg' %}" type="image/svg+xml">
|
<link rel="icon" href="{% static 'img/itworx-app-icon.png' %}?v={{ app_version }}" type="image/png" sizes="512x512">
|
||||||
<link rel="stylesheet" href="{% static 'css/auth.css' %}?v={{ app_version }}">
|
<link rel="stylesheet" href="{% static 'css/auth.css' %}?v={{ app_version }}">
|
||||||
</head>
|
</head>
|
||||||
<body class="auth-page">
|
<body class="auth-page">
|
||||||
{% include "components/icon_sprite.html" %}
|
{% include "components/icon_sprite.html" %}
|
||||||
<main class="auth-shell">
|
<main class="auth-shell">
|
||||||
<div class="auth-brand">
|
<div class="auth-brand">
|
||||||
<img class="auth-brand-logo" src="{% static 'img/vacatureradar-logo.svg' %}" alt="VacatureRadar logo" width="64" height="64">
|
<img class="auth-brand-logo" src="{% static 'img/itworx-wordmark.png' %}" alt="ITWorx.tech" width="274" height="60">
|
||||||
<p class="auth-brand-name">VacatureRadar</p>
|
<p class="auth-brand-name">VacatureRadar</p>
|
||||||
<p class="auth-brand-tagline">Intelligence cockpit</p>
|
<p class="auth-brand-tagline">Persoonlijke intelligence cockpit</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="auth-card">
|
<div class="auth-card">
|
||||||
|
|||||||
@@ -5,16 +5,16 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta name="color-scheme" content="light">
|
<meta name="color-scheme" content="light">
|
||||||
<title>Wachtwoord herstellen · VacatureRadar</title>
|
<title>Wachtwoord herstellen · VacatureRadar</title>
|
||||||
<link rel="icon" href="{% static 'favicon.svg' %}" type="image/svg+xml">
|
<link rel="icon" href="{% static 'img/itworx-app-icon.png' %}?v={{ app_version }}" type="image/png" sizes="512x512">
|
||||||
<link rel="stylesheet" href="{% static 'css/auth.css' %}?v={{ app_version }}">
|
<link rel="stylesheet" href="{% static 'css/auth.css' %}?v={{ app_version }}">
|
||||||
</head>
|
</head>
|
||||||
<body class="auth-page">
|
<body class="auth-page">
|
||||||
{% include "components/icon_sprite.html" %}
|
{% include "components/icon_sprite.html" %}
|
||||||
<main class="auth-shell">
|
<main class="auth-shell">
|
||||||
<div class="auth-brand">
|
<div class="auth-brand">
|
||||||
<img class="auth-brand-logo" src="{% static 'img/vacatureradar-logo.svg' %}" alt="VacatureRadar logo" width="64" height="64">
|
<img class="auth-brand-logo" src="{% static 'img/itworx-wordmark.png' %}" alt="ITWorx.tech" width="274" height="60">
|
||||||
<p class="auth-brand-name">VacatureRadar</p>
|
<p class="auth-brand-name">VacatureRadar</p>
|
||||||
<p class="auth-brand-tagline">Intelligence cockpit</p>
|
<p class="auth-brand-tagline">Persoonlijke intelligence cockpit</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="auth-card">
|
<div class="auth-card">
|
||||||
|
|||||||
@@ -25,6 +25,18 @@ def test_login_page_renders_stitch_design(client):
|
|||||||
assert reverse("password_reset") in body
|
assert reverse("password_reset") in body
|
||||||
assert 'src="/static/js/login.js?' in body
|
assert 'src="/static/js/login.js?' in body
|
||||||
assert "<script>" not in body
|
assert "<script>" not in body
|
||||||
|
assert "Persoonlijke intelligence cockpit" in body
|
||||||
|
assert 'alt="ITWorx.tech"' in body
|
||||||
|
assert 'src="/static/img/itworx-wordmark.png"' in body
|
||||||
|
assert 'sizes="512x512"' in body
|
||||||
|
|
||||||
|
|
||||||
|
@override_settings(VACATURERADAR_OWNER_NAME="Eigen merk")
|
||||||
|
def test_login_page_keeps_official_brand_separate_from_owner_setting(client):
|
||||||
|
body = client.get(reverse("login")).content.decode("utf-8")
|
||||||
|
|
||||||
|
assert "Eigen merk" not in body
|
||||||
|
assert 'content="VacatureRadar · ITWorx.tech"' in body
|
||||||
|
|
||||||
|
|
||||||
def test_login_with_email(client, user):
|
def test_login_with_email(client, user):
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
from django.conf import settings
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.test import override_settings
|
from django.test import override_settings
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
@@ -17,10 +18,17 @@ def test_today_requires_login(client):
|
|||||||
|
|
||||||
@pytest.mark.integration
|
@pytest.mark.integration
|
||||||
@pytest.mark.django_db
|
@pytest.mark.django_db
|
||||||
def test_browser_favicon_fallback_uses_local_svg(client):
|
def test_browser_favicon_and_brand_assets_are_local_pngs(client):
|
||||||
response = client.get("/favicon.ico")
|
response = client.get("/favicon.ico")
|
||||||
assert response.status_code == 301
|
assert response.status_code == 301
|
||||||
assert response.url.endswith("/static/favicon.svg")
|
assert response.url.endswith("/static/img/itworx-app-icon.png")
|
||||||
|
|
||||||
|
favicon = settings.BASE_DIR / "static" / "img" / "itworx-app-icon.png"
|
||||||
|
wordmark = settings.BASE_DIR / "static" / "img" / "itworx-wordmark.png"
|
||||||
|
assert favicon.read_bytes().startswith(b"\x89PNG\r\n\x1a\n")
|
||||||
|
assert wordmark.read_bytes().startswith(b"\x89PNG\r\n\x1a\n")
|
||||||
|
assert favicon.stat().st_size < 150_000
|
||||||
|
assert wordmark.stat().st_size < 100_000
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.integration
|
@pytest.mark.integration
|
||||||
@@ -30,6 +38,20 @@ def test_today_loads_for_user(client, user, profile):
|
|||||||
response = client.get(reverse("dashboard:today"))
|
response = client.get(reverse("dashboard:today"))
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert "Vandaag" in response.content.decode()
|
assert "Vandaag" in response.content.decode()
|
||||||
|
body = response.content.decode()
|
||||||
|
assert 'alt="ITWorx.tech"' in body
|
||||||
|
assert "VacatureRadar · intelligence cockpit" in body
|
||||||
|
assert "ITWorx.tech" in body
|
||||||
|
assert "VacatureRadar · Dagoverzicht" in body
|
||||||
|
assert "Dagoverzicht" in body
|
||||||
|
assert 'content="VacatureRadar · ITWorx.tech"' in body
|
||||||
|
|
||||||
|
|
||||||
|
def test_premium_layout_uses_one_left_aligned_ultrawide_grid():
|
||||||
|
css = (settings.BASE_DIR / "static" / "css" / "premium.css").read_text(encoding="utf-8")
|
||||||
|
assert "max-width: 2800px; margin-right: auto; margin-left: 0" in css
|
||||||
|
assert "@media (min-width: 1800px)" in css
|
||||||
|
assert "minmax(650px, 880px) minmax(760px, 1fr)" in css
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.integration
|
@pytest.mark.integration
|
||||||
|
|||||||
@@ -74,14 +74,18 @@ def test_deployment_examples_use_per_platform_mailbox_configuration() -> None:
|
|||||||
for key in required_keys:
|
for key in required_keys:
|
||||||
assert f"{key}=" in content
|
assert f"{key}=" in content
|
||||||
|
|
||||||
|
env_example = (ROOT / ".env.example").read_text(encoding="utf-8")
|
||||||
|
assert "VACATURERADAR_OWNER_NAME=Jens" in env_example
|
||||||
|
|
||||||
|
|
||||||
def test_unraid_deploy_requires_dedicated_ssh_alias() -> None:
|
def test_unraid_deploy_requires_dedicated_ssh_alias() -> None:
|
||||||
deploy_script = (ROOT / "scripts" / "deploy_unraid.sh").read_text(encoding="utf-8")
|
deploy_script = (ROOT / "scripts" / "deploy_unraid.sh").read_text(encoding="utf-8")
|
||||||
|
|
||||||
assert 'UNRAID_SSH_HOST:-unraid-itworx' in deploy_script
|
assert "UNRAID_SSH_HOST:-unraid-itworx" in deploy_script
|
||||||
assert "ssh -G" in deploy_script
|
assert "ssh -G" in deploy_script
|
||||||
assert '[[ "$ssh_user" != "root" ]]' in deploy_script
|
assert '[[ "$ssh_user" != "root" ]]' in deploy_script
|
||||||
assert "itworx_unraid_deploy" in deploy_script
|
assert "itworx_unraid_deploy" in deploy_script
|
||||||
assert "BatchMode=yes" in deploy_script
|
assert "BatchMode=yes" in deploy_script
|
||||||
assert "git ls-files --cached --others --exclude-standard -z" in deploy_script
|
assert "git ls-files --cached --others --exclude-standard -z" in deploy_script
|
||||||
|
assert '[[ -e "$tracked_path" ]]' in deploy_script
|
||||||
assert "/health/ready/" in deploy_script
|
assert "/health/ready/" in deploy_script
|
||||||
|
|||||||
Reference in New Issue
Block a user