Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .agents/skills/work-in-nextcloud-app/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@ Stop immediately if production systems, Git history rewriting, new production de
- Develop executable UI logic test-first; additionally cover layout, accessibility, and Nextcloud integration with suitable smoke or browser checks.
- Treat a time-boxed exploratory spike or hard-to-isolate Nextcloud integration as an explicitly justified deviation. Discard spike code or characterize it before adoption; choose the truthful broader integration level when isolation would hide the real contract.
- Use the local fast entries named by `AGENTS.md`, normally `php tests/run.php` and `node tests/run-js.mjs`; dependency-light PHP smokes run in isolated processes. Run LocalBase and every affected consumer contract/smoke suite after a LocalBase contract change.
- In local pre-production, app tests may use shared LocalBase test helpers through relative repository paths. Add heavier packaging/autoload structure or a larger test framework only when path handling, runners, assertions, mocks, or fixtures are materially duplicated or impair readability.
- PHP classes must not remain coupled through distributed relative `require` or `require_once` chains. Production classes under `lib/` use Nextcloud's PSR-4 app autoloader; a bundled category-A dependency uses exactly one reproducibly generated, app-local, namespace-isolated Composer autoloader. Never use a shared workspace autoloader, shared cross-app `vendor/`, or neighboring production repository path as a delivery mechanism. Category-B services remain separate runtime apps and are consumed only through their public activation- and version-aware contracts.
- Every app uses one central app-local test bootstrap/autoloader for dependency-light PHP tests. It may resolve a test-only LocalBase helper through exactly one central transition point until a versioned development dependency exists, but individual tests must not retain direct relative LocalBase class paths after migration. Nextcloud integration tests may load the documented Nextcloud test bootstrap; template partials, explicit process/test entrypoints, and the one-time bootstrap of a bundled Composer autoloader remain justified includes rather than class-load chains.
- When a writing task first touches executable PHP or PHP tests in an app that has not yet migrated, include that app's complete autoload migration as a separate preparatory step in the same app scope. An app is complete only when distributed manual class requires and production fallback requires are gone, allowed includes are limited and reviewable, relevant app and provider/consumer PHP tests are green, and release checks contain neither development dependencies nor foreign repository paths. Documentation-only, formatting-only, and JavaScript-only work does not trigger an artificial PHP migration.
- Known overall and app coverage must not decline unnoticed. Aim for at least 85 percent line coverage for new or materially changed executable code, report PHP and JavaScript separately, and fully cover security invariants regardless of percentages. Coverage is a warning and delivery indicator, not a substitute for meaningful assertions.
- Do not prepare a commit or release with red relevant fast tests, contract tests, security checks, coverage gates, or delivery gates.

Expand All @@ -82,6 +84,7 @@ Stop immediately if production systems, Git history rewriting, new production de

## Git and completion report

- When Simon asks for the next open steps, priorities, remaining work, or a similar outlook, include every applicable pending migration and unresolved decision from accepted ADRs and documented rollout plans. Report its current status, trigger, and required approval gate, and distinguish work executable now from work triggered by a later app change and work that is currently undecidable. Mentioning an item does not expand the current write scope or authorize a gated change.
- Do not commit, push, release, deploy, or use `git add .` without Simon's explicit authorization. Stage individual files only when staging was requested.
- Before a commit, show `git status --short`, `git diff --stat`, and `git diff --name-only`. Never use `git reset --hard`, `git clean`, force-push, history rewrite, or versioned backup copies.
- Run relevant local tests, `git diff --check`, and the repository's own structure/fast check. For an explicitly authorized cross-app contract change, validate every provider and consumer repository from its own root and use the Parent workspace check only as an additional coordinator.
Expand Down
9 changes: 9 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,12 @@ jobs:
--check-coverage \
--lines=86.47 \
node tests/run-js.mjs

deploy-staging:
name: Staging-Deployment
if: github.event_name == 'push'
needs: [php, javascript]
uses: Filzmann/br-nextcloud-apps/.github/workflows/deploy-staging.yml@main
with:
app-id: adplaner
secrets: inherit
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Changelog

## 0.4.0-rc.2

- Monatsplanänderungen und Statuswechsel gegen konkurrierende Freigaben serialisiert; genehmigte Schichtdefinitionen bleiben als unveränderlicher Planstand erhalten.
- Strikte Monats-, Datums-, UTF-8-, Längen-, Boolean- und Schichtlistenvalidierung ergänzt.
- Teameinstellungen, Tagesbemerkungen und Zuweisungen beim konkurrierenden erstmaligen Speichern gegen Unique-Constraint-Konflikte abgesichert.
- Geleerte Tagesbemerkungen samt Bearbeitungsmetadaten entfernt; öffentliche Team- und Hinweisantworten auf aktuell schichtfähige Personen und benötigte Anzeigenamen reduziert.
- Technische Monats-Locks von personenbezogenen Änderungsmetadaten getrennt und interne Demo-Fehler ohne Detailleck als Serverfehler beantwortet.
- Fehler optionaler Hinweisprovider isoliert und öffentliche Planpayloads um interne Erstellerkennungen sowie teamfremde Hinweise bereinigt.
- Lade-, Speicher- und Zuteilungsoberfläche gegen veraltete Antworten, Doppelstarts, unklare Nachladefehler sowie Tastatur-, Tabellen- und Fokusprobleme stabilisiert.

## 0.4.0-rc.1

- Kontrollierte Monatsplanstatus `draft`, `planned` und `approved` ergänzt; nur die zuständige Einsatzbegleitung darf wechseln und genehmigte Pläne sind gegen Änderungen gesperrt.
- Optionale, datensparsame Urlaubs- und Kalenderhinweise über die öffentlichen LocalBase-Verträge eingebunden; fehlende Provider bleiben ein gültiger Standalone-Zustand.
- Direkte Navigation zum vorherigen und nächsten Monat sowie sichtbarer Tabellen-Scrollbereich und fixierte Bemerkungsspalte ergänzt.
- Additive Monatsplanstatus-Migration sowie automatisierte Service-, UI-, Migrations-, Datenbank- und DDEV-Rechteprüfungen ergänzt.

## 0.3.0-rc.1

- Eigenständige Navigation ohne OrgSuite ergänzt.
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,16 @@ AdPlaner funktioniert einzeln; optionale Abwesenheits- oder Kalenderhinweise ent

Assistenzteams werden aus den zentral konfigurierten Nextcloud-Gruppen abgeleitet. Teambezogene Schichtkonfigurationen werden durch berechtigte Einsatzbegleitungen gepflegt.

Die zuständige Einsatzbegleitung führt Monatspläne kontrolliert von `draft` über `planned` nach `approved`. Genehmigte Pläne sind bis zu einer ausdrücklichen Rücknahme gegen Wünsche, Zuweisungen und Bemerkungsänderungen gesperrt. Optionale Urlaubs- und Kalenderprovider liefern ausschließlich datensparsame, schreibgeschützte Planungshinweise.

Genehmigte Pläne frieren die damaligen Schichtdefinitionen ein, speichern aber keine zusätzlichen historischen Personenstammdaten. Zuweisungen werden weiterhin nur für aktuell schichtfähige Mitglieder des jeweiligen Assistenzteams angezeigt.

## Roadmap

Geplante Erweiterungen und offene Produktentscheidungen stehen in der [Roadmap](ROADMAP.md).

Für die fachliche, visuelle und sicherheitsbezogene Staging-Prüfung steht ein
ausfüllbares [manuelles Abnahmeformular](docs/manual-acceptance.md) bereit.
Zugangsdaten und personenbezogene Echtdaten werden darin nicht dokumentiert.

Installations-, Betriebs- und Abnahmeunterlagen stehen im öffentlichen [AD-Suite-Projekt](https://github.com/Filzmann/ad-suite).
15 changes: 13 additions & 2 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,29 @@ Diese Datei bündelt geplante Erweiterungen und offene Produktentscheidungen. Ve

## Aktueller Fokus

- Die manuellen Prüfungen werden im ausfüllbaren
[`docs/manual-acceptance.md`](docs/manual-acceptance.md) dokumentiert.
- Produktive Rechte- und Datenschutzprüfung der Wunschdienstplanung.
- Monatsplan, variable Schichten, EB-Koordination und Standalone-Betrieb auf einem realitätsnahen Staging fachlich abnehmen.

## Geplante Erweiterungen

- **ADP-L10N – vollständige Lokalisierung (später, nicht freigegeben):**
AdPlaner wird im Rahmen des suiteweiten L10N-Rollouts auf die aktive
Nextcloud-Locale und Nextcloud-l10n umgestellt. Manuelle Monats- und
Wochentagsnamen sowie sichtbare UI-, Status-, Validierungs- und
Fehlermeldungen werden dabei vollständig migriert. ISO-Daten,
Monatsnummern, Schichtzeiten, Statuswerte, Teamcodes und API-Schlüssel
bleiben unverändert; Abkürzungen werden nicht durch Abschneiden gebildet.
Erforderlich sind Tests für deutsche Ausgabe, mindestens eine weitere
Locale, Fallback, Monats-/Jahresgrenzen, Pluralformen, Platzhalter und
Escaping in PHP und JavaScript. Pilot-App, Reihenfolge und Rohtext-Gate
werden vor Umsetzung suiteweit separat freigegeben.
- Persönliche Monatsansicht „Alle meine Einsätze“ mit PDF-Export und optionaler Verbindung zu gängigen Kalendern.
- Benachrichtigungen für relevante Planungs- und Statusänderungen.
- Fachlich eindeutige Festschreibung eines Dienstplans.
- Teambezogene Konfigurierbarkeit nur dort erweitern, wo konkrete Teams unterschiedliche Regeln benötigen.

## Vor der Umsetzung zu klären

- Exportformate, Zielsysteme und Datenschutzumfang.
- Benachrichtigungskanäle, Empfänger*innen und auslösende Ereignisse.
- Bedeutung, Rechte und Rückbau einer Festschreibung sowie der Umgang mit späteren Änderungen.
6 changes: 3 additions & 3 deletions appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
<name>Assistenz Dienstplanung</name>
<summary>Wunschdienstplanung für Assistenzteams.</summary>
<description>Verwaltet monatliche Wunschdienstpläne für Assistenzteams auf Basis dynamischer Nextcloud-Gruppen.</description>
<version>0.3.0-rc.2</version>
<version>0.4.0-rc.2</version>
<licence>agpl</licence>
<author>Simon</author>
<namespace>AdPlaner</namespace>
<category>organization</category>
<website>https://github.com/Filzmann/ad-suite</website>
<bugs>https://github.com/Filzmann/nextcloud-adplaner/issues</bugs>
<repository type="git">https://github.com/Filzmann/nextcloud-adplaner</repository>
<namespace>AdPlaner</namespace>
<category>organization</category>
<dependencies>
<php min-version="8.3"/>
<nextcloud min-version="34" max-version="34"/>
Expand Down
5 changes: 3 additions & 2 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@

['name' => 'api#state', 'url' => '/api/state', 'verb' => 'GET'],
['name' => 'api#monthPlan', 'url' => '/api/teams/{teamCode}/months/{month}', 'verb' => 'GET'],
['name' => 'api#transitionMonthStatus', 'url' => '/api/teams/{teamCode}/months/{month}/status', 'verb' => 'POST'],
['name' => 'api#saveTeamSettings', 'url' => '/api/teams/{teamCode}/settings', 'verb' => 'POST'],
['name' => 'api#saveDayNote', 'url' => '/api/teams/{teamCode}/months/{month}/days/{workDate}/note', 'verb' => 'POST'],
['name' => 'api#addShiftCandidate', 'url' => '/api/teams/{teamCode}/months/{month}/slots/{slotId}/candidates', 'verb' => 'POST'],
['name' => 'api#removeShiftCandidate', 'url' => '/api/teams/{teamCode}/months/{month}/slots/{slotId}/candidates/remove', 'verb' => 'POST'],
['name' => 'api#addShiftCandidate', 'url' => '/api/teams/{teamCode}/months/{month}/slots/{slotId}/candidates', 'verb' => 'POST', 'requirements' => ['slotId' => '\\d+']],
['name' => 'api#removeShiftCandidate', 'url' => '/api/teams/{teamCode}/months/{month}/slots/{slotId}/candidates/remove', 'verb' => 'POST', 'requirements' => ['slotId' => '\\d+']],
['name' => 'demo_admin#install', 'url' => '/api/admin/demo-pack/install', 'verb' => 'POST'],
],
];
75 changes: 71 additions & 4 deletions css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
.adp-controls,
.adp-tabs,
.adp-section-head,
.adp-plan-meta,
.adp-plan-status,
.adp-cell-actions {
display: flex;
align-items: center;
Expand Down Expand Up @@ -101,6 +103,7 @@
.adp-table-wrap {
overflow: auto;
max-width: 100%;
max-height: calc(100vh - 260px);
}

.adp-table {
Expand Down Expand Up @@ -133,6 +136,18 @@
border-left: 1px solid var(--color-border);
}

.adp-month-table th:last-child,
.adp-month-table td:last-child {
position: sticky;
right: 0;
z-index: 2;
box-shadow: -1px 0 0 var(--color-border);
}

.adp-month-table thead th:last-child {
z-index: 4;
}

.adp-table small,
.adp-day small {
display: block;
Expand All @@ -156,6 +171,25 @@
color: var(--color-main-text);
}

.adp-day-hints {
display: grid;
gap: 3px;
margin-top: 6px;
}

.adp-day .adp-hint {
display: inline-flex;
width: max-content;
max-width: 160px;
border-radius: 6px;
padding: 1px 5px;
background: var(--color-background-hover);
color: var(--color-main-text);
font-size: .8rem;
font-weight: 600;
white-space: normal;
}

.adp-candidates {
display: flex;
align-items: flex-start;
Expand Down Expand Up @@ -199,15 +233,48 @@
text-align: center;
}

.adp-assignment-control,
.adp-assignment-picker {
.adp-month-control {
display: inline-flex;
align-items: center;
gap: 4px;
}

.adp-assignment-picker select {
width: 150px;
.adp-month-control .adp-icon-button {
min-height: 34px;
margin: 0;
}

.adp-assignment-control {
position: relative;
display: inline-flex;
align-items: center;
gap: 4px;
}

.adp-assignment-picker {
position: absolute;
left: 0;
top: calc(100% + 4px);
z-index: 5;
display: grid;
gap: 4px;
min-width: 180px;
max-height: 240px;
overflow-y: auto;
border: 1px solid var(--color-border);
border-radius: 8px;
padding: 6px;
background: var(--color-main-background);
box-shadow: 0 4px 16px rgba(0, 0, 0, .18);
}

.adp-assignment-picker[hidden] {
display: none;
}

.adp-assignment-picker .adp-small {
width: 100%;
text-align: left;
}

.adp-note-cell textarea {
Expand Down
Loading