Skip to content

Feat/noid/one click decisions and coverage hints - #40

Merged
karlitschek merged 7 commits into
mainfrom
feat/noid/one-click-decisions-and-coverage-hints
Aug 11, 2026
Merged

Feat/noid/one click decisions and coverage hints#40
karlitschek merged 7 commits into
mainfrom
feat/noid/one-click-decisions-and-coverage-hints

Conversation

@karlitschek

Copy link
Copy Markdown
Member

🤖 AI (if applicable)

  • The content of this PR was partly or fully generated using AI

Frank Karlitschek and others added 5 commits August 10, 2026 23:44
A manager's common answer is "yes", and it cost a page load. The four
notifications that ask for a decision — a new request, an escalation, the
overdue reminder and a withdrawal — now carry Approve, Decline and Review.

Approve POSTs to the same endpoint the app uses, so the notification
dismisses itself and nothing opens. Declining is deliberately not a
one-click verdict: §5.2 requires a reason, and a manager able to reject
somebody's holiday from a toast without saying why would be a worse app,
not a faster one. Its button is a deep link that opens the request with
the reason box already unfolded, which is still a step better than
"Review" for someone who has decided to say no.

The reminder previously carried no buttons at all, which is exactly the
notification where the decision is most overdue. A withdrawal asks the
opposite question, so its buttons read "Approve withdrawal" and "Keep
leave", matching the sidebar. Notifications that merely report an outcome
stay button-free: nothing is owed on them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…icked

The coverage check has always existed, but only the manager saw it — at
approval time, when changing the dates is expensive for everyone. The
same team-scope query now runs as the dates move in the request dialog
and names who is already off, warning when booking would take the team
to the configured concurrency limit.

It is advisory in the strongest sense: it never disables submit, a failed
lookup simply omits the hint, and an employee stays free to book a clash
they have already agreed with their team. The point is that the person
choosing the dates learns what the manager will see while they can still
cheaply choose differently.

Shown only for one's own leave — the endpoint answers for the caller's
team, so HR recording an absence for somebody else would otherwise be
shown the wrong team's names, and no hint beats a misleading one. Leave
types stay neutralised by the shared-calendar visibility policy, so a
colleague's sick leave does not become visible because somebody opened
the booking form.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
"1 day to go" is a poor description of an afternoon. Inside 48 hours the
next-break hero now counts down in seconds, in tabular figures so the
digits do not jitter, under the eyebrow "Almost there". It carries
role="timer" rather than an aria-live region, which would read the clock
aloud every second.

This also fixes a latent bug: nextBreak and the reported year were
computed from a Date captured at render, so My leave left open across
midnight — or New Year — kept showing the previous day's numbers. The
hero's clock now only commits a new value when the rendered text can
have changed, so a page reading "12 days to go" does not re-render the
request list once a second all year.

The empty-state palm follows the calendar too: blossom and a passing bird
in spring, full sun in summer, fronds turning and shedding in autumn, a
snow-capped island and snowfall in winter. Meteorological seasons,
flipped for southern-hemisphere users off the country already chosen for
public holidays — no new setting, and no snow in a Sydney January. All
motion still stops under prefers-reduced-motion.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ting

SPECIFICATION.md gains the four features (§8 pre-booking coverage, §11
notification actions, §15.2 countdown and dialog hint, §15.7 seasonal
illustration) and a new §3.9 "Which today applies", which had no coverage
at all: ClockService, why a date-typed field needs a day boundary, and
the userToday/serverToday/now split every caller has to choose between.

README.md is rewritten for people evaluating the app rather than reading
the source: organised by role, leading with why a company would self-host
this, and made feature-complete against the spec and the code — bulk
entitlements, the sick-leave overview, the background jobs, the admin
settings table, guest exclusion, GDPR handling and the audit trail were
all undocumented. A "what is not in the box" section states the gaps
plainly, because a feature list you cannot trust is worth nothing.

appinfo/info.xml gets the same treatment for the App Store listing, and
drops a false claim: it advertised "CSV/Excel export" when only CSV
ships. <version> is deliberately left alone for the release.

CHANGELOG.md back-fills 1.0.7 onwards, which had entries for none of the
work merged since 1.0.6.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@karlitschek
karlitschek enabled auto-merge August 10, 2026 21:57
…ints

Only the built bundles conflicted. No source file was touched by both sides: main
brought the statistics range/clock fix (#39) and the ExportController import
order, this branch brings one-click decisions, the coverage hints in the request
dialog and the My leave countdown.

js/absence-main.mjs and its source map are generated, so hand-merging the
minified output would at best be meaningless and at worst produce a bundle
matching neither side. They are regenerated from the merged source instead.

The vendor chunks (index-*, NcCheckboxRadioSwitch-*) keep their content hashes:
they are built from node_modules alone, which neither side changed. Only the app
bundle moved, which is what both sides had edited.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@nextcloud-command nextcloud-command added the AI assisted This PR contains AI-assisted commits label Aug 11, 2026
appinfo/info.xml still said 1.0.6 while CHANGELOG.md documented everything up to
1.0.12, so the app reported a version six patches behind its own release notes.
info.xml is the single authoritative version — the Makefile derives the appstore
tarball name from it, and it is what the app store and the server's upgrade check
read — so it is the file that was wrong, not the changelog.

The line had not moved since the initial import: 1.0.6 was current then, the
1.0.7–1.0.11 bumps only ever existed as uncommitted local ones for asset
cache-busting on the devel install, and nothing since carried the committed value
forward. v1.0.6 is still the only tag, so none of those versions was ever
released and no release notes are being retroactively rewritten here.

package.json is deliberately left at 1.0.0. It has also not moved since the
initial import, nothing reads it — the bundle is not published to npm — and
starting to track the app version there now would be a new convention rather
than a fix to an inconsistent one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@karlitschek
karlitschek disabled auto-merge August 11, 2026 08:53
@karlitschek
karlitschek merged commit 585aebc into main Aug 11, 2026
26 of 33 checks passed
@karlitschek
karlitschek deleted the feat/noid/one-click-decisions-and-coverage-hints branch August 11, 2026 08:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI assisted This PR contains AI-assisted commits

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants