Feat/noid/one click decisions and coverage hints - #40
Merged
karlitschek merged 7 commits intoAug 11, 2026
Conversation
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
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>
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
disabled auto-merge
August 11, 2026 08:53
karlitschek
deleted the
feat/noid/one-click-decisions-and-coverage-hints
branch
August 11, 2026 08:53
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 AI (if applicable)