calendar
All repositories: gitoria
7.8 KB
# calendar.worldapi.orgThe creator's calendar (CONCEPT.md), in Hybriel on hl:web. The month view at `/` — prev / next buttons on top, month nameand year between them, today marked, weeks start on Monday, names in the browser's language — and, since ticket #2,**login with ident and private events**. https://calendar.worldapi.org## Use- Signed out: the month view and "Log in with ident" (top right; the identity selector or the button).- Signed in: click a day to add an event, click an event to edit or delete it. An event has a title, "At a time" (from /to, date and time) or "All day" (from / to, dates), a place and notes. It shows on every day it covers (a day shows fourchips, the fourth says "+N more"). Only the owner sees, changes or deletes an event.- Events are stored as **WorldAPI Events** (https://worldapi.org/standards/event): `$type $version $kind $title$description $start $end $timezone $location $status $visibility $created $updated` plus `owner` (users `@id`). Timedevents: local wall-clock `$start`/`$end` + `$timezone` (the browser's); all-day: `$kind = 'allday'`, date `$start`, exclusivedate `$end` (left out for one day); `$created`/`$updated` are UTC instants; `$visibility` is always `private`.- **Short ids (ident#23, mission 039)**: `users.identity` holds what ident's exchange answers — since ident#23 the identity'spublic 5-character short id (`a68sz`), before that the per-app id (32 hex); `users.hl isIdentId` accepts both (the old`isHex` check refused short ids). The switch: one-off `tools/migrate-short-ids.hl` (old → short id, idempotent, never`finish`), gate `node tests/short-id-switch.mjs` (ports 8722/8723, no browser), runbook`antcolony-docs/docs/short-id-switch.md` (Byrodin: `/CONTAINERS/projects/antcolony/docs/short-id-switch.md` once synced).## Reminders and notifications (ticket #4)- **Reminder settings** (button under the month, signed in): the calendar's default reminders — 1 hour before and the day before at20:00 until changed. Every event without reminders of its own gets them. In an event, "Calendar's" / "Own" chooses; "Own" is a listof rows (N minutes before, N hours before, N days before at HH:MM), also none at all.- Stored as WorldAPI Event `$reminders` (`{ $before: 'PT1H' }`, `{ $days_before: 1, $time: '20:00' }`); no `$reminders` = inherit; thedefaults are the Calendar's `$reminders` in `storage/mpackdb/settings.db` (one row per owner).- The page keeps the events of the next days with the reminders that apply (`soon`, part of the page state — the offline layer stores it)and sets one browser timer per reminder of the next 7 days (`arm()`; set again after every save / delete / paging and every 10 minutesof use). A timer shows the notification (hl:web `notify`, through the service worker). "Turn on notifications" is the click the browserwants before it allows them.- **Offline:** the timers need no network, and the offline page has `soon`. An event saved while the server cannot be reached shows at once,its reminders are set, and the save waits in hl:web's emit queue until the connection is back.- **Limit (Hybriel):** a timer lives while the app (or its tab) is open; a fully closed app cannot be woken without a server push (later,via ident's push notifications, ident#8). `notifyAt` cannot cancel, so `arm()` uses `setTimeout` directly and calls `notify`.- Code: `components/month-view/reminders.hl` (rows ↔ `$reminders`, describe, time-zone instants, the plan) shared by `events.hl` (settingstable, `upcoming`) and `month-view.hl` (editor, timers).## Layout- `project.hl` routes, the ident login return (`/login/callback`, `/login/failed`) · `styles.hl` all CSS (tokens from`shared/tokens.hl`, accent = light blue) · `components/main.hl` shell with the login · `components/calendar.hl` the pageand the faces `calLoad` / `calSave` / `calDelete` · `components/loginfailed.hl`.- `users.hl` users table (`storage/mpackdb/users.db`, ident identity → user `@id`) and the ident exchange ·`events.hl` events table (`storage/mpackdb/events.db`, index `owner`), strict validation, every function takes the owner.- `components/month-view/` the month view, vendored from components.hybriel.worldapi.org and EXTENDED here (events on thedays, the editor; `dates.hl` = date helpers shared with the server; it carries its own `Style`). Re-vendoring needs these changes carried over.- `login.js` ident selector ↔ shell bridge (the only hand-written JavaScript). The month view reads the browser's today / language / time zone itself (Hybriel `Date` / `Intl` in a handler, on the first pointer / focus / touch), no `month-view.js`.- PWA (ticket #3): installable and offline through hl:web's own support — `appIcons`, `appThemeColor`, `offline = [ Calendar ]` in project.hl (manifest link in the head, `/__hl/manifest.webmanifest`, `/__hl/sw.js`); icons in `icons/`. No JavaScript of ours.- `bin/hybriel` + `plugins/` (core crypto data fetch fs http http1 mpackdb proc time web) are vendored = hybriel **masterff51cf46** (2026-10-01, mission 048: #113 mpackdb generated ids redrawn while taken, #115/#116 function-literal membersreachable from faces, #118, client SVG namespace, hl:markdown #111; earlier #103–#106, #94, #83, #82, #95–#97). Built from aread-only `git archive master` (`zig build -Doptimize=ReleaseFast -Dtarget=x86_64-linux-gnu.2.39` in `native/`, zig =hybriel's `native/zig-toolchain` link), sha256 `ab7c3080…4b1d2f`. **No local patch**: re-vendor = copy binary + theplugins above, run both gates. Previous copy (e6720b1f): `.scratch/pre-048/`.- `components/calendar.hl` `validWindow` / `soonOf` are plain members called from the server faces (no `static` since #115/#116,mission 048; the gate checks both).- Language of the first render (calendar#6): `components/calendar.hl` declares `headers = null` (hybriel #105) and hands`headers['accept-language']` to `MonthView { acceptLanguage = requestLanguage }`; `names.hl` knows en de fr es it nl pt,any other → neutral names until the browser fills in its own. Names written by the server stay while paging.- Reminder timers: `arm()` creates the `setTimeout` closure inline in its `while` loop — `let p` is a new binding per pass(hybriel #106). On an older Hybriel the closures shared `p` and only the last reminder fired (mission 037 proved it:gate on 13ef4f9b → "the notifications came on time" FAIL, only "Has its own reminder" came).## Run, test, deploy- `CALENDAR_PORT=8700 ./bin/hybriel project.hl` (env: `CALENDAR_WATCH=0` no watcher, `HL_HOST`, `CALENDAR_SESSIONS`,`CALENDAR_STORAGE`, `CALENDAR_PUBLIC_URL` default https://calendar.worldapi.org, `IDENT_URL`, `IDENT_EXCHANGE_URL`,`IDENT_API_KEY`, `IDENT_API_SECRET` — `.env` beside `project.hl`, never read by workers). A login needs the ident key.- `node tests/browser.mjs` — the gate: own ident (a copy without `.env`), own server + storage, headless Chrome(ports 8700 app, 8701 ident, 8702–8709 Chrome; `CALENDAR_GATE_PORT`, `CALENDAR_GATE_IDENT_PORT`, `CALENDAR_GATE_CHROME`).Second gate: `node tests/short-id-switch.mjs` (ports 8722/8723; `CALENDAR_SWITCH_IDENT_PORT`, `CALENDAR_SWITCH_PORT`).`GATE_SKIP_EVENTS=1` skips the events part (40 checks run instead of 76, ~1.5 min instead of ~4). The language checks (`languagePart`)open a tab per language with CDP `Network.setExtraHTTPHeaders` Accept-Language de / en and the browser's own language(Intl locale + navigator.language) set to the OTHER one; first page, server HTML, next/next/prev.- `./deploy.sh` on Loreana (architect): gate → backup → rsync → `docker compose up -d --build` on Byrodin (127.0.0.1:45005).## First deploy of ticket #2 (architect)Register the app in ident with the origin `https://calendar.worldapi.org` and put `IDENT_API_KEY` / `IDENT_API_SECRET`into `.env` on Byrodin (as notes does), otherwise the login button has no key.
Branches
- mainmain branch
Latest commits
- 76edaa62calendar: Hybriel master ff51cf46 (re-vendor round, static workaround removed)mre
- 90a3fc2cdeploy.sh: back up live storage/.sessions/.env before every deploy (newest 5 kept)mre
- 6722b72ddeploy.sh: never send .git or .gitignore to Byrodinmre
- be099807State of 2026-09-27, before the move to gitoriamre