Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
45bb98e
feat(teams): add requirePlanForClock team setting with admin toggle
Dharp02 Jul 23, 2026
3fe6eb8
feat(huddle): postDate + wrapUpAt on posts, getMyPostForDate, useDail…
Dharp02 Jul 23, 2026
9a71fb2
feat(clock): gate clock in/out behind today's Huddle plan when enabled
Dharp02 Jul 23, 2026
7c8937f
docs(plan): record in-browser smoke test of Milestones 1-3
Dharp02 Jul 23, 2026
2713ff2
feat(clock): satisfy plan gates inline with the shared Huddle composer
Dharp02 Jul 23, 2026
b6dfbb3
feat(clock): realtime plan gates via DDP; bottom-nav FAB opens clock …
Dharp02 Jul 23, 2026
b5c27c4
feat(clock): enforce plan-first gate on every clock surface
Dharp02 Jul 23, 2026
b21280c
feat(clock): implement plan-first clock page with inline composer and…
Dharp02 Jul 23, 2026
8d2e82e
feat(huddle): draft plans — save without publishing, publish to start…
Dharp02 Jul 23, 2026
29cbd1c
build(ui): vendor mieweb/ui as submodule, upgrade @mieweb/ui 0.2.4 → …
Dharp02 Jul 23, 2026
ee605e6
feat(huddle): swap composer textarea for Kerebron RichEditor
Dharp02 Jul 23, 2026
757d49e
feat(huddle): SuperChat thread as the default feed view
Dharp02 Jul 23, 2026
1e7f911
docs(plan): record Milestone 7 verification — full integration suite …
Dharp02 Jul 23, 2026
8591fb3
docs(plan): record manual in-browser verification of RichEditor + Sup…
Dharp02 Jul 23, 2026
2f8d7bb
feat(clock): per-session plan gate, drafts tab, bigger editor
Dharp02 Jul 23, 2026
9609c0d
feat(huddle): fix editor toolbar, Kerebron editor on clock page, clic…
Dharp02 Jul 23, 2026
44e026f
feat(clock): enhance ClockPage with draft preloading and session cont…
Dharp02 Jul 23, 2026
071bb72
build(deps): align @kerebron/extension-basic-editor to 0.8.6, add dep…
Dharp02 Jul 24, 2026
a5a6f6b
feat(huddle): composer parity — Pulse video, mentions render, full-co…
Dharp02 Jul 24, 2026
e7a8fe4
feat(huddle): Yjs collaborative editing relay on /yjs (M8)
Dharp02 Jul 24, 2026
1aefb80
feat(huddle): live collaborative post editing via Yjs (M8)
Dharp02 Jul 24, 2026
46a191a
fix(backend): restore @mieweb/pulsevault to its github source (M8)
Dharp02 Jul 24, 2026
1442649
fix(vite): dedupe react/react-dom to a single copy
Dharp02 Jul 24, 2026
900af5f
fix(huddle): disable live collab on the inline post editor
Dharp02 Jul 24, 2026
833d1e4
feat(yjs): wire collabRoom to PostCard edit composer + E2E tests
Dharp02 Jul 27, 2026
9a8cf7f
fix(ci): init vendor/ui submodule in checks and Docker build
Dharp02 Jul 27, 2026
664290a
fix(ci): use published @mieweb/ui in CI/Docker; add TS augmentation
Dharp02 Jul 27, 2026
db9f004
fix(ci): install @mieweb/ui from committed tarball; fix formatting
Dharp02 Jul 27, 2026
d210289
fix(ci): copy @mieweb/ui tarball into Docker production stage too
Dharp02 Jul 27, 2026
15cf1b3
test(e2e): reset the test database up front and guard both hooks by name
Dharp02 Jul 27, 2026
fab4dc8
fix(huddle): restore the composer placeholder and retarget its e2e se…
Dharp02 Jul 27, 2026
bc3492c
fix(teams): wait for teams to load before consuming deep-link params
Dharp02 Jul 27, 2026
7930b8a
fix(ddp): keep retrying in the background and restore the session on …
Dharp02 Jul 27, 2026
b67fd66
test(e2e): switch shared-feed real-time tests to a shared team
Dharp02 Jul 28, 2026
f0c12c8
Add E2E tests for plan-first clock flow
Dharp02 Jul 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Dependencies
node_modules/
vendor/ui/node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
Expand Down
24 changes: 24 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Dependabot: PR-based notifications when dependencies advance.
#
# - npm: watches the root package.json/lock (includes @kerebron/* pins).
# @kerebron packages are grouped into a single PR so a release train of
# editor + kits + extensions lands together instead of as 10 PRs.
# - gitsubmodule: bumps the vendor/ui (and vendor/meteor-wormhole) submodule
# pointers when their upstream default branches advance. Kerebron bumps
# *inside* vendor/ui must be configured in the mieweb/ui repo itself —
# Dependabot cannot update a submodule's package.json from here.
version: 2
updates:
- package-ecosystem: npm
directory: /
schedule:
interval: weekly
groups:
kerebron:
patterns:
- '@kerebron/*'

- package-ecosystem: gitsubmodule
directory: /
schedule:
interval: weekly
8 changes: 7 additions & 1 deletion .github/workflows/pr-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,13 @@ jobs:
steps:
- uses: actions/checkout@v4
with:
submodules: true
# Only init meteor-wormhole — vendor/ui is on a branch not pushed to
# the public mieweb/ui repo, so a full submodules: true would fail.
# The app installs @mieweb/ui from the committed vendor/mieweb-ui.tgz.
submodules: false

- name: Init meteor-wormhole submodule
run: git submodule update --init vendor/meteor-wormhole

- id: container
name: Compute container name
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ pollenate-test-*.png
# Meteor build output and local packages
meteor-backend/prod-build/
meteor-backend/packages/
meteor-backend/.meteor/local/
meteor-backend/.meteor/local-test/

# Local development scripts and configs (machine-specific, never commit)
backend/nginx-apple-proxy.conf
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@
[submodule "vendor/meteor-wormhole"]
path = vendor/meteor-wormhole
url = https://github.com/mieweb/meteor-wormhole
[submodule "vendor/ui"]
path = vendor/ui
url = https://github.com/mieweb/ui
12 changes: 11 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,13 @@ COPY packages/README.md ./packages/
COPY meteor-backend/package.json meteor-backend/package-lock.json ./meteor-backend/
COPY scripts ./scripts

# Install all dependencies (dev included — needed for Vite build + Meteor)
# @mieweb/ui is installed from a committed tarball (see package.json:
# "@mieweb/ui": "file:vendor/mieweb-ui.tgz") — the vendor/ui submodule branch is
# not pushed to the public mieweb/ui repo, so it can't be built here. Copy the
# tarball before install so npm can resolve the file: dependency.
COPY vendor/mieweb-ui.tgz ./vendor/mieweb-ui.tgz

# Install all dependencies (dev included — needed for Vite build + Meteor).
RUN npm install
RUN cd meteor-backend && npm install

Expand Down Expand Up @@ -75,6 +81,10 @@ WORKDIR /app
# Root production deps (serve, etc.)
COPY package.json package-lock.json ./
COPY scripts ./scripts
# @mieweb/ui resolves to file:vendor/mieweb-ui.tgz — copy it so the install can
# resolve the dependency (it's bundled into dist/ at build time, but npm still
# needs the file present to satisfy the manifest).
COPY vendor/mieweb-ui.tgz ./vendor/mieweb-ui.tgz
RUN npm install --production

# Copy pre-built artifacts from builder — no source, no Meteor, no vendor
Expand Down
154 changes: 154 additions & 0 deletions clock-post-simple-plan.md

Large diffs are not rendered by default.

78 changes: 74 additions & 4 deletions meteor-backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 7 additions & 4 deletions meteor-backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"@agendajs/mongo-backend": "^4.0.2",
"@babel/runtime": "^7.23.5",
"@casl/ability": "^6.8.1",
"@mieweb/pulsevault": "^0.1.0",
"@mieweb/pulsevault": "github:mieweb/pulsevault",
"@parse/node-apn": "^8.1.0",
"@swc/helpers": "^0.5.17",
"agenda": "^6.2.5",
Expand All @@ -21,11 +21,15 @@
"busboy": "^1.6.0",
"firebase-admin": "^14.0.0",
"jose": "^6.2.3",
"lib0": "^0.2.109",
"lodash.throttle": "^4.1.1",
"meteor-node-stubs": "^1.2.12",
"nodemailer": "^9.0.1",
"srvx": "^0.11.18",
"web-push": "^3.6.7"
"web-push": "^3.6.7",
"ws": "^8.21.0",
"y-protocols": "^1.0.6",
"yjs": "^13.6.30"
},
"devDependencies": {
"@eslint/js": "^9.17.0",
Expand All @@ -35,8 +39,7 @@
"mongodb": "^6.12.0",
"typescript": "^5.7.0",
"typescript-eslint": "^8.19.1",
"vitest": "^4.1.9",
"ws": "^8.21.0"
"vitest": "^4.1.9"
},
"meteor": {
"mainModule": {
Expand Down
30 changes: 28 additions & 2 deletions meteor-backend/server/clock.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ Meteor.methods({
},

/** Clock in: close any dangling open events, open a new one, fire side-effects. */
async 'clock.start'({ teamId } = {}) {
async 'clock.start'({ teamId, planPostId } = {}) {
const identity = await requireIdentity(this);
const userId = identity.userId;
const team = await findUserTeam(userId, teamId);
Expand All @@ -147,6 +147,15 @@ Meteor.methods({
const created = await ClockEvents.findOneAsync(_id);
const pub = toPublicClockEvent(created, []);

// Plan-first flow: link the just-posted plan to this session so the
// per-session clock-out gate can find it (one post per clock session).
if (planPostId && isValidId(planPostId)) {
await rawDb().collection('huddlePosts').updateOne(
{ _id: new ObjectId(planPostId), userId },
{ $set: { clockEventId: created._id.toHexString(), updatedAt: new Date() } }
);
}

// Schedule 4h break reminder + 7h45m shift-end reminder.
scheduleClockJobs(created._id.toHexString(), userId, teamId, now).catch((err) =>
console.error('[agenda] scheduleClockJobs failed:', err)
Expand Down Expand Up @@ -190,6 +199,24 @@ Meteor.methods({
const event = await ClockEvents.findOneAsync({ userId, teamId, endTime: null });
if (!event) throw new Meteor.Error('not-found', 'No active clock event');

const team = await findUserTeam(userId, teamId);

// Plan-first flow: when the team requires a plan, block clock-out until
// THIS session's Huddle post has a wrap-up. One post per clock session,
// linked by clockEventId (see clock-post-simple-plan.md). Drafts never
// count — only published posts.
if (team?.settings?.requirePlanForClock) {
const post = await rawDb()
.collection('huddlePosts')
.findOne(
{ teamId, userId, clockEventId: event._id.toHexString(), status: { $ne: 'draft' } },
{ sort: { createdAt: -1 } }
);
if (!post?.wrapUpAt) {
throw new Meteor.Error('plan-required', "Add a wrap-up to this session's post first");
}
}

const now = Date.now();
const eventId = event._id.toHexString();

Expand Down Expand Up @@ -221,7 +248,6 @@ Meteor.methods({
const updated = await ClockEvents.findOneAsync(event._id);
const pub = toPublicClockEvent(updated, closedBreaks);

const team = await findUserTeam(userId, teamId);
if (team) {
const userName = await userDisplayName(userId);
const totalSecs = pub.accumulatedTime ?? 0;
Expand Down
Loading
Loading