Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
312 commits
Select commit Hold shift + click to select a range
22e1250
feat(theme): add --ot-* token utilities to Tailwind and theme the eng…
Clupai8o0 Sep 9, 2026
8ae7414
feat(theme): migrate student, task, unit and chart screens to the the…
Clupai8o0 Sep 9, 2026
daabbd9
feat(theme): complete dark mode with GitHub-blue palette and design p…
Clupai8o0 Sep 11, 2026
a162f9e
fix(mobile): stop the profile form clipping its own headings on phones
Clupai8o0 Sep 11, 2026
91fff67
fix(mobile): stop the task sub-tab strip clipping its active label
Clupai8o0 Sep 11, 2026
b2edfeb
fix(theme): contain the unit switcher width and inset menu focus rings
Clupai8o0 Sep 11, 2026
413d84b
fix(theme): raise specificity so the menu focus-ring inset applies
Clupai8o0 Sep 11, 2026
29bd570
feat(theme): theme foundation — tokens, service, resolution and persi…
Clupai8o0 Aug 29, 2026
5c51c00
style(theme): format proof page styles
maplefoxgit Aug 29, 2026
f0b69b2
feat(theme): THM-M01 — shell and shared components dark mode
Clupai8o0 Aug 30, 2026
e04c7c2
feat(theme): apply the resolved theme before first paint
Clupai8o0 Aug 30, 2026
edb18b6
fix(pwa): correct the splash and address bar colours for dark mode
Clupai8o0 Aug 30, 2026
93da291
feat(users): persist the theme preference on the user account
Clupai8o0 Aug 30, 2026
f92c81f
fix(theme): sync account preference across devices
maplefoxgit Aug 31, 2026
9f420e1
test: support legacy matchMedia listeners
maplefoxgit Aug 31, 2026
8fc38b5
fix(theme): isolate sync state by account
maplefoxgit Sep 1, 2026
9b64b30
fix(theme): complete the app shell and global surfaces for dark mode
Clupai8o0 Sep 9, 2026
c7d7413
feat(theme): migrate status chips, badges, scrollbars and spinner to …
Clupai8o0 Sep 9, 2026
284f73f
feat(theme): add --ot-* token utilities to Tailwind and theme the eng…
Clupai8o0 Sep 9, 2026
2915528
feat(theme): migrate student, task, unit and chart screens to the the…
Clupai8o0 Sep 9, 2026
6b65f7d
feat(theme): complete dark mode with GitHub-blue palette and design p…
Clupai8o0 Sep 11, 2026
881907e
style(theme): soften the dark ground to a lighter slate
Clupai8o0 Sep 11, 2026
bc8217d
style(theme): give dark raised surfaces a visible edge
Clupai8o0 Sep 11, 2026
ae35adb
feat(theme): add shape-token scale and normalise radii, finish dark s…
Clupai8o0 Sep 11, 2026
ee953c5
fix(ui): calendar modal + confirm dialog polish, home button layout, …
Clupai8o0 Sep 11, 2026
b8619eb
fix(home): unit card handles long names; label the reminder save button
Clupai8o0 Sep 11, 2026
1b3db6a
style(theme): brighten the active tab label and ink bar
Clupai8o0 Sep 11, 2026
de31bbd
style(theme): sit the dark paginator on the page token
Clupai8o0 Sep 11, 2026
4641c22
style(theme): use the honoured tab token and force the active label b…
Clupai8o0 Sep 11, 2026
c365cb3
style(dashboard): calm the cross-unit column header in dark
Clupai8o0 Sep 11, 2026
ff3916e
fix(units): make the view-all units/projects table mobile friendly
Clupai8o0 Sep 12, 2026
9287467
fix(profile): hide non-editable Username and Student ID from profile …
Clupai8o0 Sep 12, 2026
863c05c
fix(profile): lock university-managed identity; polish notification s…
Clupai8o0 Sep 12, 2026
1ccbb95
fix(profile): drop Preferred Name and the "set up your profile" subtitle
Clupai8o0 Sep 12, 2026
f23a6c0
Remove the calendar icon from the toolbar, keep it in the account menu
Clupai8o0 Sep 12, 2026
d00e336
Refine the project progress dashboard layout and mobile density
Clupai8o0 Sep 12, 2026
839916d
Give the engagement passport distinct empty, loading and error states
Clupai8o0 Sep 12, 2026
0c13285
Make the progress dashboard grid respond to its pane, not the viewport
Clupai8o0 Sep 12, 2026
6204ece
Lay the calendar export grade and download button on one row
Clupai8o0 Sep 12, 2026
63fadec
Tint the task status card action buttons with the status colour
Clupai8o0 Sep 12, 2026
14daa53
Give the dashboard an inline-size container and split it at 48rem
Clupai8o0 Sep 12, 2026
65760d5
Keep the calendar export field and button on one row in narrow cards
Clupai8o0 Sep 12, 2026
28013c3
Make the task status tiles a container grid that adapts to the card w…
Clupai8o0 Sep 12, 2026
976dc70
Lay the task status tiles out two to a row
Clupai8o0 Sep 13, 2026
8b95489
Merge the grade cards into one plan card with tips for new students
Clupai8o0 Sep 13, 2026
9ad0f8b
Test the calendar from the account menu now the toolbar button is gone
Clupai8o0 Sep 13, 2026
764e96f
Apply the lint formatter and attribute order to templates
Clupai8o0 Sep 13, 2026
843a878
Draw every status icon in white
Clupai8o0 Sep 13, 2026
711ec5b
fix(theme): keep task-status option glyphs visible in dark mode
Clupai8o0 Sep 11, 2026
c44e4fc
Draw the due-soon clock badge in white to match the status icons
Clupai8o0 Sep 13, 2026
d35cf8e
Give every status white icons and text on darker fills, in circles
Clupai8o0 Sep 13, 2026
95e25fa
Ring the task list badges so they stand off the status circle
Clupai8o0 Sep 13, 2026
ac202b6
Keep status marks on the page vivid enough in dark, and give badges room
Clupai8o0 Sep 13, 2026
48cfde0
Draw the planner prerequisite links in the status graphic colours
Clupai8o0 Sep 13, 2026
f7ea4c7
Restyle the cross-unit dashboard as calm unit cards
Clupai8o0 Sep 13, 2026
52d1d44
Put the demo banner above the header
Clupai8o0 Sep 13, 2026
f48f058
Give each unit card on the dashboard its own colour band
Clupai8o0 Sep 13, 2026
cda399b
Pick the dashboard due dates from a calendar
Clupai8o0 Sep 13, 2026
ac0247d
Draw bigger status circles in the dashboard rows
Clupai8o0 Sep 13, 2026
c4148ea
Show a plain question mark for Need Help
Clupai8o0 Sep 13, 2026
64334e4
Fit the whole task code in its tile
Clupai8o0 Sep 13, 2026
1aaeb1f
Give the progress burndown its own row
Clupai8o0 Sep 13, 2026
c959388
Open the linked task when a notification crosses units
Clupai8o0 Sep 13, 2026
89a0881
Line up the portfolio status circle with the task rows
Clupai8o0 Sep 13, 2026
5084a4f
Keep full-height screens inside the window under the demo banner
Clupai8o0 Sep 13, 2026
909b574
Add a full-screen option to the task chat
Clupai8o0 Sep 13, 2026
641e06a
Show the task code in the task card's details line
Clupai8o0 Sep 13, 2026
14db564
Give the task list status circles room from the edge
Clupai8o0 Sep 13, 2026
932b7e0
Space the progress card subtitles from their content
Clupai8o0 Sep 13, 2026
bf4055d
Restyle the Peer Progress Indicator to match the other task cards
Clupai8o0 Sep 13, 2026
6448add
Keep text readable on filled warning and error headers in dark
Clupai8o0 Sep 13, 2026
a246f9c
Rework the Task Planner page
Clupai8o0 Sep 13, 2026
548bbe7
Stub the project lookup the phone layout reads in the dashboard spec
Clupai8o0 Sep 13, 2026
7546fe0
Let sign out finish when no service worker controls the page
Clupai8o0 Sep 13, 2026
20d9157
Keep the status circle clear of its badges in the task list
Clupai8o0 Sep 13, 2026
990983c
Give the task chat a header row, wider bubbles in full screen and eve…
Clupai8o0 Sep 13, 2026
5f43556
Show the task's dates as a timeline and its actions in one row
Clupai8o0 Sep 13, 2026
32402d8
Even out the gaps between the task cards
Clupai8o0 Sep 13, 2026
4cc4879
Show the full length of the peer progress bars in dark
Clupai8o0 Sep 13, 2026
22176dc
Replace the PDF search field with a pill and add full screen
Clupai8o0 Sep 13, 2026
ea65984
Rework the portfolio wizard
Clupai8o0 Sep 13, 2026
77b9233
Rework the staff student list so it fits the page and shows real prog…
Clupai8o0 Sep 13, 2026
c2ed7be
Give the staff Groups page a proper header and a way forward when empty
Clupai8o0 Sep 13, 2026
2959659
Rework the group list and stop it going stale or blank
Clupai8o0 Sep 13, 2026
16c383c
Rework the group members card and keep renames and members in step
Clupai8o0 Sep 13, 2026
33eb389
Make the team contribution rating keyboard friendly and keep its shar…
Clupai8o0 Sep 13, 2026
487cc9f
Put focus back when a clear or show-all button removes itself
Clupai8o0 Sep 13, 2026
129f3f3
Open a newly created group only while its set is still on screen
Clupai8o0 Sep 13, 2026
830c2bb
Test that the contribution members load once through the first binding
Clupai8o0 Sep 13, 2026
b13965e
Keep the grade circle visible in dark
Clupai8o0 Sep 13, 2026
6662808
Remove the unused AngularJS analytics template
Clupai8o0 Sep 13, 2026
c401e83
Show the alert when a tutor times download fails
Clupai8o0 Sep 13, 2026
c951ce9
Give unit analytics a page header and group the reports
Clupai8o0 Sep 13, 2026
08003a9
Rework the marking sessions calendar on unit analytics
Clupai8o0 Sep 13, 2026
121b0a9
Name the picked tutor when their sessions are missing from new dates
Clupai8o0 Sep 13, 2026
e637ae3
Keep the date picker open until both days are picked
Clupai8o0 Sep 13, 2026
5ee6c45
Keep today and the day dividers readable in dark mode
Clupai8o0 Sep 13, 2026
1227ab2
Mark tutorial sessions on the calendar again
Clupai8o0 Sep 13, 2026
af42a96
Give short marking sessions room for their label
Clupai8o0 Sep 13, 2026
ceb2253
Stop the inbox task pane crashing when a tutorial has no stream
Clupai8o0 Sep 13, 2026
8a554e3
Load the unit's tasks before showing the unit task list
Clupai8o0 Sep 13, 2026
fa67b62
Give the staff task list a header, calm filters and real empty states
Clupai8o0 Sep 13, 2026
815cc82
Lay the inbox out as cards and give each pane a real empty state
Clupai8o0 Sep 13, 2026
eefab37
Name every marking button and say plainly when no task is selected
Clupai8o0 Sep 13, 2026
6862e4b
Show the unit task list and the selected task side by side
Clupai8o0 Sep 13, 2026
30b4d97
Keep the first task tabs reachable when the tab row overflows
Clupai8o0 Sep 13, 2026
3f57d0a
Fix four model bugs the staff pages ran into
Clupai8o0 Sep 13, 2026
9b56baa
Hide the decorative icons in the header's page menu
Clupai8o0 Sep 13, 2026
cd54c88
Colour the task list badges from theme tokens
Clupai8o0 Sep 13, 2026
d22a82c
Stop the home page throwing when a project has no unit
Clupai8o0 Sep 13, 2026
a2076f3
Give staff a real home page with a card for each unit they teach
Clupai8o0 Sep 13, 2026
8d3ef13
Rework the unit lists and fix what they got wrong
Clupai8o0 Sep 13, 2026
66ebd79
Turn the discussion and check-in pages into real pages
Clupai8o0 Sep 13, 2026
6f218c6
Quieten the unit loading state and announce it
Clupai8o0 Sep 13, 2026
53912e6
Fix the course launch pages and give their buttons names
Clupai8o0 Sep 13, 2026
a14cd20
Stop late answers and overlapping camera starts on the discussion page
Clupai8o0 Sep 13, 2026
b5353ca
Bind the student lookup to its text and claim the camera before waiting
Clupai8o0 Sep 13, 2026
ba5284b
Give unit administration a page header and linked tabs
Clupai8o0 Sep 13, 2026
aafe668
Split unit details into sections that each save on their own
Clupai8o0 Sep 13, 2026
72bdb88
Tidy the staff tab and stop it breaking without a main convenor
Clupai8o0 Sep 13, 2026
48bd3f0
Show every tutorial and keep the add row after a failed save
Clupai8o0 Sep 13, 2026
431379a
Make the students tab sortable by name and usable by keyboard
Clupai8o0 Sep 13, 2026
56dd8ea
Keep learning outcomes in step with the task or unit being edited
Clupai8o0 Sep 13, 2026
f257208
Cover the student campus and tutorial pickers with keyboard specs
Clupai8o0 Sep 13, 2026
aafcf85
Keep edits made during a save on the unit details page
Clupai8o0 Sep 13, 2026
4463742
Do not list a stream twice when two are renamed at once
Clupai8o0 Sep 13, 2026
52b7d43
Offer five students a page again on the students tab
Clupai8o0 Sep 13, 2026
441c0ca
Test the enrolled box and the mentor list as a convenor uses them
Clupai8o0 Sep 13, 2026
2c6456c
Make the unit administration page a block element
Clupai8o0 Sep 13, 2026
102b1d0
Check the grade order itself in the rename guard spec
Clupai8o0 Sep 13, 2026
1e70196
Give the task editor one save bar and a Discard that really discards
Clupai8o0 Sep 13, 2026
e1f4cfe
Lay out the task details, dates and marking as short forms
Clupai8o0 Sep 13, 2026
b7b4d18
Keep each file to submit on its own key
Clupai8o0 Sep 13, 2026
1b37f4d
Accept ZIP uploads from Windows and ask before deleting task files
Clupai8o0 Sep 13, 2026
38b4d60
Fix editing discussion prompts and removing prerequisites
Clupai8o0 Sep 13, 2026
a12e47d
Tidy the automated checks and other options sections
Clupai8o0 Sep 13, 2026
a9f9c61
Rework the group sets tab and refresh groups after a CSV import
Clupai8o0 Sep 13, 2026
cd0acd5
Rework the communications tab and ask before deleting rules and sets
Clupai8o0 Sep 13, 2026
63e5612
Rework the rollover page and keep the new unit's dates on the right day
Clupai8o0 Sep 13, 2026
ec198c7
Keep Discard on the saved values after the Tasks tab is reopened
Clupai8o0 Sep 13, 2026
acb4c40
Name the table checkboxes and selects and keep drop zones inside thei…
Clupai8o0 Sep 13, 2026
29fe139
Show imported groups without leaving the group sets tab
Clupai8o0 Sep 13, 2026
9072ef2
Say when the communication sets fail to load and offer to try again
Clupai8o0 Sep 13, 2026
94203b2
Put the group sets card headings one level under the tab title
Clupai8o0 Sep 13, 2026
2b46653
Treat an imported task list as saved and warn before it replaces edits
Clupai8o0 Sep 13, 2026
8ece7d7
Stop adding a prerequisite from wiping unsaved task edits
Clupai8o0 Sep 13, 2026
ab0c52c
Clear the open group when another group set is shown
Clupai8o0 Sep 13, 2026
b08e817
Let a task be switched back from group work to individual work
Clupai8o0 Sep 13, 2026
6baa2fa
Hand the page background back to the stylesheet after the inbox
Clupai8o0 Sep 13, 2026
b82a8d7
Keep a long file name inside the file drop zone on a phone
Clupai8o0 Sep 13, 2026
65709aa
Remove stray console.log calls from the unit and task refresh
Clupai8o0 Sep 13, 2026
b971bf8
Name the grades upload properly and refresh after an import
Clupai8o0 Sep 13, 2026
eb2bd25
Rework the portfolio list
Clupai8o0 Sep 13, 2026
efe487c
Show the portfolio in a card and explain when there is none
Clupai8o0 Sep 13, 2026
d95f860
Drop the dead grade code from the portfolio progress tab
Clupai8o0 Sep 13, 2026
d2c6c2e
Give each student in the portfolios page a header and real tabs
Clupai8o0 Sep 13, 2026
062fa01
Make the portfolio grade tab clear about what is saved
Clupai8o0 Sep 13, 2026
a15755a
Rework the D2L grade transfer dialog
Clupai8o0 Sep 13, 2026
bcbcf29
Put back the old rationale when a grade fails to save
Clupai8o0 Sep 13, 2026
07839db
Let the staff notes composer grow and make its close a button
Clupai8o0 Sep 13, 2026
5b06134
Fix a success shown as an error, a read-out icon and a spelling
Clupai8o0 Sep 13, 2026
f5fd7e4
Let the PDF toolbar wrap on a phone
Clupai8o0 Sep 13, 2026
a834452
Line the admin Tasks tab up with the rest of unit administration
Clupai8o0 Sep 13, 2026
3bc0632
Set the short session height through the calendar itself
Clupai8o0 Sep 13, 2026
0c3da86
Keep hidden table labels inside their scroll boxes
Clupai8o0 Sep 13, 2026
0c6ecf4
Share one AppInjector stand-in across specs
Clupai8o0 Sep 13, 2026
db6e6e9
fix: remove machine-specific node_modules symlink
maplefoxgit Sep 14, 2026
c7936b9
fix(theme): reconcile menu polish with the current theme base
maplefoxgit Sep 14, 2026
7bc6069
fix(theme): reconcile PR #195 with the current theme base
maplefoxgit Sep 14, 2026
4619cdc
fix(theme): reconcile PR #198 with the current theme base
maplefoxgit Sep 14, 2026
070ffae
fix(tasks): preserve unresolved group assignments on save
maplefoxgit Sep 14, 2026
30b2f88
Preserve reviewed decimal-only learning outcome numbering
maplefoxgit Sep 14, 2026
3503bc1
Locally validate PR #185 with the reviewed batch
maplefoxgit Sep 14, 2026
7eae561
Locally validate PR #186 with the reviewed batch
maplefoxgit Sep 14, 2026
eb97c15
Locally validate PR #187 with the reviewed batch
maplefoxgit Sep 14, 2026
f4fadd1
Locally validate PR #188 with the reviewed batch
maplefoxgit Sep 14, 2026
e0376f5
Preserve both reviewed changes and regression coverage
maplefoxgit Sep 14, 2026
e7a21c0
Locally validate PR #201 with the reviewed batch
maplefoxgit Sep 14, 2026
320b78b
Locally validate PR #202 with the reviewed batch
maplefoxgit Sep 14, 2026
59e6252
Keep the theme toggle with the new header breakpoint binding
maplefoxgit Sep 14, 2026
87f0200
Locally validate PR #204 with the reviewed batch
maplefoxgit Sep 14, 2026
d66b6d4
Locally validate PR #205 with the reviewed batch
maplefoxgit Sep 14, 2026
08e48ad
Locally validate PR #206 with the reviewed batch
maplefoxgit Sep 14, 2026
67931f8
Locally validate PR #207 with the reviewed batch
maplefoxgit Sep 14, 2026
6e4c19a
Locally validate PR #208 with the reviewed batch
maplefoxgit Sep 14, 2026
c9732fd
Locally validate PR #209 with the reviewed batch
maplefoxgit Sep 14, 2026
09b2f05
Locally validate PR #210 with the reviewed batch
maplefoxgit Sep 14, 2026
7d1cf17
Preserve reviewed identity tests and accessible calendar subscription
maplefoxgit Sep 14, 2026
30d985f
Retain both equivalent comment tests once
maplefoxgit Sep 14, 2026
290bb93
Locally validate PR #212 with the reviewed batch
maplefoxgit Sep 14, 2026
162743c
Render profile link tests with combined identity validation
maplefoxgit Sep 14, 2026
cb67984
Reconcile reviewed web fixes with the theme redesign
maplefoxgit Sep 14, 2026
9222387
fix(theme): preserve profile validation and current calendar target
maplefoxgit Sep 14, 2026
478d4cf
fix(web): reconcile mobile client with reviewed changes
maplefoxgit Sep 14, 2026
b9dd75c
Merge commit 'aa12fb2d5285c347de4c1de8c5e7698091f85108' into review/w…
maplefoxgit Sep 14, 2026
18b54cd
merge: reconcile reviewed mobile workflow with theme improvements
maplefoxgit Sep 14, 2026
2ce4263
Reconcile PR #195 with reviewed theme and mobile integration
maplefoxgit Sep 14, 2026
20ebeb2
Reconcile PR #198 with reviewed theme and mobile integration
maplefoxgit Sep 14, 2026
573e2e3
Reconcile PR #200 with reviewed theme and mobile integration
maplefoxgit Sep 14, 2026
f142930
fix(theme): give status circles room around their icon
Clupai8o0 Sep 14, 2026
9012c5b
fix(inbox): even frame, centred row options and unclipped row icons
Clupai8o0 Sep 14, 2026
fe50514
fix(ui): stop the engagement card's small icons clipping
Clupai8o0 Sep 14, 2026
d1a8728
fix(comments): make other people's chat bubbles visible in light mode
Clupai8o0 Sep 14, 2026
6e7ec9e
fix(tasks): lay out the quality dialog as a dialog with even padding
Clupai8o0 Sep 14, 2026
cddebd9
fix(theme): put Material's dark tables and toggles on the slate palette
Clupai8o0 Sep 14, 2026
1dcc165
fix(admin): match the Tasks tab heading to the other tabs
Clupai8o0 Sep 14, 2026
7ad5bdf
Merge pull request #195 from ontrack-features-t2-2026/fix/profile-for…
maplefoxgit Sep 14, 2026
57165ee
Merge pull request #198 from ontrack-features-t2-2026/fix/task-subtab…
maplefoxgit Sep 14, 2026
a76ca70
Merge pull request #200 from ontrack-features-t2-2026/fix/menu-overla…
maplefoxgit Sep 14, 2026
414e6cd
fix(tasks): give the history tab a header, empty state and retry
Clupai8o0 Sep 14, 2026
ea8b845
refactor(tasks): share the token expansion panel styles
Clupai8o0 Sep 14, 2026
0004e61
fix(tasks): give the similarities tab a header and empty state
Clupai8o0 Sep 14, 2026
551502e
fix(notes): give the student notes tab a header and tidy the notes
Clupai8o0 Sep 14, 2026
0d24773
fix(notes): give the moderation notes tab and dialog a tidy layout
Clupai8o0 Sep 14, 2026
042a390
fix(notes): tint the reply context so it shows in both themes
Clupai8o0 Sep 14, 2026
b218914
fix(notes): keep the note composer reachable and focusable
Clupai8o0 Sep 14, 2026
f4705c6
fix(notes): reset the staff notes when the student changes
Clupai8o0 Sep 14, 2026
2a5e966
fix(tasks): keep history refresh focusable and drop the dialog's seco…
Clupai8o0 Sep 14, 2026
149be85
fix(tasks): move focus to the first similarity when the list closes
Clupai8o0 Sep 14, 2026
e5014ee
test(notes): name the notes view layout tests for what they check
Clupai8o0 Sep 14, 2026
4211191
fix(tasks): say when history and similarities appear
Clupai8o0 Sep 14, 2026
6b10b91
fix(tasks): show a similarity report at a readable height
Clupai8o0 Sep 14, 2026
b74a73e
fix(a11y): draw one focus outline on Material form fields
Clupai8o0 Sep 14, 2026
6060b33
fix(projects): give staff the student on a student's page
Clupai8o0 Sep 14, 2026
f3fba1e
fix(notes): stop the moderation notes tab throwing before the student…
Clupai8o0 Sep 14, 2026
0f26e1d
fix(pdf): theme the viewer toolbar and fill a phone screen
Clupai8o0 Sep 14, 2026
e7f39da
fix(tasks): show the whole task details and theme the task list filters
Clupai8o0 Sep 14, 2026
6e3724c
fix(comments): give the message its own row in a narrow chat panel
Clupai8o0 Sep 14, 2026
e1420c4
fix(tasks): let the submission PDF scroll and take the panel
Clupai8o0 Sep 14, 2026
1efdba5
fix(tasks): draw the status filter's chevron inside its pill
Clupai8o0 Sep 14, 2026
cdc3b34
fix(dashboard): show four main task statuses and only the others in use
Clupai8o0 Sep 14, 2026
a7dcb51
feat(home): give students the same unit cards as staff
Clupai8o0 Sep 14, 2026
af27d10
fix(tasks): move the task list badges beside the status circle
Clupai8o0 Sep 14, 2026
d65bc5d
test(dashboard): check each status tile pairs its fill with its measu…
Clupai8o0 Sep 14, 2026
0b2a8a0
fix(projects): show a failed project load instead of an endless skeleton
Clupai8o0 Sep 14, 2026
827b445
merge: bring 11.0.x into the theme redesign
Clupai8o0 Sep 14, 2026
b8f4336
feat(notifications): show tutors' help and extension request notifica…
Clupai8o0 Sep 14, 2026
60f7cfa
fix(theme): dark mode for notifications, startup screens and skeletons
Clupai8o0 Sep 14, 2026
a5c9d56
merge: bring 11.0.x (unit hub, #212) into the theme redesign
Clupai8o0 Sep 14, 2026
8e122e6
fix(tasks): keep the new comment count on the status circle inside th…
Clupai8o0 Sep 14, 2026
1ec29ef
fix(notifications): draw the due soon icon from a name the icon font has
Clupai8o0 Sep 14, 2026
521061a
Merge branch '11.0.x' into theme/status-and-globals
Clupai8o0 Sep 17, 2026
bd0ade6
test(inbox): point the empty-state tests at the markup the merge reso…
Clupai8o0 Sep 17, 2026
69b8960
chore(theme): merge 11.0.x into the theme redesign
Clupai Sep 27, 2026
c75a8ae
fix(tasks): guard the status colour when a task has no status class
Clupai Sep 27, 2026
933e319
fix: clear the lint errors from the 11.0.x merge
Clupai Sep 27, 2026
113f1c0
test: align specs with the redesign markup and the 11.0.x mocks
Clupai Sep 27, 2026
dc24743
fix(home): restore the unit link and progress names from 11.0.x
Clupai Sep 27, 2026
1410712
style(theme): take the onboarding, Course Flow and PPI shadows from t…
Clupai Sep 27, 2026
cab60d1
fix: restore the mentor clear and calendar toggle event from 11.0.x
Clupai Sep 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
130 changes: 130 additions & 0 deletions docs/evidence/batch-01/measure-startup.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import {performance} from 'node:perf_hooks';

const baseUrl = process.env.STARTUP_BASE_URL ?? 'http://localhost:4200';
const username = process.env.STARTUP_TEST_USERNAME;
const password = process.env.STARTUP_TEST_PASSWORD;
const runs = Number(process.env.STARTUP_RUNS ?? 5);

if (!username || !password) {
throw new Error(
'Set STARTUP_TEST_USERNAME and STARTUP_TEST_PASSWORD for a local synthetic user.',
);
}

const authStartedAt = performance.now();
const authResponse = await fetch(`${baseUrl}/api/auth`, {
method: 'POST',
headers: {'content-type': 'application/json'},
body: JSON.stringify({username, password, remember: false}),
});
const authBody = await authResponse.json();
if (!authResponse.ok || !authBody.auth_token) {
throw new Error(`Synthetic sign-in failed with HTTP ${authResponse.status}.`);
}

const authMs = performance.now() - authStartedAt;
const requestHeaders = {
'Auth-Token': authBody.auth_token,
Username: authBody.user.username,
};

async function request(name, path) {
const startedAt = performance.now();
const response = await fetch(`${baseUrl}${path}`, {headers: requestHeaders});
await response.arrayBuffer();
const durationMs = performance.now() - startedAt;
if (!response.ok) {
throw new Error(`${name} failed with HTTP ${response.status}.`);
}
return {name, durationMs: round(durationMs), status: response.status};
}

async function replayBefore() {
const startedAt = performance.now();
const requests = [];
requests.push(await request('settings', '/api/settings'));
requests.push(
...(await Promise.all([
request('campuses', '/api/campuses/'),
request('teaching-periods', '/api/teaching_periods/'),
])),
);
requests.push(await request('unit-roles', '/api/unit_roles/'));
requests.push(
await request(
'projects',
'/api/projects/?include_inactive=false&include_task_definitions=true',
),
);
await new Promise((resolve) => setTimeout(resolve, 800));
return {mode: 'before', totalMs: round(performance.now() - startedAt), requests};
}

async function replayAfter() {
const startedAt = performance.now();
const requests = [];
requests.push(await request('settings', '/api/settings'));
requests.push(
...(await Promise.all([
request('campuses', '/api/campuses/'),
request('teaching-periods', '/api/teaching_periods/'),
])),
);
requests.push(
...(await Promise.all([
request('unit-roles', '/api/unit_roles/'),
request('projects', '/api/projects/?include_inactive=false&include_task_definitions=true'),
])),
);
return {mode: 'after', totalMs: round(performance.now() - startedAt), requests};
}

const samples = [];
for (let run = 1; run <= runs; run += 1) {
const pair = run % 2 === 1 ? [replayBefore, replayAfter] : [replayAfter, replayBefore];
for (const replay of pair) {
samples.push({run, ...(await replay())});
}
}

const beforeTotals = samples.filter(({mode}) => mode === 'before').map(({totalMs}) => totalMs);
const afterTotals = samples.filter(({mode}) => mode === 'after').map(({totalMs}) => totalMs);

console.log(
JSON.stringify(
{
capturedAt: new Date().toISOString(),
baseUrl,
runs,
authenticationMs: round(authMs),
method: {
before: 'settings; campuses + teaching periods; unit roles; projects; fixed 800 ms wait',
after: 'settings; campuses + teaching periods; unit roles + projects; no fixed wait',
note: 'Paired live-API orchestration replay. It measures the startup request contract, not paint time.',
},
summary: {
beforeMedianMs: median(beforeTotals),
afterMedianMs: median(afterTotals),
medianReductionMs: round(median(beforeTotals) - median(afterTotals)),
medianReductionPercent: round(
((median(beforeTotals) - median(afterTotals)) / median(beforeTotals)) * 100,
),
},
samples,
},
null,
2,
),
);

function median(values) {
const sorted = [...values].sort((left, right) => left - right);
const middle = Math.floor(sorted.length / 2);
return sorted.length % 2 === 0
? round((sorted[middle - 1] + sorted[middle]) / 2)
: sorted[middle];
}

function round(value) {
return Math.round(value * 10) / 10;
}
142 changes: 142 additions & 0 deletions docs/evidence/batch-01/startup-live-api-before-after.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
{
"capturedAt": "2026-08-29T02:40:14.749Z",
"timezone": "Australia/Melbourne",
"frontendPath": "/Users/ryan/Downloads/test-codex/phone-evidence-20260828/doubtfire-web",
"frontendRevision": "024e12ee15e7c0309d36a621aff29b98bb4d8f6e",
"baseUrl": "http://localhost:4200",
"runs": 5,
"authenticationMs": 842.8,
"method": {
"before": "settings; campuses + teaching periods; unit roles; projects; fixed 800 ms wait",
"after": "settings; campuses + teaching periods; unit roles + projects; no fixed wait",
"note": "Paired live-API orchestration replay. It measures the startup request contract, not paint time."
},
"summary": {
"beforeMedianMs": 1125.1,
"afterMedianMs": 364.8,
"medianReductionMs": 760.3,
"medianReductionPercent": 67.6
},
"samples": [
{
"run": 1,
"mode": "before",
"totalMs": 2118.8,
"requests": [
{"name": "settings", "durationMs": 101.5, "status": 200},
{"name": "campuses", "durationMs": 40.9, "status": 200},
{"name": "teaching-periods", "durationMs": 101.3, "status": 200},
{"name": "unit-roles", "durationMs": 41.2, "status": 200},
{"name": "projects", "durationMs": 1071.1, "status": 200}
]
},
{
"run": 1,
"mode": "after",
"totalMs": 400.2,
"requests": [
{"name": "settings", "durationMs": 54.5, "status": 200},
{"name": "campuses", "durationMs": 29.4, "status": 200},
{"name": "teaching-periods", "durationMs": 35.3, "status": 200},
{"name": "unit-roles", "durationMs": 41.9, "status": 200},
{"name": "projects", "durationMs": 308.9, "status": 200}
]
},
{
"run": 2,
"mode": "after",
"totalMs": 364.8,
"requests": [
{"name": "settings", "durationMs": 39.6, "status": 200},
{"name": "campuses", "durationMs": 18.1, "status": 200},
{"name": "teaching-periods", "durationMs": 66.4, "status": 200},
{"name": "unit-roles", "durationMs": 37.5, "status": 200},
{"name": "projects", "durationMs": 257.6, "status": 200}
]
},
{
"run": 2,
"mode": "before",
"totalMs": 1146.2,
"requests": [
{"name": "settings", "durationMs": 14.6, "status": 200},
{"name": "campuses", "durationMs": 9.9, "status": 200},
{"name": "teaching-periods", "durationMs": 49, "status": 200},
{"name": "unit-roles", "durationMs": 38.7, "status": 200},
{"name": "projects", "durationMs": 241.5, "status": 200}
]
},
{
"run": 3,
"mode": "before",
"totalMs": 1125.1,
"requests": [
{"name": "settings", "durationMs": 41.9, "status": 200},
{"name": "campuses", "durationMs": 19.2, "status": 200},
{"name": "teaching-periods", "durationMs": 25.8, "status": 200},
{"name": "unit-roles", "durationMs": 20.5, "status": 200},
{"name": "projects", "durationMs": 220.4, "status": 200}
]
},
{
"run": 3,
"mode": "after",
"totalMs": 588.8,
"requests": [
{"name": "settings", "durationMs": 92.5, "status": 200},
{"name": "campuses", "durationMs": 64.3, "status": 200},
{"name": "teaching-periods", "durationMs": 103.4, "status": 200},
{"name": "unit-roles", "durationMs": 65, "status": 200},
{"name": "projects", "durationMs": 391.6, "status": 200}
]
},
{
"run": 4,
"mode": "after",
"totalMs": 333.8,
"requests": [
{"name": "settings", "durationMs": 20.6, "status": 200},
{"name": "campuses", "durationMs": 21.3, "status": 200},
{"name": "teaching-periods", "durationMs": 27.1, "status": 200},
{"name": "unit-roles", "durationMs": 34, "status": 200},
{"name": "projects", "durationMs": 285.4, "status": 200}
]
},
{
"run": 4,
"mode": "before",
"totalMs": 1123.9,
"requests": [
{"name": "settings", "durationMs": 20, "status": 200},
{"name": "campuses", "durationMs": 26.2, "status": 200},
{"name": "teaching-periods", "durationMs": 38.2, "status": 200},
{"name": "unit-roles", "durationMs": 30.4, "status": 200},
{"name": "projects", "durationMs": 229.6, "status": 200}
]
},
{
"run": 5,
"mode": "before",
"totalMs": 1095,
"requests": [
{"name": "settings", "durationMs": 24, "status": 200},
{"name": "campuses", "durationMs": 13.4, "status": 200},
{"name": "teaching-periods", "durationMs": 20.6, "status": 200},
{"name": "unit-roles", "durationMs": 20.8, "status": 200},
{"name": "projects", "durationMs": 223.1, "status": 200}
]
},
{
"run": 5,
"mode": "after",
"totalMs": 193.6,
"requests": [
{"name": "settings", "durationMs": 28.8, "status": 200},
{"name": "campuses", "durationMs": 14.1, "status": 200},
{"name": "teaching-periods", "durationMs": 17.7, "status": 200},
{"name": "unit-roles", "durationMs": 24.1, "status": 200},
{"name": "projects", "durationMs": 146.6, "status": 200}
]
}
]
}
Loading
Loading