Conversation
|
Continuous integration check(s) failed. Please review the failing check's logs and make the necessary changes. |
There was a problem hiding this comment.
Pull request overview
Refactors user tag handling in the frontend away from DB.getSnapshot().tags / TagController into a new TanStack solid-db collection (collections/tags.ts), and updates multiple UI flows to consume the new API.
Changes:
- Introduce
frontend/src/ts/collections/tags.tsas the source of truth for tags (CRUD, active state, PB helpers). - Remove tag fields/types from snapshot and delete
TagController, updating call sites to use the new collection helpers. - Update multiple pages/modals to read/update tags and tag PBs via the new collection API.
Reviewed changes
Copilot reviewed 19 out of 20 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/static/contributors.json | JSON formatting tweak (closing bracket line). |
| frontend/src/ts/test/test-logic.ts | Build completed event now reads active tag IDs via getActiveTags(). |
| frontend/src/ts/test/result.ts | Result tag UI + tag PB logic migrated to tags collection helpers. |
| frontend/src/ts/test/pace-caret.ts | Pace caret “tagPb” now uses getActiveTagsPB() from tags collection. |
| frontend/src/ts/states/snapshot.ts | MiniSnapshot no longer omits tags since snapshot tags removed. |
| frontend/src/ts/pages/settings.ts | Settings tag list now reads/toggles via tags collection + live query. |
| frontend/src/ts/pages/account.ts | Account tag name rendering + filtering now uses tags collection lookups. |
| frontend/src/ts/modals/edit-tag.ts | Tag CRUD/PB-clear moved from direct Ape+snapshot mutation to tags collection helpers. |
| frontend/src/ts/modals/edit-result-tags.ts | Edit-result-tags modal now uses tags collection for tag list + PB recompute. |
| frontend/src/ts/modals/edit-preset.ts | Preset config change builder reads active tags via tags collection. |
| frontend/src/ts/event-handlers/test.ts | “Edit tags” button availability now based on getTags().length. |
| frontend/src/ts/elements/modes-notice.ts | Modes notice now renders active tags via getActiveTags(). |
| frontend/src/ts/elements/account/result-filters.ts | Result filter tag dropdown/options now sourced from tags collection. |
| frontend/src/ts/db.ts | Snapshot init seeds tags into new collection; DB tag PB helpers removed; tag removal now updates results only. |
| frontend/src/ts/controllers/tag-controller.ts | Deleted; functionality moved into collections/tags.ts. |
| frontend/src/ts/controllers/preset-controller.ts | Preset apply now clears/sets active tags via tags collection helpers. |
| frontend/src/ts/constants/default-snapshot.ts | Removes snapshot tag types/fields (SnapshotUserTag, Snapshot.tags). |
| frontend/src/ts/commandline/lists/tags.ts | Commandline tag toggling/clearing now uses tags collection helpers. |
| frontend/src/ts/collections/tags.ts | New tags collection: query, CRUD syncing, active tag localStorage, tag PB helpers. |
| seedData = userTags | ||
| .map((tag) => ({ | ||
| ...toTagItem(tag), | ||
| active: activeIds.includes(tag._id), | ||
| })) | ||
| .sort((a, b) => a.name.localeCompare(b.name)); | ||
|
|
There was a problem hiding this comment.
seedFromUserData only updates seedData + invalidates the query; it doesn’t synchronously populate tagsCollection. Code that runs immediately after login (e.g., authEvent snapshotUpdated handlers like result-filters loadTags) can observe getTags() as empty and initialize UI/filter state incorrectly. Consider writing the seeded tags directly into the collection/query cache (e.g., batch delete+insert into tagsCollection or queryClient.setQueryData) or otherwise exposing an async init that callers can await before using getTags().
| seedData = userTags | |
| .map((tag) => ({ | |
| ...toTagItem(tag), | |
| active: activeIds.includes(tag._id), | |
| })) | |
| .sort((a, b) => a.name.localeCompare(b.name)); | |
| const nextTags = userTags | |
| .map((tag) => ({ | |
| ...toTagItem(tag), | |
| active: activeIds.includes(tag._id), | |
| })) | |
| .sort((a, b) => a.name.localeCompare(b.name)); | |
| seedData = nextTags; | |
| for (const id of [...tagsCollection.keys()]) { | |
| tagsCollection.delete(id); | |
| } | |
| for (const tag of nextTags) { | |
| tagsCollection.set(tag._id, tag); | |
| } |
| onInsert: async ({ transaction }) => { | ||
| const newItems = transaction.mutations.map((m) => m.modified); | ||
|
|
||
| const serverItems = await Promise.all( | ||
| newItems.map(async (it) => { | ||
| const response = await Ape.users.createTag({ | ||
| body: { tagName: it.name }, | ||
| }); | ||
| if (response.status !== 200) { | ||
| throw new Error(`Failed to add tag: ${response.body.message}`); | ||
| } | ||
| return toTagItem(response.body.data); | ||
| }), | ||
| ); | ||
|
|
||
| tagsCollection.utils.writeBatch(() => { | ||
| serverItems.forEach((it) => tagsCollection.utils.writeInsert(it)); | ||
| }); | ||
| return { refetch: false }; | ||
| }, |
There was a problem hiding this comment.
insertTag inserts an item with a random _id, while onInsert also writeInserts the server-returned tag (with a different _id). Unless createCollection automatically reconciles these, this will leave the optimistic item behind and create duplicates. Safer pattern: delete/replace the optimistic IDs in onInsert (using transaction.mutations keys) or avoid client-generated IDs by creating the tag on the server first and then inserting the returned item.
| !isPartialPreset(presetToApply) || | ||
| presetToApply.settingGroups?.includes("behavior") | ||
| ) { | ||
| TagController.clear(true); | ||
| clearActiveTags(true); | ||
| if (presetToApply.config.tags) { | ||
| for (const tagId of presetToApply.config.tags) { | ||
| TagController.set(tagId, true, false); | ||
| setTagActive(tagId, true, false); | ||
| } | ||
| TagController.saveActiveToLocalStorage(); | ||
| saveActiveToLocalStorage(); | ||
| } |
There was a problem hiding this comment.
When applying presets, tag activation changes no longer call ModesNotice.update() (previously TagController.clear/set did). This will leave the test page notice stale after preset apply. Add an explicit ModesNotice.update() after tag updates (and keep localStorage save semantics consistent).
No description provided.