Skip to content

feat: per-appointment organizers with delegated creation (#73)#114

Open
luflow wants to merge 8 commits into
mainfrom
claude/attendance-issue-73-6bdb5b
Open

feat: per-appointment organizers with delegated creation (#73)#114
luflow wants to merge 8 commits into
mainfrom
claude/attendance-issue-73-6bdb5b

Conversation

@luflow

@luflow luflow commented Jul 24, 2026

Copy link
Copy Markdown
Owner

Closes #73

Konzept

Termine bekommen eine Organizer-Liste (einzelne Nextcloud-User). Organizer sind "Manager ihres eigenen Termins" mit festem Rechte-Set:

  • Termin vollständig bearbeiten (inkl. Sichtbarkeit, Schließen/Absagen, Anhänge, Einplanen, Erinnerungen)
  • Termin löschen
  • Antworten-Übersicht, Kommentare und Audit-Log dieses Termins sehen (Insights)
  • Check-in bleibt bewusst bei der globalen Permission

Delegiertes Anlegen

Neue additive Permission "Termine erstellen" (Admin-Settings, gruppenbasiert): Mitglieder dürfen eigene Termine anlegen und werden dabei automatisch Organizer. Leere Konfiguration = niemand zusätzlich — Upgrades sind verhaltensneutral.

Leitplanken

  • Organizer dürfen weitere Organizer hinzufügen, aber nur sich selbst entfernen; Manager dürfen jeden entfernen
  • Gäste können nie Organizer sein (analog GUEST_BLOCKED_PERMISSIONS)
  • Organizer sehen ihren Termin immer (implizite Sichtbarkeit)
  • Keine Rechte-Eskalation möglich: das Rechte-Set ist fix, Weiterreichen erzeugt nur weitere Organizer

Technisch

  • Migration: organizers-JSON-Spalte + Backfill [created_by] — verallgemeinert die bisherigen createdBy-Sonderfälle (Booking/Close/Update)
  • PermissionService: appointment-aware Checks (canManageAppointment, isOrganizer, canSeeResponseOverviewFor)
  • Payload: myPermissions pro Termin (canEdit, canSeeResponses, canSeeComments, canSeeAuditLog, isOrganizer) — Web-UI gated darauf statt auf globale Flags
  • Neuer Capability-Key organizers für Mobile-Clients (gepaarter PR im Flutter-Repo folgt)
  • Organizer erhalten Antwort-Änderungs-Notifications für ihre Termine; Personal-Settings-Gate erweitert (manage ∨ create ∨ Organizer an ≥ 1 Termin)
  • Abweichung von der Issue-Diskussion: v1 kommt mit festem Rechte-Set statt Admin-Checkboxen — Konfigurierbarkeit ist abwärtskompatibel nachrüstbar

Unit-Tests erweitert (172 grün), OpenAPI regeneriert, npm run build ok.

🤖 Generated with Claude Code

luflow and others added 4 commits July 26, 2026 15:28
…73)

Appointments get an organizer list (individual users, stored like the
visibility fields). Organizers hold a fixed right set on their own
appointment: edit everything, delete, see responses/comments/audit log,
manage bookings and send reminders. Check-in stays a global permission.

- New additive permission create_appointments (empty config = nobody
  additional, so upgrades stay behavior-neutral); creators become
  organizers of their own appointments automatically
- Organizer list editing: managers freely; organizers may add anyone but
  remove only themselves; guests can never be organizers
- Existing appointments are backfilled with organizers=[created_by],
  generalizing the previous createdBy special cases
- Per-appointment myPermissions payload (canEdit, canSeeResponses,
  canSeeComments, canSeeAuditLog, isOrganizer) consumed by the web UI;
  new capability flag 'organizers' for mobile clients
- Organizers receive response-change notifications for their
  appointments; personal-settings toggle extended accordingly
- Web UI: organizer picker in the appointment form (creator prefilled),
  'Organized by' line on cards, admin setting for the new permission
…ing buttons

- EasyMDE styles in-editor headings with viewport-based sizes
  (calc(1.375rem + 1.5vw)) which renders huge on wide screens; override
  with the same moderate scale the rendered description uses
- EasyMDE appends "1"/"2"/"3" via ::after to the heading toolbar
  buttons (meant for its FontAwesome icons); our injected SVG icons
  already carry the digit, so suppress the pseudo element
- Spread the rendered heading scale further apart (h1 1.75em/700,
  h2 1.45em, h3 1.2em) so levels are distinguishable in the detail view
The info.xml description still listed the feature set from before
recurring appointments, self-check-in, scheduling and the rest, and it
did not mention the companion app at all.

- info.xml: rewrote summary and description in English and German to
  match what the app actually does today - recurring appointments,
  calendar import and sync, closing and deadlines, cancel/reactivate,
  scheduling, attachments, Teams (Circles), guests without an account,
  activity history and self-check-in
- info.xml: added a prominent section for the iOS/Android companion app
  with store links, next to an explicit note that this Nextcloud app
  stays free and open source and works without it
- info.xml: shortened both summaries to the 128 character limit the
  appstore schema enforces (the previous draft failed validation)
- README: same feature refresh, plus a requirements section and the
  mobile app links
- Added the appointments screenshot and refreshed the existing three

Co-Authored-By: Claude <[email protected]>
@luflow
luflow force-pushed the claude/attendance-issue-73-6bdb5b branch from 4811808 to 61e4e68 Compare July 26, 2026 13:33
luflow and others added 4 commits July 26, 2026 15:39
Both source strings carry a TRANSLATORS note asking for exactly this,
but the German coming back from Transifex used "abbrechen" — which in
German means aborting an operation, the same word as the generic Cancel
dialog button. Calling off an appointment is "absagen".

- "Cancel appointment": "Termin abbrechen" -> "Termin absagen"
- "Cancelled on {when}": "Abgebrochen am {when}" -> "Abgesagt am {when}"

This lines both up with "Cancelled" : "Abgesagt", which Transifex
already had right. The generic "Cancel" : "Abbrechen" stays as it is.

Stopgap in the German files only, as per the l10n-autotranslate skill;
the durable fix belongs in Transifex or this will come back on the next
sync.

Co-Authored-By: Claude <[email protected]>
Drop the <types> block. Nextcloud's InfoParser reads the child element
*names* as app types, so <type>notification</type> registered a bogus
type "type" (verifiable via occ config:app:get attendance types) and the
intended "notification" never applied. It is not a valid type anyway —
the schema only allows prelogin, filesystem, authentication,
extended_authentication, logging, dav, prevent_group_restriction and
session. None of them is needed here: the calendar goes through the API
in CalendarService, notifications through registerNotifierService.

Also fix the element order, which the schema enforces as a sequence:
move <screenshot> after <repository>, and reorder repair-steps, settings
and navigations. Pure reordering, no content changes.

info.xml now passes xmllint against apps.nextcloud.com/schema/apps/info.xsd.
Since stable34 the shipped notifications app no longer bundles its composer
dependencies, while its composer/autoload.php still requires the gitignored
vendor/autoload.php. @nextcloud/e2e-test-server installs shipped apps with a
plain git clone, so app:enable — and every later occ call — dies on the missing
autoloader. Note the reason at the branch so the bump isn't retried blindly.

Upstream: nextcloud/notifications#3206,
nextcloud-libraries/nextcloud-e2e-test-server#1059
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Organizer with Insights

1 participant