Skip to content

Plan-First Clock Flow: Gates, Drafts, RichEditor Composer, and SuperChat Feed (Milestones 1–7)#446

Draft
Dharp02 wants to merge 16 commits into
mainfrom
feat/plan-first-clock-flow
Draft

Plan-First Clock Flow: Gates, Drafts, RichEditor Composer, and SuperChat Feed (Milestones 1–7)#446
Dharp02 wants to merge 16 commits into
mainfrom
feat/plan-first-clock-flow

Conversation

@Dharp02

@Dharp02 Dharp02 commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Overview

The plan-first clock flow (clock-post-simple-plan.md): write today's plan as a Huddle post → clock in → add a wrap-up to that same post → clock out. Gated per team by one setting, off by default — with the setting off, everything behaves exactly as today.

Now covers Milestones 1–7 plus the vendor/ui dependency prerequisite. Only the Yjs live-sync stretch (M8) and a final manual in-browser pass of the new editor/feed remain.

Milestone 1 — Team setting

  • settings.requirePlanForClock on the team doc (absent = false), admin-only teams.updateSettings, Switch in the Team Settings modal

Milestone 2 — Today's post

  • postDate (client-local YYYY-MM-DD) on posts, wrapUpwrapUpAt, huddle.getMyPostForDate, realtime useDailyPost hook

Milestone 3 — Gates (+ design iteration)

  • Clock In blocked until today's post exists; clock.stop throws plan-required until it has a wrap-up (client-local localDate for timezone correctness)
  • Gate state centralized in useClockToggle.planGate, realtime via the huddlePosts.byTeam DDP publication — every surface agrees: clock page, bottom-nav FAB (dimmed "plan required" state, navigates to the clock page), Work/Tickets clock-in prompts
  • Clock page redesigned as the gate: status banner → plain textarea → seven-segment punch clock, with combined actions "Post plan and clock in" / "Post wrap-up and clock out" (⌘↵)

Milestone 4 — Drafts

  • draft: true posts: author-only, date-less, status: 'draft'; excluded from feed, publication/change stream, and both gates
  • huddle.publishPost stamps postDate + clears status (arrives in the feed as a realtime added); huddle.getMyLatestDraft
  • Clock page: "Save draft" / "Update draft" + "Publish plan and clock in"

Dependency prerequisite — vendor/ui submodule

  • mieweb/ui vendored as a git submodule at vendor/ui; "@mieweb/ui": "file:vendor/ui" (0.2.4 → 0.6.1, no breaking changes found across the 40 imported components)
  • postinstall runs scripts/ensure-ui-build.mjs so fresh clones self-heal (no-op when built, SKIP_UI_BUILD=1 to skip); npm run setup:ui for manual builds

Milestone 5 — Composer → RichEditor (Kerebron)

  • Huddle composer now uses RichEditor from @mieweb/ui/kerebron (WYSIWYG ProseMirror, markdown in/out); @kerebron/* peer deps installed; wasm grammars served at /kerebron-wasm via a small inline Vite plugin (dev middleware + dist copy)
  • When today's post exists, the composer opens it for editing (remounted via key) and submit updates instead of creating

Milestone 6 — Feed → SuperChat panel

  • Posts map onto a SuperChatConversation; feed renders <SuperChat order="desc" readOnly virtualized> with code/image/mermaid render plugins
  • Inline self-edit via onMessageEditedhuddle.updatePost
  • Chat/cards toggle keeps the classic card view for per-post comments and likes (SuperChat has no per-message threads — deliberately not force-fit)

Milestone 7 — Verify

  • meteor-backend/tests/plan-gate.test.ts: 14 integration tests (gates + drafts); full backend integration suite 137/137
  • Lint, typecheck, 76 unit tests, production build (incl. wasm asset copy) all clean
  • In-browser smoke tests of the gates/realtime/drafts flow; RichEditor + SuperChat views still need a final logged-in manual pass

Out of Scope (for Now)

  • Milestone 8 (stretch): Yjs live collaborative sync — needs an upstream mieweb/ui PR adding an extensions prop to RichEditor
  • Full Playwright e2e run (test:all)

Dharp02 added 3 commits July 22, 2026 20:14
Milestone 1 of the plan-first clock flow: teams.updateSettings method,
settings on the public team shape, teamApi.updateSettings, and a Switch
in the Team Settings modal (admins only, default off).
…yPost hook

Milestone 2 of the plan-first clock flow: posts can carry a client-local
YYYY-MM-DD postDate, huddle.updatePost stamps wrapUpAt when wrapUp is
passed, and huddle.getMyPostForDate + useDailyPost expose today's post.
Milestone 3 of the plan-first clock flow:
- clock.stop throws Meteor.Error('plan-required') when the team setting
  is on and today's post has no wrap-up; accepts an optional client-local
  localDate so 'today' matches the user's timezone
- ClockPage disables Clock In without today's post and Clock Out without
  a wrap-up, with inline messages linking to Huddle
- useClockToggle surfaces plan-required refusals inline instead of alert
- wormhole exposure for teams.updateSettings + huddle.getMyPostForDate
- integration tests: meteor-backend/tests/plan-gate.test.ts (9 passing)
@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown

⏳ Preview Build In Progress

Docker image is building — this takes a few minutes (Meteor bundle compilation happens at image-build time, not container start time).

A new comment will appear here when the preview is ready or if the build fails.

Dharp02 added 4 commits July 22, 2026 20:48
The clock-page gate now embeds the same HuddleComposer used on the
Huddle tab (PlanComposer wrapper): plan mode creates today's post,
wrap-up mode appends a wrap-up and stamps wrapUpAt — no navigation
needed. Gates now target the active session's team, not the selected
team, so clock-out feedback shows even after switching teams. Extracted
shared avatar helpers and toPostAttachment to remove duplication.
…page

- useDailyPost now subscribes to the huddlePosts.byTeam publication, so
  the clock-in/clock-out gates flip in realtime on post create/edit/
  delete — no reload and no manual refetch events needed
- the mobile bottom-nav clock FAB navigates to the clock page instead of
  toggling directly, so the gates and inline composer are always visible
- dropped the now-unneeded huddle:refetch window events
Centralize the gate in useClockToggle (planGate: planMissing/
wrapUpMissing/todayPost, realtime via useDailyPost) so all clock entry
points agree:
- clockIn() refuses while today's plan is missing and reports success
- bottom-nav FAB shows a dimmed 'plan required'/'wrap-up required'
  state on any page (dashboard included) while still opening the clock
  page where the inline composer lives
- Work/Tickets clock-in prompts surface the gate instead of silently
  clocking in without a plan
- ClockPage now consumes the shared planGate instead of computing its own
Dharp02 added 5 commits July 23, 2026 12:35
… shift

Milestone 4 (added by request): posts accept draft: true (author-only,
date-less, status: 'draft'); the feed, publication/change stream, and
both clock gates only see published posts. huddle.publishPost stamps the
client-local postDate + clears status (arriving in the feed as a
realtime added), huddle.getMyLatestDraft fetches the newest draft. Clock
page composer gets Save/Update draft and 'Publish plan and clock in'.
Plan doc updated: drafts promoted from out-of-scope to Milestone 4,
milestones renumbered, design-iteration notes recorded.
…0.6.1 (file:vendor/ui)

Dependency prerequisite for the RichEditor/SuperChat milestones. The
library is built locally from the vendor/ui submodule; postinstall runs
scripts/ensure-ui-build.mjs so a fresh clone self-heals (no-op when
dist/ exists, SKIP_UI_BUILD=1 to opt out), plus a manual setup:ui
script. Smoke-tested: typecheck, lint, 76 unit tests, production build,
and runtime render all clean on 0.6.1.
Milestone 5: the Huddle composer now uses RichEditor from
@mieweb/ui/kerebron (WYSIWYG ProseMirror, markdown in/out) — the manual
markdown toolbar and preview tabs are gone. @kerebron/* peer deps
installed; a small Vite plugin serves @kerebron/wasm assets at
/kerebron-wasm in dev and copies them into dist on build; kerebron.css
imported in styles.css. When today's post exists the composer opens it
for editing (remounted via key) and submit updates instead of creating.
Mentions become removable chips below the editor.
Milestone 6: huddle posts map onto a SuperChatConversation (one
participant per author, one message per post; image attachments embedded
as markdown, others as links, ticket title as an inline tag) rendered
with <SuperChat order='desc' readOnly virtualized> and code/image/
mermaid render plugins. Self-authored messages are editable inline via
onMessageEdited → huddle.updatePost. A chat/cards toggle keeps the
classic card view for per-post comments and likes (SuperChat has no
per-message threads — deliberately not force-fit).
@Dharp02 Dharp02 changed the title Plan-First Clock Flow: Team Setting, Daily Post, and Clock Gates (Milestones 1–3) Plan-First Clock Flow: Gates, Drafts, RichEditor Composer, and SuperChat Feed (Milestones 1–7) Jul 23, 2026
Dharp02 added 3 commits July 23, 2026 13:57
Three product changes by request:

1. Per-session gate (was once-per-day): posts carry clockEventId;
   clock.start links the plan post to the new session (planPostId),
   clock.stop gates on that session's post. Every clock-in needs a
   fresh plan; a 2nd clock-in the same day needs its own. New
   huddle.getMyPostForSession + useSessionPost hook; useClockToggle
   exposes sessionPost. Recovery path (createPost accepts clockEventId
   + wrapUp) so a session can never get stuck. Huddle-tab composer now
   always creates a new post.

2. Drafts tab: Feed/Drafts toggle on the Huddle page + DraftsPanel for
   creating/editing/publishing/deleting multiple drafts. New
   huddle.getMyDrafts; publishPost accepts clockEventId.

3. Bigger editor: RichEditor min-h-52 + larger text; clock-page
   textarea rows=10/min-h-52.

Team Settings copy updated to per-session. Tests updated (15 backend
integration, 76 unit). In-browser verified: two independent sessions,
two feed posts, drafts created and hidden from the feed.
…k-outside collapse

- Shared MarkdownEditor wrapper: a capturing mousedown handler
  preventDefaults clicks on the Kerebron toolbar/menu
  (.kb-custom-menu__wrapper) so the editor keeps its selection — toolbar
  buttons (Toggle bold/italic/etc.) now apply to the selected text
  instead of no-oping. Also handles Cmd/Ctrl+Enter submit.
- Clock page now uses the same Kerebron RichEditor (was a plain
  textarea); remounts via key to clear after posting and re-seed when a
  draft loads.
- Huddle composer collapses on click-outside when empty, freeing up feed
  space; typed content is preserved (never collapses with content).

Verified in-browser: toolbar bold via mouse, clock-page plan/wrap-up
flow through the rich editor, and click-outside collapse.
@Dharp02
Dharp02 requested a review from horner July 24, 2026 16:46
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.

When clocked in and out should be directed to feed to update the summary of work update

1 participant