Activity Search Phase 1#1875
Conversation
237d865 to
2a5f418
Compare
|
This feels very useful, so much potential here |
9e5e9c4 to
1849440
Compare
b91a810 to
34a44a1
Compare
8265694 to
c4a558e
Compare
|
@AaronPlave is working on testing this at larger scale (~100k-1M directives), will hold off on final approval until done |
@dandelany did some performance testing and found that with 500k activities search performance was usually under a few seconds with the exception of search with a sort on directives by plan name (requiring a join) with no other significant filters to reduce result set - in that case search was slower but maybe 5-10 seconds on my machine, which feels like acceptable performance. |
- Server-side pagination (offset + aggregate count) with first/prev/next/last controls - Expanded filters: plan name/owner, created_by, last-modified date range, scheduling-goal origin - Argument name dropdown driven by the selected model's activity type parameter schemas; narrows further when an activity type is selected - Server-side sort: AG Grid column state translated to nested Hasura order_by - All filter state encoded in URL query params (bookmarkable / shareable searches), initialized on load with deferred model-id resolution while subscription primes - Result table: tag chips, JSON arguments column, formatted timestamps via getShortISOForDate, plus toggleable Created At / Plan ID / Activity ID columns - Column picker (ActivityTableMenu) with show/hide all + reset; column state persisted via localStorage. Forward columnVisible / columnsReset events through SingleActionDataGrid so the picker can react - Search button always enabled; auto-search-on-load still gated on a non-empty filter
Adds persistColumnStateKey + transformColumnState props on DataGrid (forwarded through BulkAction/SingleActionDataGrid). WorkspaceFileBrowser drops its duplicated save/clear logic and rides its name-column processing through transformColumnState.
Replace maxOptionChars*8 width estimate with canvas measureText, reading the font off a hidden DOM ref so it tracks CSS. Pass items through RowVirtualizerFixed as a slot prop (fixes stale content when array changes in place). Add loading prop. TimelineItemList + mock updated for new virtualizer API.
Mission Model uses SearchableDropdown. Collapse pending-model state into a single selectedModelId (selectedModel derived). Inline subscription-error banner. Per-dropdown loading. Start Offset min/max filters. Argument Value defaults tooltip. Search always enabled, above Clear, sticky footer. 500ms-delayed spinner overlay over results; no-op local sort comparators avoid the flash before server-sorted data lands. SearchResults adopts the new persistColumnStateKey for column-state persistence.
UI / UX - Multi-select Activity Type filter (`_in` clause); arg-name dropdown handles multi - New filters: Last Modified By, Created After/Before, Plan Tag, Scheduling Goal - New columns: Model, Model ID, Absolute Start Time, Scheduling Goal - Column order regrouped: action → identity → plan/model → tagging → timing → audit → provenance - Open-in-plan: Svelte component cell, full-cell click, pinned-left icon column - Right-click context menu: "Copy N Activit(ies)" and "Open in plan" (single-select) - Click-drag column resize (no shift-key required) - Open-in-plan exempt from column picker and the "hide all" sweep Behavior fixes - Cross-plan paste respects the right-click paste-at-time even when the source activities' absolute times fall outside the target plan window - Arg value matching: JSON.parse + singleton-array sugar so typing `5` finds `XYZ: 5` and `XYZ: [1, 2, 5]`; numeric/bool branch covers all four shapes - Drop the `directive_id: id` gql alias — fixes Hasura sort error on Activity ID - DataGrid: querySelectorAll so the selected-row class stays in sync between center and pinned-left containers (fixes the two-tone selected row bug) Types / internals - ActivityDirectiveSearchResult now extends ActivityDirectiveDB instead of redefining shared fields; corrects applied_preset shape along the way - SEARCH_ACTIVITIES extends plan with mission_model, adds source_scheduling_goal, anchor_id, anchored_to_start, metadata for the clipboard mapping - Use ColumnPinnedType / SortDirection imports for the two literal ColDef fields
Activity directive ids are unique per-plan but not globally; cross-plan search results can collide on the bare id. Key the search results grid and the clipboard/paste anchor remap by (plan_id, id) so row identity, selection, and anchor preservation stay scoped to the source plan.
d5e1f32 to
012256d
Compare
|
dandelany
left a comment
There was a problem hiding this comment.
This is looking good, and we've done plenty of testing on it! The performance and UX on my local machine are great. I think it's ready to merge.
Added a few nonblocking comments below - one's easy, but for the others, the effort probably isn't worth the impact for V1.
| user, | ||
| ); | ||
|
|
||
| if (result) { |
There was a problem hiding this comment.
I think this can occasionally show incorrect results if you quickly change from a slow search to a fast search, the earlier slow results can come in after the fast ones and replace them as the "most recent" when they're not.
I consider this a nonblocker for this PR because you have to be trying pretty hard to make this happen, and this is an MVP feature, and the fix is nontrivial
| bind:dataGrid | ||
| bind:selectedItemIds | ||
| getRowId={getRowKey} | ||
| idKey="id" |
There was a problem hiding this comment.
confirmed the original bug was resolved - idKey should probably just be removed here in favor of getRowId for clarity, since it gets overridden when getRowId is provided
| return measureCanvasContext; | ||
| } | ||
|
|
||
| function measureMaxOptionWidth(opts: DropdownOptions): number { |
There was a problem hiding this comment.
It's annoying that we have to do this whole layout measuring dance... I think I understand why, due to the RowVirtualizer needing real static sizes? Let's ship it if there's not an easy alternative, and I'm guessing there's not. But worth thinking about the best pattern in future


Summary
New
/searchpage for finding activity directives across all plans, plus shared-component improvements that came out of building it.Search page
Filters (all bookmarkable via URL query params):
5matchesXYZ: 5andXYZ: [1, 2, 5]; arrays/structs accepted as JSON)Results:
Columns (default-visible unless noted):
Selection & cross-plan copy:
Shared changes
DataGrid:
persistColumnStateKey+transformColumnStateprops centralize column-state localStorage save/clearBulkActionDataGridandSingleActionDataGridtransformColumnStateSearchableDropdown:
measureTextwith font read off a hidden DOM ref (replaces themaxOptionChars * 8heuristic that overshot for proportional fonts)RowVirtualizerFixedas a slot prop so menus refresh while openloadingproptype="button"so Enter inside a sibling input no longer toggles the menuRowVirtualizerFixed:
itemsprop replacescount; slot exposesitemBug fixes & polish
querySelectorAllso pinned-left and center containers stay in sync (fixes two-tone selected row with pinned columns — affects every table with pinned columns, not just search)Test plan
TODO
Future Work
Future directions for this work could involve:
/searchpage