Skip to content

feat: resolution editor integration#321

Open
Strehk wants to merge 87 commits intomainfrom
feat/resolution-editor-integration
Open

feat: resolution editor integration#321
Strehk wants to merge 87 commits intomainfrom
feat/resolution-editor-integration

Conversation

@Strehk
Copy link
Copy Markdown
Member

@Strehk Strehk commented Mar 8, 2026

Summary

  • Full resolution editor integration: database schema, API handlers, delegate working paper UI, chair resolution management, comment system, amendment system, voting (paragraph + final), and print view
  • Admin/mission control improvements: tabbed conference config with full CRUD for committees, delegations, NSAs, and users
  • Participant views: committee overview, paper list, paper detail with clause locking and real-time collaboration
  • Presentation mode: resolution preview with amendment tracking and voting results
  • Chair tools: DR promotion, support re-evaluation, status reversion, sponsor management, amendment lifecycle controls
  • i18n support for all new components (EN + DE)

Test plan

  • Verify delegate can create working papers, add clauses, and submit for review
  • Verify chair can promote papers to draft resolution and manage amendments
  • Verify comment system works for both chairs and participants
  • Verify clause locking prevents concurrent edits by different users
  • Verify paragraph and final voting flows work correctly
  • Verify print view renders resolution with vote results
  • Verify presentation mode displays resolution and amendment status
  • Verify mission control config tabs (committees, delegations, NSAs, users) function correctly

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Full resolution lifecycle: create/edit/submit papers, promote to draft resolutions, set active DR, support re‑evaluation toggles, per‑DR sponsorship and live updates.
    • Resolution editor: clause‑level locking, threaded comments, amendments workflow (propose/sponsor/adopt/reject), per‑clause voting and final vote results.
    • Voting UI: unified voting modal (show‑of‑hands & roll‑call) with completion callbacks and printable results.
    • Participant & Chair UX: dedicated participant views, chair controls, presentation resolution preview, share codes, autogenerated paper names.
  • Documentation

    • Added Phase 4 plan and comprehensive resolution meta‑plan; new English and German translation keys for the UI.

Strehk and others added 30 commits March 3, 2026 22:29
…ant view

- Allow double delegations: change committeeMember/conferenceMember user
  relations from one-to-one to one-to-many so multiple users can share a seat
- Add admin config table with TanStack Table: sortable columns, global faceted
  search, paginated with ellipsis, edit modal for role and seat assignment
- Show OIDC name and committee columns in the admin user table
- Increase Rumble defaultLimit from 300 to 1000 to support larger conferences
- Add participant view with identity card and committee pages
- Add self-add to speakers list functionality
- Add i18n strings for new features (en + de)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…legations, and NSAs

Restructure the config page into 5 tabs (General, Users, Committees,
Delegations, Non-State Actors). Add backend mutations for
create/update/delete on conferences, committees, representations,
committee members, and conference members. Extract existing user
management into UsersTab and build new tab components for managing
conference settings, committees, delegations (with bulk country-code
add and committee seat editing), and NSA/UN actors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Position 0 (currently speaking) now shows "You're up!" badge instead of
"#1", and queue numbering starts at the actual position. Badge and remove
button are now stacked full width.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comprehensive design document covering the full resolution lifecycle
per DMUN Geschäftsordnung: working papers, draft resolutions,
amendments, per-paragraph voting, and final adoption.

Covers database schema (10 new tables, 6 enums), new routes
(delegate papers, chair resolutions tab, mission control overview),
resolution editor library extensions, and 8 implementation phases.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Install @deutschemodelunitednations/munify-resolution-editor and lay the
complete database foundation for the resolution lifecycle: 6 enums,
10 tables, 4 new committee columns, relations, and 5 GraphQL handlers
(resolutionPaper, paperSponsor, paperShareCode, paperEditor,
paperContentSnapshot) with full mutations for paper creation, content
editing, submission, DR promotion, and vote recording.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…se locking

Add full delegate-facing resolution editing with collaborative clause-level
locking using explicit click-to-lock UX (hover overlay + "Done editing" button).

Includes: paper detail page, auto-save, share codes, sponsor management,
paper submission, lock subscription, hybrid heartbeat, and collaborative mode
that activates only when multiple editors are present.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…, concurrent editing

- Convert ChairNavbar from top tabs to bottom dock with 5 items (incl. Resolutions)
- Add resolutions page with submitted papers queue, DR list, and placeholder sections
- Promote-to-DR mutation with confirmation modal and document number assignment
- DR detail page with always-editable ResolutionEditor and clause locking
- Clause-level locking for concurrent chair/Sekretariat editing (heartbeat, lock badges)
- Title hidden post-promotion; document number is sole DR identifier (chair + participant)
- Add resolution fields to committee query/subscription
- Add 13 i18n keys (en + de)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ggle, real-time updates

Add chair controls to open/close support re-evaluation phase with DaisyUI
toggles, delegate UI for adding/removing DR support, active DR selection per
committee, and server-side enforcement of re-evaluation state. Clear active DR
automatically on final vote. Real-time updates via committee pubsub subscriptions
on all participant pages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cipants

Add team-internal comment system on draft resolutions with clause-level and
document-level threading, visibility control (TEAM_ONLY default, PUBLIC opt-in),
read-only view for participants, and real-time updates via GraphQL subscriptions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow chairs (TEAM/ADMIN) to add or remove any committee member as a
sponsor, bypassing delegate role checks, status gates, and re-evaluation
gates. Adds a searchable modal for adding sponsors and hover-X buttons
for removal. Sponsors are now sorted alphabetically by name in both
chair and participant views.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement the full amendment system backend (GO §17):
- 6 amendment mutations: create, submit, adoptByConsensus, accept, reject, withdraw
- 2 sponsor mutations: addAmendmentSponsor, removeAmendmentSponsor
- Auto-transition to AMENDMENT_PHASE when chair sets currentOperativeIndex
- Amendment application logic (DELETE, ADD, ALTER_TEXT, ALTER_POSITION) with content snapshots
- Sponsor threshold validation (10% of present delegations)
- Clause-already-passed guard for DELETE/ALTER_TEXT amendments

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nd OIDC auth redirect

- Amendment queue UI with GO-ordered display
- Per-paragraph debate controls and start amendment phase button
- Consensus check, accept/reject amendment actions
- Fix: re-auth on expired OIDC tokens — mustBeLoggedIn() now throws
  GraphQLError (passes through Yoga unmasked), Houdini ClientPlugin
  detects "Must be logged in" errors and triggers page reload → OIDC
  hook redirects to login
- Update meta-plan: mark Phase 6a-6c progress

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add per-paragraph operative clause voting and final roll-call vote to
the resolution paper lifecycle. Introduces VOTING_PHASE status between
AMENDMENT_PHASE and FINAL, with quick-input voting for chairs,
auto-confetti on adoption, and real-time vote display for participants.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… hover

Fix relative dock links breaking on nested pages by using absolute paths.
Add a sixth dock tab linking to the active draft resolution (reactive via
subscription). Show keyboard shortcuts (⌥1–⌥6) on hover with backdrop blur.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow chairs to revert a resolution paper to its previous lifecycle
status (FINAL→VOTING→AMENDMENT→DR→SUBMITTED→WORKING_PAPER) with
appropriate side effects per transition, confirmation modal with
status-specific warnings, and optional snapshot restore for amendments.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The revert button was inside the DaisyUI collapse-title, causing
clicks to toggle the accordion instead of triggering the button.
Moved it outside the collapse as a sibling element.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Place the revert button at the bottom of the expanded collapse-content
section instead of outside the accordion. Added text label so the
button clearly communicates its action.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a ghost back-arrow button next to the existing "Advance to Next
Paragraph" button, allowing chairs to navigate to the previous
operative clause during the amendment phase.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduces a hotkey-toggled (alt+v) voting modal available across all
chair pages, with a programmatic openVotingModal() API that returns a
Promise resolving to the vote result. Extracts VotingSetupForm as a
reusable component and adds oncomplete callbacks to both voting types.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ctive amendment tracking

Phase 8 implementation:
- Add documentNumber/sequenceNumber to amendments (e.g. DISEC/I/DR.1/DEL.1)
- Add activeAmendmentId to committee for tracking presented amendments
- Add phase-aware PresentationResolutionPreview component with resolution layout preset
- Extend presentation subscription with resolution and amendment data
- Fix layout preset i18n match ordering (wildcard must come last)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Paraglide match syntax with wildcard was incompatible with Prettier's
alphabetical key sorting, causing all presets to show as "Unknown Layout".
Replace with individual keys (layoutPresetDefault, layoutPresetSmallScreen,
layoutPresetResolution) and a simple lookup map in the component.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add resolutionHeadline field to committee DB schema, import schema, and creation form
- Pass headerData (conference title, committee info, document number, topic, authoring delegation, sponsors, date) to ResolutionEditor in chair, participant, and presentation views
- Add resolutionHeadline i18n keys (en/de)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 67 EN/DE message keys and a Paraglide-to-ResolutionEditorLabels
adapter so the resolution editor, preview, and amendment mini-editors
all render localized text matching the app language.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a resolution's final vote outcome is ADOPTED, filter out operative
clauses that were voted REJECTED during paragraph-by-paragraph voting
so the adopted resolution content is clean.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…il page

This enables chairs to comment on submitted working papers by linking
to the chair's own resolution detail page instead of the participant view.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow chairs to switch between edit and preview modes at any paper status.
Default to preview mode. Lock to preview-only when paper is FINAL with a
vote outcome. Add print resolution button to chair and participant views.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…viation duplication

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
m1212e and others added 27 commits March 12, 2026 14:26
The $effect that auto-submits DELETE amendments was tracking operativeClauses
as a dependency (via doSubmit's synchronous reads), causing re-triggers on
data refetch. Wrap doSubmit in untrack() and move submitting reset after the
DELETE early-return so the guard can't be defeated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Previously only SUBMITTED amendments were withdrawn when a DELETE
amendment removed an operative clause. Now PENDING amendments targeting
the same clause are also withdrawn, preventing orphaned amendments.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add text-base-content to comment cards, textareas, and select fields
so text is readable in dark mode.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ion modal

Backend now rejects amendments if the same proposer already has a PENDING/SUBMITTED
amendment of the same type targeting the same operative clause. Frontend shows a
confirmation dialog before submitting DELETE amendments instead of submitting immediately.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use explicit white background to match the ResolutionPreview container
styling, ensuring the dropdown is readable in both light and dark mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds an independent font size slider for the resolution editor content
in the presentation view, persisted via Dexie alongside the existing
overall base font size setting.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use correct German MUN terminology: "Operativer Absatz", "Unterabsatz",
and "Präambelabsatz" instead of "Klausel" throughout the German locale.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The language was resetting to German on every page navigation because the
Paraglide strategy only fell back to baseLocale. Adding 'cookie' to the
strategy persists the user's language choice. Also adds Portuguese (pt)
as a third supported language with placeholder translations.

https://claude.ai/code/session_01Pbqm6VJsvVThr4iCczVrcu
Auto-generated by inlang tooling to ignore everything except settings.json.

https://claude.ai/code/session_01Pbqm6VJsvVThr4iCczVrcu
The cycling toggle was unintuitive with 3 languages. Now clicking the
language button opens a modal listing all available languages with their
flags and native names for direct selection.

https://claude.ai/code/session_01Pbqm6VJsvVThr4iCczVrcu
URL-based locale prefixes (/en/, /pt/) caused language resets on every
internal navigation since links weren't wrapped with localizeHref().
Now locale is persisted via cookie with browser preference detection on
first visit. Locale-prefixed URLs are redirected and converted to cookie.
Also: use Flag component in language switcher, add i18n "language" key,
pre-translate Portuguese messages, change base locale to English.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Configure Tailwind's dark: variant to use [data-theme="dark"] selector
so it works with DaisyUI's theme system instead of the default
prefers-color-scheme media query. Replace hardcoded text-slate-900
with text-base-content in TextSection, ContactSection, and LandingHero.
Update Card component styling for dark mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a `resolutionFeatureEnabled` boolean (default: true) to the conference
table. When disabled, resolution/papers navbar icons are hidden for both
chairs and participants. Configurable via Mission Control > General.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…cache fix, and UI improvements

Add per-conference resolution feature toggle, track current operative
clause by ID, update schema and migration. Fix launcher showing stale
data after conference creation by marking Houdini cache stale. Update
info box components and presentation/participant views.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Version 0.34.0 was removed from the action repository, causing CI failures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add resolutionFeatureEnabled to CommitteeTeamQuery so generated types
match the layout component. Add missing Portuguese translations.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
kysely (CVE-2026-32763, CVE-2026-33468): transitive dep of @inlang/sdk
for internal SQLite ops, not used in app code.
picomatch (CVE-2026-33671): build-time only dep of rollup plugins.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When ADMIN_DOMAIN_WHITELIST or ADMIN_EMAIL_WHITELIST is empty,
split(',') produces [''] which could interfere with matching.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a deleteConference mutation (global admin only) and an isGlobalAdmin
query. The launcher page shows a "Manage Conferences" toggle at the bottom
for whitelisted admins, listing all conferences with delete buttons. A modal
requires typing the exact conference name to confirm deletion.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…e-level admin

Replace isWhitelistedEmail/isDMUNEmail with isGlobalAdmin helper that checks
both OIDC admin role and whitelisted email. Conference creation remains
global-admin-only; all other operations now use conference-level ADMIN/TEAM
roles via assertConferenceAdmin and assertCommitteeChairOrAdmin.

- Rename isDMUNEmail.ts to isAdminEmail.ts with isGlobalAdmin() helper
- Add explicit assertCommitteeChairOrAdmin checks to mutations that
  previously relied solely on ability filters (speakers lists, presence,
  committee updates)
- Update all 20+ handler ability blocks to use isGlobalAdmin
- Conference ADMIN/TEAM can now see TEAM_ONLY resolution comments
- presenceChangedTimestamp readable by all logged-in users

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add deleteConference, deleteConferenceConfirmation,
deleteConferenceWarning, and manageConferences to pt.json.
Update CLAUDE.md to mention pt.json alongside de/en.
Add i18n:check to lefthook pre-push hook to catch missing keys locally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Strehk Strehk added the PR: Feature New feature label Apr 3, 2026
Strehk pushed a commit that referenced this pull request Apr 4, 2026
- Add missing `query` import from `$api/rumble` in amendment.ts,
  operativeClauseVote.ts, and resolutionPaper.ts (build failures)
- Guard `window.location.reload()` with `browser` check in client.ts (SSR crash)
- Fix GraphQL injection in sendBeacon by using variables instead of
  string interpolation in both participant and chair paper pages
- Replace weak 6-char share code with nanoid helper per repo conventions
- Fix final vote guard to only accept VOTING_PHASE (was also accepting
  AMENDMENT_PHASE, allowing voting phase to be skipped)
- Add paper phase check to adoptByConsensus and acceptAmendment to prevent
  amendment application after paper leaves AMENDMENT_PHASE
- Fix ALTER_POSITION off-by-one: align with "insert after" convention
  used by ADD, and allow targetPosition of -1 for beginning
- Fix restored amendments reset to SUBMITTED instead of PENDING so they
  remain visible and actionable after revert
- Fix subscription cleanup in participant papers list (websocket leak)
- Fix i18n: "Stimmung" -> "Abstimmung" in de.json, "notes" -> "votes"
  and "two-thrids" -> "two-thirds" in en.json

https://claude.ai/code/session_013PjiR7TYfuzeoqmy6zRPT9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PR: Feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants