@flanksource/clicky-ui 0.3.40 → 0.3.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/dist/ai.cjs +10 -0
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.js +10 -0
- package/dist/ai.js.map +1 -1
- package/dist/components/AccordionList.cjs +5 -1
- package/dist/components/AccordionList.cjs.map +1 -1
- package/dist/components/AccordionList.d.ts +3 -1
- package/dist/components/AccordionList.d.ts.map +1 -1
- package/dist/components/AccordionList.js +5 -1
- package/dist/components/AccordionList.js.map +1 -1
- package/dist/components/JsonSchemaForm.cjs +9 -4
- package/dist/components/JsonSchemaForm.cjs.map +1 -1
- package/dist/components/JsonSchemaForm.d.ts +1 -1
- package/dist/components/JsonSchemaForm.d.ts.map +1 -1
- package/dist/components/JsonSchemaForm.js +8 -3
- package/dist/components/JsonSchemaForm.js.map +1 -1
- package/dist/components/json-schema-form-accordion-array.cjs +3 -1
- package/dist/components/json-schema-form-accordion-array.cjs.map +1 -1
- package/dist/components/json-schema-form-accordion-array.d.ts +4 -1
- package/dist/components/json-schema-form-accordion-array.d.ts.map +1 -1
- package/dist/components/json-schema-form-accordion-array.js +3 -1
- package/dist/components/json-schema-form-accordion-array.js.map +1 -1
- package/dist/components/json-schema-form-array-view.cjs +63 -0
- package/dist/components/json-schema-form-array-view.cjs.map +1 -0
- package/dist/components/json-schema-form-array-view.d.ts +21 -0
- package/dist/components/json-schema-form-array-view.d.ts.map +1 -0
- package/dist/components/json-schema-form-array-view.js +63 -0
- package/dist/components/json-schema-form-array-view.js.map +1 -0
- package/dist/components/json-schema-form-array.cjs +3 -7
- package/dist/components/json-schema-form-array.cjs.map +1 -1
- package/dist/components/json-schema-form-array.d.ts.map +1 -1
- package/dist/components/json-schema-form-array.js +3 -7
- package/dist/components/json-schema-form-array.js.map +1 -1
- package/dist/components/json-schema-form-conditionals.cjs +67 -0
- package/dist/components/json-schema-form-conditionals.cjs.map +1 -0
- package/dist/components/json-schema-form-conditionals.d.ts +9 -0
- package/dist/components/json-schema-form-conditionals.d.ts.map +1 -0
- package/dist/components/json-schema-form-conditionals.js +67 -0
- package/dist/components/json-schema-form-conditionals.js.map +1 -0
- package/dist/components/json-schema-form-defaults.cjs +68 -0
- package/dist/components/json-schema-form-defaults.cjs.map +1 -0
- package/dist/components/json-schema-form-defaults.d.ts +4 -0
- package/dist/components/json-schema-form-defaults.d.ts.map +1 -0
- package/dist/components/json-schema-form-defaults.js +68 -0
- package/dist/components/json-schema-form-defaults.js.map +1 -0
- package/dist/components/json-schema-form-errors.cjs +49 -31
- package/dist/components/json-schema-form-errors.cjs.map +1 -1
- package/dist/components/json-schema-form-errors.d.ts +4 -2
- package/dist/components/json-schema-form-errors.d.ts.map +1 -1
- package/dist/components/json-schema-form-errors.js +51 -33
- package/dist/components/json-schema-form-errors.js.map +1 -1
- package/dist/components/json-schema-form-filter.cjs +2 -1
- package/dist/components/json-schema-form-filter.cjs.map +1 -1
- package/dist/components/json-schema-form-filter.js +2 -1
- package/dist/components/json-schema-form-filter.js.map +1 -1
- package/dist/components/json-schema-form-item-summary.cjs +6 -2
- package/dist/components/json-schema-form-item-summary.cjs.map +1 -1
- package/dist/components/json-schema-form-item-summary.d.ts.map +1 -1
- package/dist/components/json-schema-form-item-summary.js +6 -2
- package/dist/components/json-schema-form-item-summary.js.map +1 -1
- package/dist/components/json-schema-form-layout.cjs +28 -19
- package/dist/components/json-schema-form-layout.cjs.map +1 -1
- package/dist/components/json-schema-form-layout.d.ts +8 -6
- package/dist/components/json-schema-form-layout.d.ts.map +1 -1
- package/dist/components/json-schema-form-layout.js +29 -20
- package/dist/components/json-schema-form-layout.js.map +1 -1
- package/dist/components/json-schema-form-listener-paths.cjs +52 -0
- package/dist/components/json-schema-form-listener-paths.cjs.map +1 -0
- package/dist/components/json-schema-form-listener-paths.d.ts +10 -0
- package/dist/components/json-schema-form-listener-paths.d.ts.map +1 -0
- package/dist/components/json-schema-form-listener-paths.js +52 -0
- package/dist/components/json-schema-form-listener-paths.js.map +1 -0
- package/dist/components/json-schema-form-listener-types.d.ts +22 -0
- package/dist/components/json-schema-form-listener-types.d.ts.map +1 -0
- package/dist/components/json-schema-form-listeners.cjs +250 -0
- package/dist/components/json-schema-form-listeners.cjs.map +1 -0
- package/dist/components/json-schema-form-listeners.d.ts +13 -0
- package/dist/components/json-schema-form-listeners.d.ts.map +1 -0
- package/dist/components/json-schema-form-listeners.js +250 -0
- package/dist/components/json-schema-form-listeners.js.map +1 -0
- package/dist/components/json-schema-form-object-array-view.cjs +62 -0
- package/dist/components/json-schema-form-object-array-view.cjs.map +1 -0
- package/dist/components/json-schema-form-object-array-view.d.ts +14 -0
- package/dist/components/json-schema-form-object-array-view.d.ts.map +1 -0
- package/dist/components/json-schema-form-object-array-view.js +62 -0
- package/dist/components/json-schema-form-object-array-view.js.map +1 -0
- package/dist/components/json-schema-form-object.cjs +3 -0
- package/dist/components/json-schema-form-object.cjs.map +1 -1
- package/dist/components/json-schema-form-object.d.ts.map +1 -1
- package/dist/components/json-schema-form-object.js +3 -0
- package/dist/components/json-schema-form-object.js.map +1 -1
- package/dist/components/json-schema-form-render.cjs +17 -9
- package/dist/components/json-schema-form-render.cjs.map +1 -1
- package/dist/components/json-schema-form-render.d.ts.map +1 -1
- package/dist/components/json-schema-form-render.js +19 -11
- package/dist/components/json-schema-form-render.js.map +1 -1
- package/dist/components/json-schema-form-resolve.cjs +6 -99
- package/dist/components/json-schema-form-resolve.cjs.map +1 -1
- package/dist/components/json-schema-form-resolve.d.ts +1 -8
- package/dist/components/json-schema-form-resolve.d.ts.map +1 -1
- package/dist/components/json-schema-form-resolve.js +5 -98
- package/dist/components/json-schema-form-resolve.js.map +1 -1
- package/dist/components/json-schema-form-runtime-types.d.ts +15 -0
- package/dist/components/json-schema-form-runtime-types.d.ts.map +1 -1
- package/dist/components/json-schema-form-table-array.cjs +67 -16
- package/dist/components/json-schema-form-table-array.cjs.map +1 -1
- package/dist/components/json-schema-form-table-array.d.ts +4 -1
- package/dist/components/json-schema-form-table-array.d.ts.map +1 -1
- package/dist/components/json-schema-form-table-array.js +70 -19
- package/dist/components/json-schema-form-table-array.js.map +1 -1
- package/dist/components/json-schema-form-types.d.ts +16 -0
- package/dist/components/json-schema-form-types.d.ts.map +1 -1
- package/dist/components/json-schema-form-utils.cjs +7 -1
- package/dist/components/json-schema-form-utils.cjs.map +1 -1
- package/dist/components/json-schema-form-utils.d.ts +2 -1
- package/dist/components/json-schema-form-utils.d.ts.map +1 -1
- package/dist/components/json-schema-form-utils.js +7 -1
- package/dist/components/json-schema-form-utils.js.map +1 -1
- package/dist/components.cjs +3 -2
- package/dist/components.cjs.map +1 -1
- package/dist/components.d.ts +3 -2
- package/dist/components.d.ts.map +1 -1
- package/dist/components.js +2 -1
- package/dist/components.js.map +1 -1
- package/dist/data/DataTable.cjs +9 -3
- package/dist/data/DataTable.cjs.map +1 -1
- package/dist/data/DataTable.d.ts +6 -0
- package/dist/data/DataTable.d.ts.map +1 -1
- package/dist/data/DataTable.js +9 -3
- package/dist/data/DataTable.js.map +1 -1
- package/dist/data/FixtureEditor/FixtureEditor.cjs +43 -24
- package/dist/data/FixtureEditor/FixtureEditor.cjs.map +1 -1
- package/dist/data/FixtureEditor/FixtureEditor.d.ts.map +1 -1
- package/dist/data/FixtureEditor/FixtureEditor.js +43 -24
- package/dist/data/FixtureEditor/FixtureEditor.js.map +1 -1
- package/dist/data/Tree.cjs +10 -2
- package/dist/data/Tree.cjs.map +1 -1
- package/dist/data/Tree.d.ts +6 -1
- package/dist/data/Tree.d.ts.map +1 -1
- package/dist/data/Tree.js +10 -2
- package/dist/data/Tree.js.map +1 -1
- package/dist/data/ai/SessionInspector.cjs +143 -167
- package/dist/data/ai/SessionInspector.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.collection-types.d.ts +5 -0
- package/dist/data/ai/SessionInspector.collection-types.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.collection.cjs +18 -5
- package/dist/data/ai/SessionInspector.collection.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.collection.d.ts +2 -0
- package/dist/data/ai/SessionInspector.collection.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.collection.fixtures.d.ts +6 -0
- package/dist/data/ai/SessionInspector.collection.fixtures.d.ts.map +1 -0
- package/dist/data/ai/SessionInspector.collection.js +18 -5
- package/dist/data/ai/SessionInspector.collection.js.map +1 -1
- package/dist/data/ai/SessionInspector.d.ts +24 -2
- package/dist/data/ai/SessionInspector.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.hierarchy-state.cjs +105 -7
- package/dist/data/ai/SessionInspector.hierarchy-state.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.hierarchy-state.d.ts +12 -1
- package/dist/data/ai/SessionInspector.hierarchy-state.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.hierarchy-state.js +107 -9
- package/dist/data/ai/SessionInspector.hierarchy-state.js.map +1 -1
- package/dist/data/ai/SessionInspector.hierarchy.cjs +1 -1
- package/dist/data/ai/SessionInspector.hierarchy.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.hierarchy.js +1 -1
- package/dist/data/ai/SessionInspector.hierarchy.js.map +1 -1
- package/dist/data/ai/SessionInspector.js +144 -168
- package/dist/data/ai/SessionInspector.js.map +1 -1
- package/dist/data/ai/SessionInspector.legacy.cjs +116 -0
- package/dist/data/ai/SessionInspector.legacy.cjs.map +1 -0
- package/dist/data/ai/SessionInspector.legacy.d.ts +19 -0
- package/dist/data/ai/SessionInspector.legacy.d.ts.map +1 -0
- package/dist/data/ai/SessionInspector.legacy.js +116 -0
- package/dist/data/ai/SessionInspector.legacy.js.map +1 -0
- package/dist/data/ai/SessionInspector.panels.cjs +3 -0
- package/dist/data/ai/SessionInspector.panels.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.panels.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.panels.js +3 -0
- package/dist/data/ai/SessionInspector.panels.js.map +1 -1
- package/dist/data/ai/SessionInspector.plan.cjs +29 -12
- package/dist/data/ai/SessionInspector.plan.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.plan.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.plan.js +30 -13
- package/dist/data/ai/SessionInspector.plan.js.map +1 -1
- package/dist/data/ai/SessionInspector.remote-view.cjs +44 -0
- package/dist/data/ai/SessionInspector.remote-view.cjs.map +1 -0
- package/dist/data/ai/SessionInspector.remote-view.d.ts +11 -0
- package/dist/data/ai/SessionInspector.remote-view.d.ts.map +1 -0
- package/dist/data/ai/SessionInspector.remote-view.js +44 -0
- package/dist/data/ai/SessionInspector.remote-view.js.map +1 -0
- package/dist/data/ai/SessionInspector.remote.cjs +275 -0
- package/dist/data/ai/SessionInspector.remote.cjs.map +1 -0
- package/dist/data/ai/SessionInspector.remote.d.ts +57 -0
- package/dist/data/ai/SessionInspector.remote.d.ts.map +1 -0
- package/dist/data/ai/SessionInspector.remote.js +275 -0
- package/dist/data/ai/SessionInspector.remote.js.map +1 -0
- package/dist/data/ai/SessionInspector.summary.cjs +0 -156
- package/dist/data/ai/SessionInspector.summary.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.summary.d.ts +0 -3
- package/dist/data/ai/SessionInspector.summary.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.summary.js +2 -158
- package/dist/data/ai/SessionInspector.summary.js.map +1 -1
- package/dist/data/ai/SessionInspector.tab-state.cjs +15 -0
- package/dist/data/ai/SessionInspector.tab-state.cjs.map +1 -0
- package/dist/data/ai/SessionInspector.tab-state.d.ts +3 -0
- package/dist/data/ai/SessionInspector.tab-state.d.ts.map +1 -0
- package/dist/data/ai/SessionInspector.tab-state.js +15 -0
- package/dist/data/ai/SessionInspector.tab-state.js.map +1 -0
- package/dist/data/ai/SessionInspector.tabs.model.cjs +31 -18
- package/dist/data/ai/SessionInspector.tabs.model.cjs.map +1 -1
- package/dist/data/ai/SessionInspector.tabs.model.d.ts +3 -1
- package/dist/data/ai/SessionInspector.tabs.model.d.ts.map +1 -1
- package/dist/data/ai/SessionInspector.tabs.model.js +32 -19
- package/dist/data/ai/SessionInspector.tabs.model.js.map +1 -1
- package/dist/data/ai/SessionInspector.verification.cjs +53 -0
- package/dist/data/ai/SessionInspector.verification.cjs.map +1 -0
- package/dist/data/ai/SessionInspector.verification.d.ts +7 -0
- package/dist/data/ai/SessionInspector.verification.d.ts.map +1 -0
- package/dist/data/ai/SessionInspector.verification.js +53 -0
- package/dist/data/ai/SessionInspector.verification.js.map +1 -0
- package/dist/data/ai/SessionViewer.model.cjs +7 -1
- package/dist/data/ai/SessionViewer.model.cjs.map +1 -1
- package/dist/data/ai/SessionViewer.model.d.ts +21 -3
- package/dist/data/ai/SessionViewer.model.d.ts.map +1 -1
- package/dist/data/ai/SessionViewer.model.js +7 -1
- package/dist/data/ai/SessionViewer.model.js.map +1 -1
- package/dist/data/ai/SessionViewer.unified.d.ts +13 -0
- package/dist/data/ai/SessionViewer.unified.d.ts.map +1 -1
- package/dist/data/ai/index.d.ts +3 -1
- package/dist/data/ai/index.d.ts.map +1 -1
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/devtools/useDebugStream.cjs +5 -1
- package/dist/devtools/useDebugStream.cjs.map +1 -1
- package/dist/devtools/useDebugStream.d.ts.map +1 -1
- package/dist/devtools/useDebugStream.js +6 -2
- package/dist/devtools/useDebugStream.js.map +1 -1
- package/dist/hooks/event-source-provider.cjs +9 -0
- package/dist/hooks/event-source-provider.cjs.map +1 -0
- package/dist/hooks/event-source-provider.d.ts +15 -0
- package/dist/hooks/event-source-provider.d.ts.map +1 -0
- package/dist/hooks/event-source-provider.js +9 -0
- package/dist/hooks/event-source-provider.js.map +1 -0
- package/dist/hooks/event-source.cjs +11 -0
- package/dist/hooks/event-source.cjs.map +1 -0
- package/dist/hooks/event-source.d.ts +22 -0
- package/dist/hooks/event-source.d.ts.map +1 -0
- package/dist/hooks/event-source.js +11 -0
- package/dist/hooks/event-source.js.map +1 -0
- package/dist/hooks/use-log-tail.cjs +5 -1
- package/dist/hooks/use-log-tail.cjs.map +1 -1
- package/dist/hooks/use-log-tail.d.ts.map +1 -1
- package/dist/hooks/use-log-tail.js +5 -1
- package/dist/hooks/use-log-tail.js.map +1 -1
- package/dist/hooks/use-prompts.cjs +5 -1
- package/dist/hooks/use-prompts.cjs.map +1 -1
- package/dist/hooks/use-prompts.d.ts.map +1 -1
- package/dist/hooks/use-prompts.js +6 -2
- package/dist/hooks/use-prompts.js.map +1 -1
- package/dist/hooks/use-task-run.cjs +9 -2
- package/dist/hooks/use-task-run.cjs.map +1 -1
- package/dist/hooks/use-task-run.d.ts.map +1 -1
- package/dist/hooks/use-task-run.js +10 -3
- package/dist/hooks/use-task-run.js.map +1 -1
- package/dist/hooks.cjs +4 -0
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.ts +2 -0
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +4 -0
- package/dist/hooks.js.map +1 -1
- package/dist/icons/programmingCatalog.cjs +34 -34
- package/dist/icons/programmingCatalog.cjs.map +1 -1
- package/dist/icons/programmingCatalog.js +34 -34
- package/dist/icons/programmingCatalog.js.map +1 -1
- package/dist/index.cjs +9 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/monaco/MonacoEditor.cjs +4 -1
- package/dist/monaco/MonacoEditor.cjs.map +1 -1
- package/dist/monaco/MonacoEditor.d.ts +1 -1
- package/dist/monaco/MonacoEditor.d.ts.map +1 -1
- package/dist/monaco/MonacoEditor.js +4 -1
- package/dist/monaco/MonacoEditor.js.map +1 -1
- package/dist/monaco/types.d.ts +2 -1
- package/dist/monaco/types.d.ts.map +1 -1
- package/dist/overlay/CommandPalette.cjs +14 -4
- package/dist/overlay/CommandPalette.cjs.map +1 -1
- package/dist/overlay/CommandPalette.d.ts +5 -1
- package/dist/overlay/CommandPalette.d.ts.map +1 -1
- package/dist/overlay/CommandPalette.js +14 -4
- package/dist/overlay/CommandPalette.js.map +1 -1
- package/dist/overlay/CommandPaletteList.cjs +5 -0
- package/dist/overlay/CommandPaletteList.cjs.map +1 -1
- package/dist/overlay/CommandPaletteList.d.ts +4 -2
- package/dist/overlay/CommandPaletteList.d.ts.map +1 -1
- package/dist/overlay/CommandPaletteList.js +5 -0
- package/dist/overlay/CommandPaletteList.js.map +1 -1
- package/dist/overlay/DropdownMenu.cjs +1 -0
- package/dist/overlay/DropdownMenu.cjs.map +1 -1
- package/dist/overlay/DropdownMenu.js +1 -0
- package/dist/overlay/DropdownMenu.js.map +1 -1
- package/dist/rpc/OperationCatalog.cjs +29 -26
- package/dist/rpc/OperationCatalog.cjs.map +1 -1
- package/dist/rpc/OperationCatalog.d.ts +9 -1
- package/dist/rpc/OperationCatalog.d.ts.map +1 -1
- package/dist/rpc/OperationCatalog.js +29 -26
- package/dist/rpc/OperationCatalog.js.map +1 -1
- package/dist/rpc/OperationEntityContextPicker.cjs +62 -256
- package/dist/rpc/OperationEntityContextPicker.cjs.map +1 -1
- package/dist/rpc/OperationEntityContextPicker.d.ts.map +1 -1
- package/dist/rpc/OperationEntityContextPicker.js +64 -258
- package/dist/rpc/OperationEntityContextPicker.js.map +1 -1
- package/dist/rpc/OperationEntityPicker.cjs +185 -0
- package/dist/rpc/OperationEntityPicker.cjs.map +1 -0
- package/dist/rpc/OperationEntityPicker.d.ts +51 -0
- package/dist/rpc/OperationEntityPicker.d.ts.map +1 -0
- package/dist/rpc/OperationEntityPicker.js +185 -0
- package/dist/rpc/OperationEntityPicker.js.map +1 -0
- package/dist/rpc/OperationEntityPicker.model.cjs +39 -0
- package/dist/rpc/OperationEntityPicker.model.cjs.map +1 -0
- package/dist/rpc/OperationEntityPicker.model.d.ts +27 -0
- package/dist/rpc/OperationEntityPicker.model.d.ts.map +1 -0
- package/dist/rpc/OperationEntityPicker.model.js +39 -0
- package/dist/rpc/OperationEntityPicker.model.js.map +1 -0
- package/dist/rpc/operationCatalogRowSelection.cjs +85 -0
- package/dist/rpc/operationCatalogRowSelection.cjs.map +1 -0
- package/dist/rpc/operationCatalogRowSelection.d.ts +57 -0
- package/dist/rpc/operationCatalogRowSelection.d.ts.map +1 -0
- package/dist/rpc/operationCatalogRowSelection.js +85 -0
- package/dist/rpc/operationCatalogRowSelection.js.map +1 -0
- package/dist/rpc/operationEntityPicker.fixtures.d.ts +13 -0
- package/dist/rpc/operationEntityPicker.fixtures.d.ts.map +1 -0
- package/dist/rpc.cjs +2 -0
- package/dist/rpc.cjs.map +1 -1
- package/dist/rpc.d.ts +2 -0
- package/dist/rpc.d.ts.map +1 -1
- package/dist/rpc.js +2 -0
- package/dist/rpc.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +4 -1
- package/schemas/json-schema-form.schema.json +566 -0
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useState, useMemo,
|
|
3
|
-
import { useQuery, keepPreviousData } from "@tanstack/react-query";
|
|
4
|
-
import { Button } from "../components/button.js";
|
|
2
|
+
import { useState, useMemo, useCallback } from "react";
|
|
5
3
|
import { DropdownMenu } from "../overlay/DropdownMenu.js";
|
|
6
|
-
import {
|
|
7
|
-
import { CommandOutput } from "./CommandOutput.js";
|
|
8
|
-
import { useDebouncedRecord, packParameterValues, packLookupParameterValues, parametersToFormConfig, dataTablePaginationFromForm } from "./formMetadata.js";
|
|
4
|
+
import { packParameterValues } from "./formMetadata.js";
|
|
9
5
|
import { getClickySurfaces, filterOperationsBySurface, findSurfaceListOperation, findSurfaceDetailOperation, getOperationClickyMeta } from "./clickyMetadata.js";
|
|
6
|
+
import { OperationEntityPicker } from "./OperationEntityPicker.js";
|
|
10
7
|
import { getClickyRowId } from "./rowNavigation.js";
|
|
11
8
|
import { resolveSurfaceIcon } from "./surfaceIconMap.js";
|
|
12
9
|
import { useOperations } from "./useOperations.js";
|
|
13
10
|
import { entityContextItemID, clickyRowRecord, contextItemFromEntityRow } from "./OperationEntityContextPicker.model.js";
|
|
14
11
|
import { UiTable } from "../icons/components/UiTable.js";
|
|
15
12
|
import { UiAdd } from "../icons/components/UiAdd.js";
|
|
13
|
+
const plural = (count) => count === 1 ? "" : "s";
|
|
16
14
|
function OperationEntityContextPicker({
|
|
17
15
|
client,
|
|
18
16
|
items,
|
|
@@ -28,7 +26,6 @@ function OperationEntityContextPicker({
|
|
|
28
26
|
surfaceRenderer,
|
|
29
27
|
triggerLabel = "Add context"
|
|
30
28
|
}) {
|
|
31
|
-
var _a;
|
|
32
29
|
const {
|
|
33
30
|
operations,
|
|
34
31
|
spec,
|
|
@@ -36,12 +33,6 @@ function OperationEntityContextPicker({
|
|
|
36
33
|
} = useOperations(client);
|
|
37
34
|
const [open, setOpen] = useState(false);
|
|
38
35
|
const [surfaceKey, setSurfaceKey] = useState("");
|
|
39
|
-
const [filters, setFilters] = useState({});
|
|
40
|
-
const [selectedRows, setSelectedRows] = useState(
|
|
41
|
-
{}
|
|
42
|
-
);
|
|
43
|
-
const [attaching, setAttaching] = useState(false);
|
|
44
|
-
const [attachError, setAttachError] = useState("");
|
|
45
36
|
const surfaces = useMemo(() => {
|
|
46
37
|
return getClickySurfaces(spec).flatMap((surface) => {
|
|
47
38
|
const surfaceOperations = filterOperationsBySurface(
|
|
@@ -72,84 +63,14 @@ function OperationEntityContextPicker({
|
|
|
72
63
|
return leftGroup.localeCompare(rightGroup) || left.surface.title.localeCompare(right.surface.title);
|
|
73
64
|
});
|
|
74
65
|
}, [operations, spec, surfaceFilter, surfaceGroup]);
|
|
75
|
-
useEffect(() => {
|
|
76
|
-
setFilters({});
|
|
77
|
-
setSelectedRows({});
|
|
78
|
-
setAttachError("");
|
|
79
|
-
}, [surfaceKey]);
|
|
80
66
|
const selected = surfaces.find((entry) => entry.surface.key === surfaceKey);
|
|
81
|
-
const parameters = (selected == null ? void 0 : selected.listOperation.operation.parameters) ?? [];
|
|
82
|
-
const debouncedFilters = useDebouncedRecord(filters, 250);
|
|
83
|
-
const packedFilters = useMemo(
|
|
84
|
-
() => packParameterValues(debouncedFilters, parameters),
|
|
85
|
-
[debouncedFilters, parameters]
|
|
86
|
-
);
|
|
87
|
-
const packedLookupFilters = useMemo(
|
|
88
|
-
() => packLookupParameterValues(debouncedFilters, parameters),
|
|
89
|
-
[debouncedFilters, parameters]
|
|
90
|
-
);
|
|
91
|
-
const lookupQuery = useQuery({
|
|
92
|
-
queryKey: [
|
|
93
|
-
"entity-context-lookup",
|
|
94
|
-
selected == null ? void 0 : selected.listOperation.path,
|
|
95
|
-
packedLookupFilters
|
|
96
|
-
],
|
|
97
|
-
queryFn: async () => {
|
|
98
|
-
var _a2;
|
|
99
|
-
return await ((_a2 = client.lookupFilters) == null ? void 0 : _a2.call(
|
|
100
|
-
client,
|
|
101
|
-
selected.listOperation.path,
|
|
102
|
-
selected.listOperation.method,
|
|
103
|
-
packedLookupFilters,
|
|
104
|
-
{ Accept: "application/json+clicky" }
|
|
105
|
-
)) ?? { filters: {} };
|
|
106
|
-
},
|
|
107
|
-
enabled: open && !!selected && !!client.lookupFilters && parameters.some((parameter) => parameter.in === "query"),
|
|
108
|
-
placeholderData: keepPreviousData,
|
|
109
|
-
staleTime: 3e4,
|
|
110
|
-
retry: 0
|
|
111
|
-
});
|
|
112
|
-
const listQuery = useQuery({
|
|
113
|
-
queryKey: [
|
|
114
|
-
"entity-context-list",
|
|
115
|
-
selected == null ? void 0 : selected.listOperation.path,
|
|
116
|
-
packedFilters
|
|
117
|
-
],
|
|
118
|
-
queryFn: () => client.executeCommand(
|
|
119
|
-
selected.listOperation.path,
|
|
120
|
-
selected.listOperation.method,
|
|
121
|
-
packedFilters,
|
|
122
|
-
{ Accept: "application/json+clicky" }
|
|
123
|
-
),
|
|
124
|
-
enabled: open && !!selected,
|
|
125
|
-
placeholderData: keepPreviousData,
|
|
126
|
-
staleTime: 3e4,
|
|
127
|
-
retry: 0
|
|
128
|
-
});
|
|
129
|
-
const filterShapes = (_a = spec == null ? void 0 : spec.components) == null ? void 0 : _a["x-clicky-filters"];
|
|
130
|
-
const filterConfig = useMemo(
|
|
131
|
-
() => parametersToFormConfig(parameters, filters, setFilters, {
|
|
132
|
-
includeLocations: ["query"],
|
|
133
|
-
lookup: lookupQuery.data,
|
|
134
|
-
components: filterShapes
|
|
135
|
-
}),
|
|
136
|
-
[filters, filterShapes, lookupQuery.data, parameters]
|
|
137
|
-
);
|
|
138
|
-
const pagination = useMemo(
|
|
139
|
-
() => dataTablePaginationFromForm(filterConfig.pagination, listQuery.data),
|
|
140
|
-
[filterConfig.pagination, listQuery.data]
|
|
141
|
-
);
|
|
142
67
|
const existingIDs = useMemo(
|
|
143
68
|
() => new Set(items.map((item) => item.id)),
|
|
144
69
|
[items]
|
|
145
70
|
);
|
|
146
|
-
const markedListResponse = useMemo(
|
|
147
|
-
() => markAttachedRows(listQuery.data, selected == null ? void 0 : selected.surface.key, existingIDs),
|
|
148
|
-
[existingIDs, listQuery.data, selected == null ? void 0 : selected.surface.key]
|
|
149
|
-
);
|
|
150
71
|
const hydrateRow = useCallback(
|
|
151
|
-
async (row) => {
|
|
152
|
-
var
|
|
72
|
+
async (row, listFilters) => {
|
|
73
|
+
var _a, _b, _c;
|
|
153
74
|
if (!selected) throw new Error("Select an entity type first.");
|
|
154
75
|
const recordID = getClickyRowId(row);
|
|
155
76
|
if (!recordID) {
|
|
@@ -162,7 +83,7 @@ function OperationEntityContextPicker({
|
|
|
162
83
|
let record = clickyRowRecord(row);
|
|
163
84
|
if (selected.detailOperation) {
|
|
164
85
|
const detailMeta = getOperationClickyMeta(selected.detailOperation);
|
|
165
|
-
const idParam = (detailMeta == null ? void 0 : detailMeta.idParam) ?? ((_b = (
|
|
86
|
+
const idParam = (detailMeta == null ? void 0 : detailMeta.idParam) ?? ((_b = (_a = selected.detailOperation.operation.parameters) == null ? void 0 : _a.find(
|
|
166
87
|
(parameter) => parameter.in === "path"
|
|
167
88
|
)) == null ? void 0 : _b.name) ?? "id";
|
|
168
89
|
const detailParameterNames = new Set(
|
|
@@ -170,6 +91,10 @@ function OperationEntityContextPicker({
|
|
|
170
91
|
(parameter) => parameter.name
|
|
171
92
|
)) ?? []
|
|
172
93
|
);
|
|
94
|
+
const packedFilters = packParameterValues(
|
|
95
|
+
listFilters,
|
|
96
|
+
selected.listOperation.operation.parameters ?? []
|
|
97
|
+
);
|
|
173
98
|
const detailParams = Object.fromEntries(
|
|
174
99
|
Object.entries(packedFilters).filter(
|
|
175
100
|
([key]) => detailParameterNames.has(key)
|
|
@@ -193,37 +118,34 @@ function OperationEntityContextPicker({
|
|
|
193
118
|
throw new Error("This row does not expose a stable record ID.");
|
|
194
119
|
return contextItem;
|
|
195
120
|
},
|
|
196
|
-
[client, existingIDs,
|
|
121
|
+
[client, existingIDs, selected]
|
|
197
122
|
);
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
setAttachError("");
|
|
203
|
-
const results = await Promise.allSettled(rows.map(hydrateRow));
|
|
204
|
-
const added = results.flatMap(
|
|
205
|
-
(result) => result.status === "fulfilled" ? [result.value] : []
|
|
206
|
-
);
|
|
207
|
-
const failures = results.flatMap(
|
|
208
|
-
(result) => result.status === "rejected" ? [result.reason] : []
|
|
209
|
-
);
|
|
210
|
-
if (added.length > 0) {
|
|
211
|
-
if (onAddMany) onAddMany(added);
|
|
212
|
-
else added.forEach(onAdd);
|
|
213
|
-
}
|
|
214
|
-
setAttaching(false);
|
|
215
|
-
if (failures.length > 0) {
|
|
216
|
-
const first = failures[0];
|
|
217
|
-
setAttachError(
|
|
218
|
-
`${failures.length} record${failures.length === 1 ? "" : "s"} could not be attached: ${first instanceof Error ? first.message : String(first)}`
|
|
123
|
+
const attachRows = useCallback(
|
|
124
|
+
async (rows, listFilters) => {
|
|
125
|
+
const results = await Promise.allSettled(
|
|
126
|
+
rows.map((row) => hydrateRow(row, listFilters))
|
|
219
127
|
);
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
128
|
+
const added = results.flatMap(
|
|
129
|
+
(result) => result.status === "fulfilled" ? [result.value] : []
|
|
130
|
+
);
|
|
131
|
+
const failures = results.flatMap(
|
|
132
|
+
(result) => result.status === "rejected" ? [result.reason] : []
|
|
133
|
+
);
|
|
134
|
+
if (added.length > 0) {
|
|
135
|
+
if (onAddMany) onAddMany(added);
|
|
136
|
+
else added.forEach(onAdd);
|
|
137
|
+
}
|
|
138
|
+
if (failures.length > 0) {
|
|
139
|
+
const first = failures[0];
|
|
140
|
+
throw new Error(
|
|
141
|
+
`${failures.length} record${plural(failures.length)} could not be attached: ${first instanceof Error ? first.message : String(first)}`
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
[hydrateRow, onAdd, onAddMany]
|
|
146
|
+
);
|
|
225
147
|
const menuItems = useMemo(() => {
|
|
226
|
-
var
|
|
148
|
+
var _a;
|
|
227
149
|
const groups = [];
|
|
228
150
|
const byGroup = /* @__PURE__ */ new Map();
|
|
229
151
|
for (const entry of surfaces) {
|
|
@@ -249,9 +171,9 @@ function OperationEntityContextPicker({
|
|
|
249
171
|
}
|
|
250
172
|
bucket.push(leaf);
|
|
251
173
|
}
|
|
252
|
-
if (groups.length <= 1) return ((
|
|
174
|
+
if (groups.length <= 1) return ((_a = groups[0]) == null ? void 0 : _a.leaves) ?? [];
|
|
253
175
|
return groups.map(({ group, leaves }) => {
|
|
254
|
-
var
|
|
176
|
+
var _a2;
|
|
255
177
|
const groupColor = surfaceGroupColor == null ? void 0 : surfaceGroupColor(group);
|
|
256
178
|
const prefix = `${group} `;
|
|
257
179
|
const children = leaves.map(
|
|
@@ -260,7 +182,7 @@ function OperationEntityContextPicker({
|
|
|
260
182
|
return {
|
|
261
183
|
label: group,
|
|
262
184
|
title: group,
|
|
263
|
-
icon: (surfaceGroupIcon == null ? void 0 : surfaceGroupIcon(group)) ?? ((
|
|
185
|
+
icon: (surfaceGroupIcon == null ? void 0 : surfaceGroupIcon(group)) ?? ((_a2 = leaves[0]) == null ? void 0 : _a2.icon) ?? UiTable,
|
|
264
186
|
...groupColor ? { iconColor: groupColor } : {},
|
|
265
187
|
onSelect: () => {
|
|
266
188
|
},
|
|
@@ -276,8 +198,6 @@ function OperationEntityContextPicker({
|
|
|
276
198
|
surfaceLabel,
|
|
277
199
|
surfaces
|
|
278
200
|
]);
|
|
279
|
-
const selectedCount = Object.keys(selectedRows).length;
|
|
280
|
-
const selectedLabel = selected ? (surfaceLabel == null ? void 0 : surfaceLabel(selected.surface, selected.listOperation)) ?? selected.surface.title : "records";
|
|
281
201
|
const trigger = /* @__PURE__ */ jsx(
|
|
282
202
|
DropdownMenu,
|
|
283
203
|
{
|
|
@@ -298,108 +218,40 @@ function OperationEntityContextPicker({
|
|
|
298
218
|
]
|
|
299
219
|
}
|
|
300
220
|
);
|
|
221
|
+
if (!selected) return trigger;
|
|
222
|
+
const selectedLabel = (surfaceLabel == null ? void 0 : surfaceLabel(selected.surface, selected.listOperation)) ?? selected.surface.title;
|
|
223
|
+
const selectedSurfaceKey = selected.surface.key;
|
|
301
224
|
const defaultDialog = /* @__PURE__ */ jsx(
|
|
302
|
-
|
|
225
|
+
OperationEntityPicker,
|
|
303
226
|
{
|
|
304
227
|
open,
|
|
305
228
|
onClose: () => setOpen(false),
|
|
306
229
|
title: `Add ${selectedLabel} context`,
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
onClick: () => void attachSelected(),
|
|
328
|
-
disabled: selectedCount === 0 || attaching,
|
|
329
|
-
children: attaching ? "Adding…" : selectedCount > 0 ? `Add ${selectedCount} record${selectedCount === 1 ? "" : "s"}` : "Add records"
|
|
330
|
-
}
|
|
331
|
-
)
|
|
332
|
-
] })
|
|
333
|
-
] }),
|
|
334
|
-
children: /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 flex-col gap-4", children: [
|
|
335
|
-
surfaces.length === 0 && !operationsLoading ? /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "No attachable entity surfaces are available." }) : null,
|
|
336
|
-
lookupQuery.error ? /* @__PURE__ */ jsx(PickerError, { error: lookupQuery.error, prefix: "Load filters" }) : null,
|
|
337
|
-
listQuery.error ? /* @__PURE__ */ jsx(PickerError, { error: listQuery.error, prefix: "Load records" }) : null,
|
|
338
|
-
attachError ? /* @__PURE__ */ jsx(PickerError, { error: attachError, prefix: "Attach record" }) : null,
|
|
339
|
-
attaching ? /* @__PURE__ */ jsx("div", { role: "status", className: "text-xs text-muted-foreground", children: "Loading full record details and adding context…" }) : null,
|
|
340
|
-
selected ? /* @__PURE__ */ jsx(
|
|
341
|
-
CommandOutput,
|
|
342
|
-
{
|
|
343
|
-
bare: true,
|
|
344
|
-
className: "mt-0 flex-1",
|
|
345
|
-
response: markedListResponse ?? null,
|
|
346
|
-
loading: listQuery.isLoading || listQuery.isFetching,
|
|
347
|
-
loadingMessage: "Loading records…",
|
|
348
|
-
emptyMessage: "No matching records.",
|
|
349
|
-
ariaLabel: "Context records",
|
|
350
|
-
rowSelection: {
|
|
351
|
-
selectedRowIds: Object.keys(selectedRows),
|
|
352
|
-
// Keep selections made on other pages: reconcile the table's
|
|
353
|
-
// next id set against the rows on the current page, falling back
|
|
354
|
-
// to the already-known row for ids from previously-viewed pages.
|
|
355
|
-
onSelectionChange: (nextIds, rows) => {
|
|
356
|
-
const rowByID = new Map(
|
|
357
|
-
rows.flatMap((row) => {
|
|
358
|
-
const id = getClickyRowId(row);
|
|
359
|
-
return id ? [[id, row]] : [];
|
|
360
|
-
})
|
|
361
|
-
);
|
|
362
|
-
setSelectedRows(
|
|
363
|
-
(prev) => Object.fromEntries(
|
|
364
|
-
nextIds.flatMap((id) => {
|
|
365
|
-
const row = rowByID.get(id) ?? prev[id];
|
|
366
|
-
return row ? [[id, row]] : [];
|
|
367
|
-
})
|
|
368
|
-
)
|
|
369
|
-
);
|
|
370
|
-
},
|
|
371
|
-
getRowId: (row, index) => getClickyRowId(row) ?? `context-row-${index}`,
|
|
372
|
-
isRowSelectable: (row) => {
|
|
373
|
-
const id = getClickyRowId(row);
|
|
374
|
-
return !!id && !existingIDs.has(
|
|
375
|
-
entityContextItemID(selected.surface.key, id)
|
|
376
|
-
);
|
|
377
|
-
},
|
|
378
|
-
toggleOnRowClick: true
|
|
379
|
-
},
|
|
380
|
-
...filterConfig.search ? { search: filterConfig.search } : {},
|
|
381
|
-
...filterConfig.timeRange ? { timeRange: filterConfig.timeRange } : {},
|
|
382
|
-
...filterConfig.filters.length ? { externalFilters: filterConfig.filters } : {},
|
|
383
|
-
...pagination ? { pagination } : {},
|
|
384
|
-
...filterConfig.sort ? {
|
|
385
|
-
sort: filterConfig.sort.value,
|
|
386
|
-
onSortChange: filterConfig.sort.onChange
|
|
387
|
-
} : {}
|
|
388
|
-
}
|
|
389
|
-
) : null,
|
|
390
|
-
items.length ? /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
391
|
-
items.length,
|
|
392
|
-
" context ",
|
|
393
|
-
items.length === 1 ? "record" : "records",
|
|
394
|
-
" ",
|
|
395
|
-
"attached. Attached rows are disabled."
|
|
396
|
-
] }) : null
|
|
397
|
-
] })
|
|
230
|
+
client,
|
|
231
|
+
surfaceKey: selectedSurfaceKey,
|
|
232
|
+
mode: "multi",
|
|
233
|
+
onSelect: (_ids, rows, { filters }) => attachRows(rows, filters),
|
|
234
|
+
unavailableRows: {
|
|
235
|
+
isUnavailable: (row) => {
|
|
236
|
+
const id = getClickyRowId(row);
|
|
237
|
+
return !!id && existingIDs.has(entityContextItemID(selectedSurfaceKey, id));
|
|
238
|
+
},
|
|
239
|
+
label: "Attached",
|
|
240
|
+
columnLabel: "Context"
|
|
241
|
+
},
|
|
242
|
+
selectLabel: ({ count, pending }) => pending ? "Adding…" : count > 0 ? `Add ${count} record${plural(count)}` : "Add records",
|
|
243
|
+
note: items.length ? /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
244
|
+
items.length,
|
|
245
|
+
" context ",
|
|
246
|
+
items.length === 1 ? "record" : "records",
|
|
247
|
+
" ",
|
|
248
|
+
"attached. Attached rows are disabled."
|
|
249
|
+
] }) : null
|
|
398
250
|
}
|
|
399
251
|
);
|
|
400
252
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
401
253
|
trigger,
|
|
402
|
-
|
|
254
|
+
surfaceRenderer ? surfaceRenderer({
|
|
403
255
|
surface: selected.surface,
|
|
404
256
|
listOperation: selected.listOperation,
|
|
405
257
|
...selected.detailOperation ? { detailOperation: selected.detailOperation } : {},
|
|
@@ -421,52 +273,6 @@ function parseResponseJSON(response) {
|
|
|
421
273
|
return void 0;
|
|
422
274
|
}
|
|
423
275
|
}
|
|
424
|
-
function markAttachedRows(response, surfaceKey, existingIDs) {
|
|
425
|
-
var _a;
|
|
426
|
-
if (!response || !surfaceKey || existingIDs.size === 0 || !response.parsed)
|
|
427
|
-
return response;
|
|
428
|
-
const parsed = response.parsed;
|
|
429
|
-
const node = parsed.version === 1 && parsed.node ? parsed.node : parsed;
|
|
430
|
-
if (node.kind !== "table" || !((_a = node.rows) == null ? void 0 : _a.length)) return response;
|
|
431
|
-
const tableNode = node;
|
|
432
|
-
const attached = tableNode.rows.map((row) => {
|
|
433
|
-
const id = getClickyRowId(row);
|
|
434
|
-
return !!id && existingIDs.has(entityContextItemID(surfaceKey, id));
|
|
435
|
-
});
|
|
436
|
-
if (!attached.some(Boolean)) return response;
|
|
437
|
-
const markerColumn = {
|
|
438
|
-
name: "__chat_context",
|
|
439
|
-
label: "Context",
|
|
440
|
-
shrink: true
|
|
441
|
-
};
|
|
442
|
-
const markedNode = {
|
|
443
|
-
...tableNode,
|
|
444
|
-
kind: "table",
|
|
445
|
-
columns: [...tableNode.columns ?? [], markerColumn],
|
|
446
|
-
rows: tableNode.rows.map((row, index) => ({
|
|
447
|
-
...row,
|
|
448
|
-
cells: {
|
|
449
|
-
...row.cells,
|
|
450
|
-
__chat_context: attached[index] ? { kind: "badge", badgeLabel: "Attached" } : { kind: "text", text: "", plain: "" }
|
|
451
|
-
}
|
|
452
|
-
}))
|
|
453
|
-
};
|
|
454
|
-
return {
|
|
455
|
-
...response,
|
|
456
|
-
parsed: parsed.version === 1 ? { ...parsed, node: markedNode } : markedNode
|
|
457
|
-
};
|
|
458
|
-
}
|
|
459
|
-
function PickerError({ error, prefix }) {
|
|
460
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
461
|
-
return /* @__PURE__ */ jsxs("div", { className: "rounded-md border border-destructive/40 bg-destructive/5 p-3 text-sm text-destructive", children: [
|
|
462
|
-
/* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
|
|
463
|
-
prefix,
|
|
464
|
-
":"
|
|
465
|
-
] }),
|
|
466
|
-
" ",
|
|
467
|
-
message
|
|
468
|
-
] });
|
|
469
|
-
}
|
|
470
276
|
export {
|
|
471
277
|
OperationEntityContextPicker
|
|
472
278
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OperationEntityContextPicker.js","sources":["../../src/rpc/OperationEntityContextPicker.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useState, type ReactNode } from \"react\";\nimport { keepPreviousData, useQuery } from \"@tanstack/react-query\";\nimport { Button } from \"../components/button\";\nimport type { ClickyDocument, ClickyNode, ClickyRow } from \"../data/Clicky\";\nimport type { StaticIconComponent } from \"../data/Icon\";\nimport type { ChatContextItem } from \"../data/ai/context\";\nimport { UiAdd, UiTable } from \"../icons\";\nimport { DropdownMenu, type DropdownMenuItem } from \"../overlay/DropdownMenu\";\nimport { Modal } from \"../overlay/Modal\";\nimport { CommandOutput } from \"./CommandOutput\";\nimport {\n dataTablePaginationFromForm,\n packLookupParameterValues,\n packParameterValues,\n parametersToFormConfig,\n useDebouncedRecord,\n type ParameterValues,\n} from \"./formMetadata\";\nimport {\n filterOperationsBySurface,\n findSurfaceDetailOperation,\n findSurfaceListOperation,\n getClickySurfaces,\n getOperationClickyMeta,\n} from \"./clickyMetadata\";\nimport { getClickyRowId } from \"./rowNavigation\";\nimport { resolveSurfaceIcon } from \"./surfaceIconMap\";\nimport type {\n ClickySurface,\n ExecutionResponse,\n ResolvedOperation,\n} from \"./types\";\nimport { useOperations, type OperationsApiClient } from \"./useOperations\";\nimport {\n clickyRowRecord,\n contextItemFromEntityRow,\n entityContextItemID,\n} from \"./OperationEntityContextPicker.model\";\n\nexport type EntityContextSurfaceFilter = (\n surface: ClickySurface,\n listOperation: ResolvedOperation,\n) => boolean;\n\nexport type EntityContextSurfaceText = (\n surface: ClickySurface,\n listOperation: ResolvedOperation,\n) => string;\n\nexport type EntityContextSurfaceIcon = (\n surface: ClickySurface,\n listOperation: ResolvedOperation,\n) => string | StaticIconComponent | undefined;\n\nexport type EntityContextSurfaceColor = (\n surface: ClickySurface,\n listOperation: ResolvedOperation,\n) => string | undefined;\n\nexport type EntityContextGroupIcon = (\n group: string,\n) => string | StaticIconComponent | undefined;\n\nexport type EntityContextGroupColor = (group: string) => string | undefined;\n\n// EntityContextSurfaceRenderContext is handed to a host-supplied surfaceRenderer\n// so it can replace the picker dialog for selected surfaces, the way\n// ResultRenderer replaces a result surface. The generic dialog lists whatever\n// the entity's list operation returns, which is the right default and the wrong\n// answer for a surface the host already browses with a purpose-built UI — a\n// document tree, a map, a calendar. `defaultView` is the standard dialog;\n// return it unchanged to keep it.\n//\n// The whole dialog is replaced rather than only its body: a replacement that\n// owns selection has to own the confirm button too, or the footer would count\n// rows the host is no longer tracking.\nexport type EntityContextSurfaceRenderContext = {\n surface: ClickySurface;\n listOperation: ResolvedOperation;\n detailOperation?: ResolvedOperation;\n /** Already-attached items, so a replacement can disable them. */\n items: ChatContextItem[];\n onAdd: (item: ChatContextItem) => void;\n onAddMany: (items: ChatContextItem[]) => void;\n /** True while this surface is the one chosen from the dropdown. */\n open: boolean;\n close: () => void;\n defaultView: ReactNode;\n};\n\nexport type EntityContextSurfaceRenderer = (\n ctx: EntityContextSurfaceRenderContext,\n) => ReactNode;\n\nexport type OperationEntityContextPickerProps = {\n client: OperationsApiClient;\n items: ChatContextItem[];\n onAdd: (item: ChatContextItem) => void;\n onAddMany?: (items: ChatContextItem[]) => void;\n surfaceFilter?: EntityContextSurfaceFilter;\n surfaceLabel?: EntityContextSurfaceText;\n surfaceGroup?: EntityContextSurfaceText;\n surfaceIcon?: EntityContextSurfaceIcon;\n surfaceColor?: EntityContextSurfaceColor;\n /** Icon for a top-level provider/group row (the submenu trigger). */\n surfaceGroupIcon?: EntityContextGroupIcon;\n /** Icon colour for a top-level provider/group row. */\n surfaceGroupColor?: EntityContextGroupColor;\n /** Replaces the picker dialog for surfaces the host browses its own way. */\n surfaceRenderer?: EntityContextSurfaceRenderer;\n triggerLabel?: string;\n};\n\ntype ContextSurface = {\n surface: ClickySurface;\n listOperation: ResolvedOperation;\n detailOperation?: ResolvedOperation;\n};\n\nexport function OperationEntityContextPicker({\n client,\n items,\n onAdd,\n onAddMany,\n surfaceFilter,\n surfaceLabel,\n surfaceGroup,\n surfaceIcon,\n surfaceColor,\n surfaceGroupIcon,\n surfaceGroupColor,\n surfaceRenderer,\n triggerLabel = \"Add context\",\n}: OperationEntityContextPickerProps) {\n const {\n operations,\n spec,\n isLoading: operationsLoading,\n } = useOperations(client);\n const [open, setOpen] = useState(false);\n const [surfaceKey, setSurfaceKey] = useState(\"\");\n const [filters, setFilters] = useState<ParameterValues>({});\n const [selectedRows, setSelectedRows] = useState<Record<string, ClickyRow>>(\n {},\n );\n const [attaching, setAttaching] = useState(false);\n const [attachError, setAttachError] = useState(\"\");\n\n const surfaces = useMemo<ContextSurface[]>(() => {\n return getClickySurfaces(spec)\n .flatMap((surface): ContextSurface[] => {\n const surfaceOperations = filterOperationsBySurface(\n operations,\n surface.key,\n );\n const listOperation = findSurfaceListOperation(\n surfaceOperations,\n surface.key,\n );\n if (!listOperation || listOperation.method.toUpperCase() !== \"GET\")\n return [];\n if (surfaceFilter && !surfaceFilter(surface, listOperation)) return [];\n const detailOperation = findSurfaceDetailOperation(\n surfaceOperations,\n surface.key,\n );\n return [\n {\n surface,\n listOperation,\n ...(detailOperation ? { detailOperation } : {}),\n },\n ];\n })\n .sort((left, right) => {\n const leftGroup =\n surfaceGroup?.(left.surface, left.listOperation) ??\n left.surface.parent ??\n \"\";\n const rightGroup =\n surfaceGroup?.(right.surface, right.listOperation) ??\n right.surface.parent ??\n \"\";\n return (\n leftGroup.localeCompare(rightGroup) ||\n left.surface.title.localeCompare(right.surface.title)\n );\n });\n }, [operations, spec, surfaceFilter, surfaceGroup]);\n\n useEffect(() => {\n setFilters({});\n setSelectedRows({});\n setAttachError(\"\");\n }, [surfaceKey]);\n\n const selected = surfaces.find((entry) => entry.surface.key === surfaceKey);\n const parameters = selected?.listOperation.operation.parameters ?? [];\n const debouncedFilters = useDebouncedRecord(filters, 250);\n const packedFilters = useMemo(\n () => packParameterValues(debouncedFilters, parameters),\n [debouncedFilters, parameters],\n );\n const packedLookupFilters = useMemo(\n () => packLookupParameterValues(debouncedFilters, parameters),\n [debouncedFilters, parameters],\n );\n\n const lookupQuery = useQuery({\n queryKey: [\n \"entity-context-lookup\",\n selected?.listOperation.path,\n packedLookupFilters,\n ],\n queryFn: async () =>\n (await client.lookupFilters?.(\n selected!.listOperation.path,\n selected!.listOperation.method,\n packedLookupFilters,\n { Accept: \"application/json+clicky\" },\n )) ?? { filters: {} },\n enabled:\n open &&\n !!selected &&\n !!client.lookupFilters &&\n parameters.some((parameter) => parameter.in === \"query\"),\n placeholderData: keepPreviousData,\n staleTime: 30_000,\n retry: 0,\n });\n\n const listQuery = useQuery<ExecutionResponse>({\n queryKey: [\n \"entity-context-list\",\n selected?.listOperation.path,\n packedFilters,\n ],\n queryFn: () =>\n client.executeCommand(\n selected!.listOperation.path,\n selected!.listOperation.method,\n packedFilters,\n { Accept: \"application/json+clicky\" },\n ),\n enabled: open && !!selected,\n placeholderData: keepPreviousData,\n staleTime: 30_000,\n retry: 0,\n });\n\n // Shapes come from the spec so a control keeps its identity while the lookup\n // that fills it is in flight; see parametersToFormConfig.\n const filterShapes = spec?.components?.[\"x-clicky-filters\"];\n const filterConfig = useMemo(\n () =>\n parametersToFormConfig(parameters, filters, setFilters, {\n includeLocations: [\"query\"],\n lookup: lookupQuery.data,\n components: filterShapes,\n }),\n [filters, filterShapes, lookupQuery.data, parameters],\n );\n const pagination = useMemo(\n () => dataTablePaginationFromForm(filterConfig.pagination, listQuery.data),\n [filterConfig.pagination, listQuery.data],\n );\n const existingIDs = useMemo(\n () => new Set(items.map((item) => item.id)),\n [items],\n );\n const markedListResponse = useMemo(\n () => markAttachedRows(listQuery.data, selected?.surface.key, existingIDs),\n [existingIDs, listQuery.data, selected?.surface.key],\n );\n\n const hydrateRow = useCallback(\n async (row: ClickyRow) => {\n if (!selected) throw new Error(\"Select an entity type first.\");\n const recordID = getClickyRowId(row);\n if (!recordID) {\n throw new Error(\"This row does not expose a stable record ID.\");\n }\n const contextID = entityContextItemID(selected.surface.key, recordID);\n if (existingIDs.has(contextID)) {\n throw new Error(\"This record is already attached.\");\n }\n\n let record: unknown = clickyRowRecord(row);\n if (selected.detailOperation) {\n const detailMeta = getOperationClickyMeta(selected.detailOperation);\n const idParam =\n detailMeta?.idParam ??\n selected.detailOperation.operation.parameters?.find(\n (parameter) => parameter.in === \"path\",\n )?.name ??\n \"id\";\n const detailParameterNames = new Set(\n selected.detailOperation.operation.parameters?.map(\n (parameter) => parameter.name,\n ) ?? [],\n );\n const detailParams = Object.fromEntries(\n Object.entries(packedFilters).filter(([key]) =>\n detailParameterNames.has(key),\n ),\n );\n detailParams[idParam] = recordID;\n const response = await client.executeCommand(\n selected.detailOperation.path,\n selected.detailOperation.method,\n detailParams,\n { Accept: \"application/json\" },\n );\n record = response.parsed ?? parseResponseJSON(response) ?? record;\n }\n\n const contextItem = contextItemFromEntityRow(\n selected.surface,\n row,\n record,\n );\n if (!contextItem)\n throw new Error(\"This row does not expose a stable record ID.\");\n return contextItem;\n },\n [client, existingIDs, packedFilters, selected],\n );\n\n const attachSelected = useCallback(async () => {\n const rows = Object.values(selectedRows);\n if (rows.length === 0) return;\n setAttaching(true);\n setAttachError(\"\");\n const results = await Promise.allSettled(rows.map(hydrateRow));\n const added = results.flatMap((result) =>\n result.status === \"fulfilled\" ? [result.value] : [],\n );\n const failures = results.flatMap((result) =>\n result.status === \"rejected\" ? [result.reason] : [],\n );\n if (added.length > 0) {\n if (onAddMany) onAddMany(added);\n else added.forEach(onAdd);\n }\n setAttaching(false);\n if (failures.length > 0) {\n const first = failures[0];\n setAttachError(\n `${failures.length} record${failures.length === 1 ? \"\" : \"s\"} could not be attached: ${first instanceof Error ? first.message : String(first)}`,\n );\n return;\n }\n setSelectedRows({});\n setOpen(false);\n }, [hydrateRow, onAdd, onAddMany, selectedRows]);\n\n const menuItems = useMemo<DropdownMenuItem[]>(() => {\n // `surfaces` is pre-sorted by group then title, so bucketing by group in\n // insertion order yields a stable provider → type tree without re-sorting.\n const groups: Array<{ group: string; leaves: DropdownMenuItem[] }> = [];\n const byGroup = new Map<string, DropdownMenuItem[]>();\n for (const entry of surfaces) {\n const group =\n surfaceGroup?.(entry.surface, entry.listOperation) ??\n entry.surface.parent ??\n \"Other\";\n const label =\n surfaceLabel?.(entry.surface, entry.listOperation) ??\n entry.surface.title;\n const icon =\n surfaceIcon?.(entry.surface, entry.listOperation) ??\n resolveSurfaceIcon(entry.surface.icon) ??\n UiTable;\n const iconColor = surfaceColor?.(entry.surface, entry.listOperation);\n const leaf: DropdownMenuItem = {\n label,\n title: label,\n icon,\n ...(iconColor ? { iconColor } : {}),\n onSelect: () => {\n setSurfaceKey(entry.surface.key);\n setOpen(true);\n },\n };\n let bucket = byGroup.get(group);\n if (!bucket) {\n bucket = [];\n byGroup.set(group, bucket);\n groups.push({ group, leaves: bucket });\n }\n bucket.push(leaf);\n }\n\n // A single group would nest everything under one lone submenu; render its\n // types flat instead.\n if (groups.length <= 1) return groups[0]?.leaves ?? [];\n\n return groups.map(({ group, leaves }): DropdownMenuItem => {\n const groupColor = surfaceGroupColor?.(group);\n // A submenu child already sits under its group header — don't repeat the\n // group name in the child label. The tooltip (title) and the detail dialog\n // keep the full label.\n const prefix = `${group} `;\n const children = leaves.map((leaf) =>\n typeof leaf.label === \"string\" && leaf.label.startsWith(prefix)\n ? { ...leaf, label: leaf.label.slice(prefix.length) }\n : leaf,\n );\n return {\n label: group,\n title: group,\n icon: surfaceGroupIcon?.(group) ?? leaves[0]?.icon ?? UiTable,\n ...(groupColor ? { iconColor: groupColor } : {}),\n onSelect: () => {},\n children,\n };\n });\n }, [\n surfaceColor,\n surfaceGroup,\n surfaceGroupColor,\n surfaceGroupIcon,\n surfaceIcon,\n surfaceLabel,\n surfaces,\n ]);\n\n const selectedCount = Object.keys(selectedRows).length;\n const selectedLabel = selected\n ? (surfaceLabel?.(selected.surface, selected.listOperation) ??\n selected.surface.title)\n : \"records\";\n\n const trigger = (\n <DropdownMenu\n label={triggerLabel}\n icon={UiAdd}\n variant=\"ghost\"\n size=\"sm\"\n align=\"left\"\n menuLabel=\"Context entity types\"\n menuClassName=\"min-w-56\"\n items={\n menuItems.length > 0\n ? menuItems\n : [\n {\n label: operationsLoading\n ? \"Loading entity types…\"\n : \"No entity listings available\",\n disabled: true,\n onSelect: () => {},\n },\n ]\n }\n />\n );\n\n const defaultDialog = (\n <Modal\n open={open}\n onClose={() => setOpen(false)}\n title={`Add ${selectedLabel} context`}\n size=\"2xl\"\n expandable\n scrollBody={false}\n footer={\n <div className=\"flex items-center justify-between gap-3\">\n <span className=\"text-xs text-muted-foreground\">\n {selectedCount === 0\n ? \"Select one or more records from the table.\"\n : `${selectedCount} record${selectedCount === 1 ? \"\" : \"s\"} selected`}\n </span>\n <div className=\"flex items-center gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setOpen(false)}\n disabled={attaching}\n >\n Cancel\n </Button>\n <Button\n type=\"button\"\n onClick={() => void attachSelected()}\n disabled={selectedCount === 0 || attaching}\n >\n {attaching\n ? \"Adding…\"\n : selectedCount > 0\n ? `Add ${selectedCount} record${selectedCount === 1 ? \"\" : \"s\"}`\n : \"Add records\"}\n </Button>\n </div>\n </div>\n }\n >\n <div className=\"flex min-h-0 flex-1 flex-col gap-4\">\n {surfaces.length === 0 && !operationsLoading ? (\n <p className=\"text-sm text-muted-foreground\">\n No attachable entity surfaces are available.\n </p>\n ) : null}\n {lookupQuery.error ? (\n <PickerError error={lookupQuery.error} prefix=\"Load filters\" />\n ) : null}\n {listQuery.error ? (\n <PickerError error={listQuery.error} prefix=\"Load records\" />\n ) : null}\n {attachError ? (\n <PickerError error={attachError} prefix=\"Attach record\" />\n ) : null}\n {attaching ? (\n <div role=\"status\" className=\"text-xs text-muted-foreground\">\n Loading full record details and adding context…\n </div>\n ) : null}\n\n {selected ? (\n <CommandOutput\n bare\n className=\"mt-0 flex-1\"\n response={markedListResponse ?? null}\n loading={listQuery.isLoading || listQuery.isFetching}\n loadingMessage=\"Loading records…\"\n emptyMessage=\"No matching records.\"\n ariaLabel=\"Context records\"\n rowSelection={{\n selectedRowIds: Object.keys(selectedRows),\n // Keep selections made on other pages: reconcile the table's\n // next id set against the rows on the current page, falling back\n // to the already-known row for ids from previously-viewed pages.\n onSelectionChange: (nextIds, rows) => {\n const rowByID = new Map(\n rows.flatMap((row) => {\n const id = getClickyRowId(row);\n return id ? [[id, row] as const] : [];\n }),\n );\n setSelectedRows((prev) =>\n Object.fromEntries(\n nextIds.flatMap((id) => {\n const row = rowByID.get(id) ?? prev[id];\n return row ? [[id, row] as const] : [];\n }),\n ),\n );\n },\n getRowId: (row, index) =>\n getClickyRowId(row) ?? `context-row-${index}`,\n isRowSelectable: (row) => {\n const id = getClickyRowId(row);\n return (\n !!id &&\n !existingIDs.has(\n entityContextItemID(selected.surface.key, id),\n )\n );\n },\n toggleOnRowClick: true,\n }}\n {...(filterConfig.search ? { search: filterConfig.search } : {})}\n {...(filterConfig.timeRange\n ? { timeRange: filterConfig.timeRange }\n : {})}\n {...(filterConfig.filters.length\n ? { externalFilters: filterConfig.filters }\n : {})}\n {...(pagination ? { pagination } : {})}\n {...(filterConfig.sort\n ? {\n sort: filterConfig.sort.value,\n onSortChange: filterConfig.sort.onChange,\n }\n : {})}\n />\n ) : null}\n\n {items.length ? (\n <p className=\"text-xs text-muted-foreground\">\n {items.length} context {items.length === 1 ? \"record\" : \"records\"}{\" \"}\n attached. Attached rows are disabled.\n </p>\n ) : null}\n </div>\n </Modal>\n );\n\n return (\n <>\n {trigger}\n {selected && surfaceRenderer\n ? surfaceRenderer({\n surface: selected.surface,\n listOperation: selected.listOperation,\n ...(selected.detailOperation\n ? { detailOperation: selected.detailOperation }\n : {}),\n items,\n onAdd,\n onAddMany: (added) =>\n onAddMany ? onAddMany(added) : added.forEach(onAdd),\n open,\n close: () => setOpen(false),\n defaultView: defaultDialog,\n })\n : defaultDialog}\n </>\n );\n}\n\nfunction parseResponseJSON(response: ExecutionResponse): unknown {\n const text = response.stdout || response.output || \"\";\n if (!text.trim()) return undefined;\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\n\nfunction markAttachedRows(\n response: ExecutionResponse | undefined,\n surfaceKey: string | undefined,\n existingIDs: Set<string>,\n): ExecutionResponse | undefined {\n if (!response || !surfaceKey || existingIDs.size === 0 || !response.parsed)\n return response;\n const parsed = response.parsed as Partial<ClickyDocument> &\n Partial<ClickyNode>;\n const node = parsed.version === 1 && parsed.node ? parsed.node : parsed;\n if (node.kind !== \"table\" || !node.rows?.length) return response;\n const tableNode = node as ClickyNode;\n const attached = tableNode.rows!.map((row) => {\n const id = getClickyRowId(row);\n return !!id && existingIDs.has(entityContextItemID(surfaceKey, id));\n });\n if (!attached.some(Boolean)) return response;\n\n const markerColumn = {\n name: \"__chat_context\",\n label: \"Context\",\n shrink: true,\n };\n const markedNode: ClickyNode = {\n ...tableNode,\n kind: \"table\",\n columns: [...(tableNode.columns ?? []), markerColumn],\n rows: tableNode.rows!.map((row, index) => ({\n ...row,\n cells: {\n ...row.cells,\n __chat_context: attached[index]\n ? { kind: \"badge\", badgeLabel: \"Attached\" }\n : { kind: \"text\", text: \"\", plain: \"\" },\n },\n })),\n };\n return {\n ...response,\n parsed:\n parsed.version === 1\n ? { ...(parsed as ClickyDocument), node: markedNode }\n : markedNode,\n };\n}\n\nfunction PickerError({ error, prefix }: { error: unknown; prefix: string }) {\n const message = error instanceof Error ? error.message : String(error);\n return (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/5 p-3 text-sm text-destructive\">\n <span className=\"font-medium\">{prefix}:</span> {message}\n </div>\n );\n}\n"],"names":["_a"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"OperationEntityContextPicker.js","sources":["../../src/rpc/OperationEntityContextPicker.tsx"],"sourcesContent":["import { useCallback, useMemo, useState, type ReactNode } from \"react\";\nimport type { ClickyRow } from \"../data/Clicky\";\nimport type { StaticIconComponent } from \"../data/Icon\";\nimport type { ChatContextItem } from \"../data/ai/context\";\nimport { UiAdd, UiTable } from \"../icons\";\nimport { DropdownMenu, type DropdownMenuItem } from \"../overlay/DropdownMenu\";\nimport { packParameterValues, type ParameterValues } from \"./formMetadata\";\nimport {\n filterOperationsBySurface,\n findSurfaceDetailOperation,\n findSurfaceListOperation,\n getClickySurfaces,\n getOperationClickyMeta,\n} from \"./clickyMetadata\";\nimport { OperationEntityPicker } from \"./OperationEntityPicker\";\nimport { getClickyRowId } from \"./rowNavigation\";\nimport { resolveSurfaceIcon } from \"./surfaceIconMap\";\nimport type {\n ClickySurface,\n ExecutionResponse,\n ResolvedOperation,\n} from \"./types\";\nimport { useOperations, type OperationsApiClient } from \"./useOperations\";\nimport {\n clickyRowRecord,\n contextItemFromEntityRow,\n entityContextItemID,\n} from \"./OperationEntityContextPicker.model\";\n\nexport type EntityContextSurfaceFilter = (\n surface: ClickySurface,\n listOperation: ResolvedOperation,\n) => boolean;\n\nexport type EntityContextSurfaceText = (\n surface: ClickySurface,\n listOperation: ResolvedOperation,\n) => string;\n\nexport type EntityContextSurfaceIcon = (\n surface: ClickySurface,\n listOperation: ResolvedOperation,\n) => string | StaticIconComponent | undefined;\n\nexport type EntityContextSurfaceColor = (\n surface: ClickySurface,\n listOperation: ResolvedOperation,\n) => string | undefined;\n\nexport type EntityContextGroupIcon = (\n group: string,\n) => string | StaticIconComponent | undefined;\n\nexport type EntityContextGroupColor = (group: string) => string | undefined;\n\n// EntityContextSurfaceRenderContext is handed to a host-supplied surfaceRenderer\n// so it can replace the picker dialog for selected surfaces, the way\n// ResultRenderer replaces a result surface. The generic dialog lists whatever\n// the entity's list operation returns, which is the right default and the wrong\n// answer for a surface the host already browses with a purpose-built UI — a\n// document tree, a map, a calendar. `defaultView` is the standard dialog;\n// return it unchanged to keep it.\n//\n// The whole dialog is replaced rather than only its body: a replacement that\n// owns selection has to own the confirm button too, or the footer would count\n// rows the host is no longer tracking.\nexport type EntityContextSurfaceRenderContext = {\n surface: ClickySurface;\n listOperation: ResolvedOperation;\n detailOperation?: ResolvedOperation;\n /** Already-attached items, so a replacement can disable them. */\n items: ChatContextItem[];\n onAdd: (item: ChatContextItem) => void;\n onAddMany: (items: ChatContextItem[]) => void;\n /** True while this surface is the one chosen from the dropdown. */\n open: boolean;\n close: () => void;\n defaultView: ReactNode;\n};\n\nexport type EntityContextSurfaceRenderer = (\n ctx: EntityContextSurfaceRenderContext,\n) => ReactNode;\n\nexport type OperationEntityContextPickerProps = {\n client: OperationsApiClient;\n items: ChatContextItem[];\n onAdd: (item: ChatContextItem) => void;\n onAddMany?: (items: ChatContextItem[]) => void;\n surfaceFilter?: EntityContextSurfaceFilter;\n surfaceLabel?: EntityContextSurfaceText;\n surfaceGroup?: EntityContextSurfaceText;\n surfaceIcon?: EntityContextSurfaceIcon;\n surfaceColor?: EntityContextSurfaceColor;\n /** Icon for a top-level provider/group row (the submenu trigger). */\n surfaceGroupIcon?: EntityContextGroupIcon;\n /** Icon colour for a top-level provider/group row. */\n surfaceGroupColor?: EntityContextGroupColor;\n /** Replaces the picker dialog for surfaces the host browses its own way. */\n surfaceRenderer?: EntityContextSurfaceRenderer;\n triggerLabel?: string;\n};\n\ntype ContextSurface = {\n surface: ClickySurface;\n listOperation: ResolvedOperation;\n detailOperation?: ResolvedOperation;\n};\n\nconst plural = (count: number) => (count === 1 ? \"\" : \"s\");\n\nexport function OperationEntityContextPicker({\n client,\n items,\n onAdd,\n onAddMany,\n surfaceFilter,\n surfaceLabel,\n surfaceGroup,\n surfaceIcon,\n surfaceColor,\n surfaceGroupIcon,\n surfaceGroupColor,\n surfaceRenderer,\n triggerLabel = \"Add context\",\n}: OperationEntityContextPickerProps) {\n const {\n operations,\n spec,\n isLoading: operationsLoading,\n } = useOperations(client);\n const [open, setOpen] = useState(false);\n const [surfaceKey, setSurfaceKey] = useState(\"\");\n\n const surfaces = useMemo<ContextSurface[]>(() => {\n return getClickySurfaces(spec)\n .flatMap((surface): ContextSurface[] => {\n const surfaceOperations = filterOperationsBySurface(\n operations,\n surface.key,\n );\n const listOperation = findSurfaceListOperation(\n surfaceOperations,\n surface.key,\n );\n if (!listOperation || listOperation.method.toUpperCase() !== \"GET\")\n return [];\n if (surfaceFilter && !surfaceFilter(surface, listOperation)) return [];\n const detailOperation = findSurfaceDetailOperation(\n surfaceOperations,\n surface.key,\n );\n return [\n {\n surface,\n listOperation,\n ...(detailOperation ? { detailOperation } : {}),\n },\n ];\n })\n .sort((left, right) => {\n const leftGroup =\n surfaceGroup?.(left.surface, left.listOperation) ??\n left.surface.parent ??\n \"\";\n const rightGroup =\n surfaceGroup?.(right.surface, right.listOperation) ??\n right.surface.parent ??\n \"\";\n return (\n leftGroup.localeCompare(rightGroup) ||\n left.surface.title.localeCompare(right.surface.title)\n );\n });\n }, [operations, spec, surfaceFilter, surfaceGroup]);\n\n const selected = surfaces.find((entry) => entry.surface.key === surfaceKey);\n const existingIDs = useMemo(\n () => new Set(items.map((item) => item.id)),\n [items],\n );\n\n const hydrateRow = useCallback(\n async (row: ClickyRow, listFilters: ParameterValues) => {\n if (!selected) throw new Error(\"Select an entity type first.\");\n const recordID = getClickyRowId(row);\n if (!recordID) {\n throw new Error(\"This row does not expose a stable record ID.\");\n }\n const contextID = entityContextItemID(selected.surface.key, recordID);\n if (existingIDs.has(contextID)) {\n throw new Error(\"This record is already attached.\");\n }\n\n let record: unknown = clickyRowRecord(row);\n if (selected.detailOperation) {\n const detailMeta = getOperationClickyMeta(selected.detailOperation);\n const idParam =\n detailMeta?.idParam ??\n selected.detailOperation.operation.parameters?.find(\n (parameter) => parameter.in === \"path\",\n )?.name ??\n \"id\";\n const detailParameterNames = new Set(\n selected.detailOperation.operation.parameters?.map(\n (parameter) => parameter.name,\n ) ?? [],\n );\n // The list's own scope (a database, an environment) rides along to the\n // detail call wherever the detail operation accepts the same parameter.\n const packedFilters = packParameterValues(\n listFilters,\n selected.listOperation.operation.parameters ?? [],\n );\n const detailParams = Object.fromEntries(\n Object.entries(packedFilters).filter(([key]) =>\n detailParameterNames.has(key),\n ),\n );\n detailParams[idParam] = recordID;\n const response = await client.executeCommand(\n selected.detailOperation.path,\n selected.detailOperation.method,\n detailParams,\n { Accept: \"application/json\" },\n );\n record = response.parsed ?? parseResponseJSON(response) ?? record;\n }\n\n const contextItem = contextItemFromEntityRow(\n selected.surface,\n row,\n record,\n );\n if (!contextItem)\n throw new Error(\"This row does not expose a stable record ID.\");\n return contextItem;\n },\n [client, existingIDs, selected],\n );\n\n // Adds every record that hydrates, then rejects with the failures so the\n // picker keeps the dialog open and shows them.\n const attachRows = useCallback(\n async (rows: ClickyRow[], listFilters: ParameterValues) => {\n const results = await Promise.allSettled(\n rows.map((row) => hydrateRow(row, listFilters)),\n );\n const added = results.flatMap((result) =>\n result.status === \"fulfilled\" ? [result.value] : [],\n );\n const failures = results.flatMap((result) =>\n result.status === \"rejected\" ? [result.reason] : [],\n );\n if (added.length > 0) {\n if (onAddMany) onAddMany(added);\n else added.forEach(onAdd);\n }\n if (failures.length > 0) {\n const first = failures[0];\n throw new Error(\n `${failures.length} record${plural(failures.length)} could not be attached: ${first instanceof Error ? first.message : String(first)}`,\n );\n }\n },\n [hydrateRow, onAdd, onAddMany],\n );\n\n const menuItems = useMemo<DropdownMenuItem[]>(() => {\n // `surfaces` is pre-sorted by group then title, so bucketing by group in\n // insertion order yields a stable provider → type tree without re-sorting.\n const groups: Array<{ group: string; leaves: DropdownMenuItem[] }> = [];\n const byGroup = new Map<string, DropdownMenuItem[]>();\n for (const entry of surfaces) {\n const group =\n surfaceGroup?.(entry.surface, entry.listOperation) ??\n entry.surface.parent ??\n \"Other\";\n const label =\n surfaceLabel?.(entry.surface, entry.listOperation) ??\n entry.surface.title;\n const icon =\n surfaceIcon?.(entry.surface, entry.listOperation) ??\n resolveSurfaceIcon(entry.surface.icon) ??\n UiTable;\n const iconColor = surfaceColor?.(entry.surface, entry.listOperation);\n const leaf: DropdownMenuItem = {\n label,\n title: label,\n icon,\n ...(iconColor ? { iconColor } : {}),\n onSelect: () => {\n setSurfaceKey(entry.surface.key);\n setOpen(true);\n },\n };\n let bucket = byGroup.get(group);\n if (!bucket) {\n bucket = [];\n byGroup.set(group, bucket);\n groups.push({ group, leaves: bucket });\n }\n bucket.push(leaf);\n }\n\n // A single group would nest everything under one lone submenu; render its\n // types flat instead.\n if (groups.length <= 1) return groups[0]?.leaves ?? [];\n\n return groups.map(({ group, leaves }): DropdownMenuItem => {\n const groupColor = surfaceGroupColor?.(group);\n // A submenu child already sits under its group header — don't repeat the\n // group name in the child label. The tooltip (title) and the detail dialog\n // keep the full label.\n const prefix = `${group} `;\n const children = leaves.map((leaf) =>\n typeof leaf.label === \"string\" && leaf.label.startsWith(prefix)\n ? { ...leaf, label: leaf.label.slice(prefix.length) }\n : leaf,\n );\n return {\n label: group,\n title: group,\n icon: surfaceGroupIcon?.(group) ?? leaves[0]?.icon ?? UiTable,\n ...(groupColor ? { iconColor: groupColor } : {}),\n onSelect: () => {},\n children,\n };\n });\n }, [\n surfaceColor,\n surfaceGroup,\n surfaceGroupColor,\n surfaceGroupIcon,\n surfaceIcon,\n surfaceLabel,\n surfaces,\n ]);\n\n const trigger = (\n <DropdownMenu\n label={triggerLabel}\n icon={UiAdd}\n variant=\"ghost\"\n size=\"sm\"\n align=\"left\"\n menuLabel=\"Context entity types\"\n menuClassName=\"min-w-56\"\n items={\n menuItems.length > 0\n ? menuItems\n : [\n {\n label: operationsLoading\n ? \"Loading entity types…\"\n : \"No entity listings available\",\n disabled: true,\n onSelect: () => {},\n },\n ]\n }\n />\n );\n\n if (!selected) return trigger;\n\n const selectedLabel =\n surfaceLabel?.(selected.surface, selected.listOperation) ??\n selected.surface.title;\n const selectedSurfaceKey = selected.surface.key;\n const defaultDialog = (\n <OperationEntityPicker\n open={open}\n onClose={() => setOpen(false)}\n title={`Add ${selectedLabel} context`}\n client={client}\n surfaceKey={selectedSurfaceKey}\n mode=\"multi\"\n onSelect={(_ids, rows, { filters }) => attachRows(rows, filters)}\n unavailableRows={{\n isUnavailable: (row) => {\n const id = getClickyRowId(row);\n return (\n !!id && existingIDs.has(entityContextItemID(selectedSurfaceKey, id))\n );\n },\n label: \"Attached\",\n columnLabel: \"Context\",\n }}\n selectLabel={({ count, pending }) =>\n pending\n ? \"Adding…\"\n : count > 0\n ? `Add ${count} record${plural(count)}`\n : \"Add records\"\n }\n note={\n items.length ? (\n <p className=\"text-xs text-muted-foreground\">\n {items.length} context {items.length === 1 ? \"record\" : \"records\"}{\" \"}\n attached. Attached rows are disabled.\n </p>\n ) : null\n }\n />\n );\n\n return (\n <>\n {trigger}\n {surfaceRenderer\n ? surfaceRenderer({\n surface: selected.surface,\n listOperation: selected.listOperation,\n ...(selected.detailOperation\n ? { detailOperation: selected.detailOperation }\n : {}),\n items,\n onAdd,\n onAddMany: (added) =>\n onAddMany ? onAddMany(added) : added.forEach(onAdd),\n open,\n close: () => setOpen(false),\n defaultView: defaultDialog,\n })\n : defaultDialog}\n </>\n );\n}\n\nfunction parseResponseJSON(response: ExecutionResponse): unknown {\n const text = response.stdout || response.output || \"\";\n if (!text.trim()) return undefined;\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\n"],"names":["_a"],"mappings":"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"}
|