@flanksource/clicky-ui 0.1.0 → 0.2.1
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 +29 -2
- package/dist/api-explorer.d.ts +5 -0
- package/dist/api-explorer.d.ts.map +1 -0
- package/dist/api-explorer.js +25 -0
- package/dist/api-explorer.js.map +1 -0
- package/dist/clicky.d.ts +2 -0
- package/dist/clicky.d.ts.map +1 -0
- package/dist/clicky.js +5 -0
- package/dist/clicky.js.map +1 -0
- package/dist/components/DatePicker.d.ts +18 -0
- package/dist/components/DatePicker.d.ts.map +1 -0
- package/dist/components/DatePicker.js +63 -0
- package/dist/components/DatePicker.js.map +1 -0
- package/dist/components/DateTimePicker.d.ts +18 -0
- package/dist/components/DateTimePicker.d.ts.map +1 -0
- package/dist/components/DateTimePicker.js +84 -0
- package/dist/components/DateTimePicker.js.map +1 -0
- package/dist/components/FilterBar.d.ts +180 -0
- package/dist/components/FilterBar.d.ts.map +1 -0
- package/dist/components/FilterBar.js +1685 -0
- package/dist/components/FilterBar.js.map +1 -0
- package/dist/components/MultiSelect.d.ts +19 -0
- package/dist/components/MultiSelect.d.ts.map +1 -0
- package/dist/components/MultiSelect.js +143 -0
- package/dist/components/MultiSelect.js.map +1 -0
- package/dist/components/RangeSlider.d.ts +16 -0
- package/dist/components/RangeSlider.d.ts.map +1 -0
- package/dist/components/RangeSlider.js +92 -0
- package/dist/components/RangeSlider.js.map +1 -0
- package/dist/components/button.d.ts +21 -0
- package/dist/components/button.d.ts.map +1 -0
- package/dist/components/button.js +126 -0
- package/dist/components/button.js.map +1 -0
- package/dist/components/density-switcher.d.ts +7 -0
- package/dist/components/density-switcher.d.ts.map +1 -0
- package/dist/components/density-switcher.js +32 -0
- package/dist/components/density-switcher.js.map +1 -0
- package/dist/components/icon-menu-picker.d.ts +22 -0
- package/dist/components/icon-menu-picker.d.ts.map +1 -0
- package/dist/components/icon-menu-picker.js +181 -0
- package/dist/components/icon-menu-picker.js.map +1 -0
- package/dist/components/select.d.ts +15 -0
- package/dist/components/select.d.ts.map +1 -0
- package/dist/components/select.js +39 -0
- package/dist/components/select.js.map +1 -0
- package/dist/components/theme-switcher.d.ts +7 -0
- package/dist/components/theme-switcher.d.ts.map +1 -0
- package/dist/components/theme-switcher.js +42 -0
- package/dist/components/theme-switcher.js.map +1 -0
- package/dist/components.d.ts +14 -0
- package/dist/components.d.ts.map +1 -0
- package/dist/components.js +31 -0
- package/dist/components.js.map +1 -0
- package/dist/data/AnsiHtml.d.ts +7 -0
- package/dist/data/AnsiHtml.d.ts.map +1 -0
- package/dist/data/AnsiHtml.js +71 -0
- package/dist/data/AnsiHtml.js.map +1 -0
- package/dist/data/Avatar.d.ts +32 -0
- package/dist/data/Avatar.d.ts.map +1 -0
- package/dist/data/Avatar.js +201 -0
- package/dist/data/Avatar.js.map +1 -0
- package/dist/data/AvatarBadge.d.ts +26 -0
- package/dist/data/AvatarBadge.d.ts.map +1 -0
- package/dist/data/AvatarBadge.js +104 -0
- package/dist/data/AvatarBadge.js.map +1 -0
- package/dist/data/Badge.d.ts +44 -0
- package/dist/data/Badge.d.ts.map +1 -0
- package/dist/data/Badge.js +667 -0
- package/dist/data/Badge.js.map +1 -0
- package/dist/data/Clicky.d.ts +147 -0
- package/dist/data/Clicky.d.ts.map +1 -0
- package/dist/data/Clicky.fixtures.d.ts +3 -0
- package/dist/data/Clicky.fixtures.d.ts.map +1 -0
- package/dist/data/Clicky.js +1960 -0
- package/dist/data/Clicky.js.map +1 -0
- package/dist/data/DataTable.d.ts +95 -0
- package/dist/data/DataTable.d.ts.map +1 -0
- package/dist/data/DataTable.js +1464 -0
- package/dist/data/DataTable.js.map +1 -0
- package/dist/data/FilterPill.d.ts +29 -0
- package/dist/data/FilterPill.d.ts.map +1 -0
- package/dist/data/FilterPill.js +153 -0
- package/dist/data/FilterPill.js.map +1 -0
- package/dist/data/Gauge.d.ts +15 -0
- package/dist/data/Gauge.d.ts.map +1 -0
- package/dist/data/Gauge.js +63 -0
- package/dist/data/Gauge.js.map +1 -0
- package/dist/data/Icon.d.ts +53 -0
- package/dist/data/Icon.d.ts.map +1 -0
- package/dist/data/Icon.js +115 -0
- package/dist/data/Icon.js.map +1 -0
- package/dist/data/JsonView.d.ts +8 -0
- package/dist/data/JsonView.d.ts.map +1 -0
- package/dist/data/JsonView.js +74 -0
- package/dist/data/JsonView.js.map +1 -0
- package/dist/data/KeyValueList.d.ts +17 -0
- package/dist/data/KeyValueList.d.ts.map +1 -0
- package/dist/data/KeyValueList.js +33 -0
- package/dist/data/KeyValueList.js.map +1 -0
- package/dist/data/LogViewer.d.ts +10 -0
- package/dist/data/LogViewer.d.ts.map +1 -0
- package/dist/data/LogViewer.js +46 -0
- package/dist/data/LogViewer.js.map +1 -0
- package/dist/data/LogsTable.d.ts +27 -0
- package/dist/data/LogsTable.d.ts.map +1 -0
- package/dist/data/LogsTable.js +580 -0
- package/dist/data/LogsTable.js.map +1 -0
- package/dist/data/Markdown.d.ts +6 -0
- package/dist/data/Markdown.d.ts.map +1 -0
- package/dist/data/Markdown.js +59 -0
- package/dist/data/Markdown.js.map +1 -0
- package/dist/data/MatrixTable.d.ts +22 -0
- package/dist/data/MatrixTable.d.ts.map +1 -0
- package/dist/data/MatrixTable.js +164 -0
- package/dist/data/MatrixTable.js.map +1 -0
- package/dist/data/MethodBadge.d.ts +6 -0
- package/dist/data/MethodBadge.d.ts.map +1 -0
- package/dist/data/MethodBadge.js +18 -0
- package/dist/data/MethodBadge.js.map +1 -0
- package/dist/data/ProgressBar.d.ts +13 -0
- package/dist/data/ProgressBar.d.ts.map +1 -0
- package/dist/data/ProgressBar.js +34 -0
- package/dist/data/ProgressBar.js.map +1 -0
- package/dist/data/SortableHeader.d.ts +12 -0
- package/dist/data/SortableHeader.d.ts.map +1 -0
- package/dist/data/SortableHeader.js +33 -0
- package/dist/data/SortableHeader.js.map +1 -0
- package/dist/data/TabButton.d.ts +12 -0
- package/dist/data/TabButton.d.ts.map +1 -0
- package/dist/data/TabButton.js +45 -0
- package/dist/data/TabButton.js.map +1 -0
- package/dist/data/Tree.d.ts +35 -0
- package/dist/data/Tree.d.ts.map +1 -0
- package/dist/data/Tree.js +236 -0
- package/dist/data/Tree.js.map +1 -0
- package/dist/data/TreeGroupHeader.d.ts +11 -0
- package/dist/data/TreeGroupHeader.d.ts.map +1 -0
- package/dist/data/TreeGroupHeader.js +41 -0
- package/dist/data/TreeGroupHeader.js.map +1 -0
- package/dist/data/TreeNode.d.ts +43 -0
- package/dist/data/TreeNode.d.ts.map +1 -0
- package/dist/data/TreeNode.js +100 -0
- package/dist/data/TreeNode.js.map +1 -0
- package/dist/data/cells/StatusDot.d.ts +11 -0
- package/dist/data/cells/StatusDot.d.ts.map +1 -0
- package/dist/data/cells/StatusDot.js +38 -0
- package/dist/data/cells/StatusDot.js.map +1 -0
- package/dist/data/cells/TagList.d.ts +59 -0
- package/dist/data/cells/TagList.d.ts.map +1 -0
- package/dist/data/cells/TagList.js +257 -0
- package/dist/data/cells/TagList.js.map +1 -0
- package/dist/data/cells/Timestamp.d.ts +46 -0
- package/dist/data/cells/Timestamp.d.ts.map +1 -0
- package/dist/data/cells/Timestamp.js +146 -0
- package/dist/data/cells/Timestamp.js.map +1 -0
- package/dist/data/cells/status-mapping.d.ts +8 -0
- package/dist/data/cells/status-mapping.d.ts.map +1 -0
- package/dist/data/cells/status-mapping.js +44 -0
- package/dist/data/cells/status-mapping.js.map +1 -0
- package/dist/data/code-highlight.d.ts +12 -0
- package/dist/data/code-highlight.d.ts.map +1 -0
- package/dist/data/code-highlight.js +28 -0
- package/dist/data/code-highlight.js.map +1 -0
- package/dist/data/diagnostics/DiagnosticsDetailPanel.d.ts +9 -0
- package/dist/data/diagnostics/DiagnosticsDetailPanel.d.ts.map +1 -0
- package/dist/data/diagnostics/DiagnosticsDetailPanel.js +445 -0
- package/dist/data/diagnostics/DiagnosticsDetailPanel.js.map +1 -0
- package/dist/data/diagnostics/DiagnosticsTree.d.ts +9 -0
- package/dist/data/diagnostics/DiagnosticsTree.d.ts.map +1 -0
- package/dist/data/diagnostics/DiagnosticsTree.js +78 -0
- package/dist/data/diagnostics/DiagnosticsTree.js.map +1 -0
- package/dist/data/diagnostics/ErrorDetails.d.ts +20 -0
- package/dist/data/diagnostics/ErrorDetails.d.ts.map +1 -0
- package/dist/data/diagnostics/ErrorDetails.js +157 -0
- package/dist/data/diagnostics/ErrorDetails.js.map +1 -0
- package/dist/data/diagnostics/GoroutineCard.d.ts +10 -0
- package/dist/data/diagnostics/GoroutineCard.d.ts.map +1 -0
- package/dist/data/diagnostics/GoroutineCard.js +75 -0
- package/dist/data/diagnostics/GoroutineCard.js.map +1 -0
- package/dist/data/diagnostics/JvmStackTrace.d.ts +11 -0
- package/dist/data/diagnostics/JvmStackTrace.d.ts.map +1 -0
- package/dist/data/diagnostics/JvmStackTrace.js +26 -0
- package/dist/data/diagnostics/JvmStackTrace.js.map +1 -0
- package/dist/data/diagnostics/RenderedStackTrace.d.ts +18 -0
- package/dist/data/diagnostics/RenderedStackTrace.d.ts.map +1 -0
- package/dist/data/diagnostics/RenderedStackTrace.js +235 -0
- package/dist/data/diagnostics/RenderedStackTrace.js.map +1 -0
- package/dist/data/diagnostics/ThreadCard.d.ts +10 -0
- package/dist/data/diagnostics/ThreadCard.d.ts.map +1 -0
- package/dist/data/diagnostics/ThreadCard.js +78 -0
- package/dist/data/diagnostics/ThreadCard.js.map +1 -0
- package/dist/data/diagnostics/error-diagnostics.d.ts +26 -0
- package/dist/data/diagnostics/error-diagnostics.d.ts.map +1 -0
- package/dist/data/diagnostics/error-diagnostics.js +108 -0
- package/dist/data/diagnostics/error-diagnostics.js.map +1 -0
- package/dist/data/diagnostics/fixtures.d.ts +3 -0
- package/dist/data/diagnostics/fixtures.d.ts.map +1 -0
- package/dist/data/diagnostics/jvm-stacktrace.d.ts +34 -0
- package/dist/data/diagnostics/jvm-stacktrace.d.ts.map +1 -0
- package/dist/data/diagnostics/jvm-stacktrace.js +190 -0
- package/dist/data/diagnostics/jvm-stacktrace.js.map +1 -0
- package/dist/data/diagnostics/stacktrace-parse.d.ts +11 -0
- package/dist/data/diagnostics/stacktrace-parse.d.ts.map +1 -0
- package/dist/data/diagnostics/stacktrace-parse.js +87 -0
- package/dist/data/diagnostics/stacktrace-parse.js.map +1 -0
- package/dist/data/diagnostics/stacktrace.d.ts +38 -0
- package/dist/data/diagnostics/stacktrace.d.ts.map +1 -0
- package/dist/data/diagnostics/stacktrace.js +119 -0
- package/dist/data/diagnostics/stacktrace.js.map +1 -0
- package/dist/data/diagnostics/types.d.ts +30 -0
- package/dist/data/diagnostics/types.d.ts.map +1 -0
- package/dist/data/diagnostics/utils.d.ts +8 -0
- package/dist/data/diagnostics/utils.d.ts.map +1 -0
- package/dist/data/diagnostics/utils.js +59 -0
- package/dist/data/diagnostics/utils.js.map +1 -0
- package/dist/data/har/HarPanel.d.ts +9 -0
- package/dist/data/har/HarPanel.d.ts.map +1 -0
- package/dist/data/har/HarPanel.js +175 -0
- package/dist/data/har/HarPanel.js.map +1 -0
- package/dist/data/har/fixtures.d.ts +3 -0
- package/dist/data/har/fixtures.d.ts.map +1 -0
- package/dist/data/har/types.d.ts +47 -0
- package/dist/data/har/types.d.ts.map +1 -0
- package/dist/data.d.ts +39 -0
- package/dist/data.d.ts.map +1 -0
- package/dist/data.js +109 -0
- package/dist/data.js.map +1 -0
- package/dist/hooks/use-density.d.ts +22 -0
- package/dist/hooks/use-density.d.ts.map +1 -0
- package/dist/hooks/use-density.js +54 -0
- package/dist/hooks/use-density.js.map +1 -0
- package/dist/hooks/use-history-route.d.ts +6 -0
- package/dist/hooks/use-history-route.d.ts.map +1 -0
- package/dist/hooks/use-history-route.js +31 -0
- package/dist/hooks/use-history-route.js.map +1 -0
- package/dist/hooks/use-sort.d.ts +17 -0
- package/dist/hooks/use-sort.d.ts.map +1 -0
- package/dist/hooks/use-sort.js +42 -0
- package/dist/hooks/use-sort.js.map +1 -0
- package/dist/hooks/use-theme.d.ts +17 -0
- package/dist/hooks/use-theme.d.ts.map +1 -0
- package/dist/hooks/use-theme.js +68 -0
- package/dist/hooks/use-theme.js.map +1 -0
- package/dist/hooks.d.ts +5 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +14 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +193 -0
- package/dist/index.js.map +1 -0
- package/dist/layout/Section.d.ts +23 -0
- package/dist/layout/Section.d.ts.map +1 -0
- package/dist/layout/Section.js +73 -0
- package/dist/layout/Section.js.map +1 -0
- package/dist/layout/SplitPane.d.ts +13 -0
- package/dist/layout/SplitPane.d.ts.map +1 -0
- package/dist/layout/SplitPane.js +72 -0
- package/dist/layout/SplitPane.js.map +1 -0
- package/dist/lib/palette.d.ts +4 -0
- package/dist/lib/palette.d.ts.map +1 -0
- package/dist/lib/palette.js +35 -0
- package/dist/lib/palette.js.map +1 -0
- package/dist/lib/size.d.ts +6 -0
- package/dist/lib/size.d.ts.map +1 -0
- package/dist/lib/size.js +14 -0
- package/dist/lib/size.js.map +1 -0
- package/dist/lib/utils.d.ts +3 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +9 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/overlay/HoverCard.d.ts +13 -0
- package/dist/overlay/HoverCard.d.ts.map +1 -0
- package/dist/overlay/HoverCard.js +170 -0
- package/dist/overlay/HoverCard.js.map +1 -0
- package/dist/overlay/Modal.d.ts +17 -0
- package/dist/overlay/Modal.d.ts.map +1 -0
- package/dist/overlay/Modal.js +91 -0
- package/dist/overlay/Modal.js.map +1 -0
- package/dist/rpc/AcceptPicker.d.ts +52 -0
- package/dist/rpc/AcceptPicker.d.ts.map +1 -0
- package/dist/rpc/AcceptPicker.js +126 -0
- package/dist/rpc/AcceptPicker.js.map +1 -0
- package/dist/rpc/ApiExplorer.d.ts +11 -0
- package/dist/rpc/ApiExplorer.d.ts.map +1 -0
- package/dist/rpc/ApiExplorer.js +37 -0
- package/dist/rpc/ApiExplorer.js.map +1 -0
- package/dist/rpc/CommandForm.d.ts +15 -0
- package/dist/rpc/CommandForm.d.ts.map +1 -0
- package/dist/rpc/CommandForm.js +356 -0
- package/dist/rpc/CommandForm.js.map +1 -0
- package/dist/rpc/CommandOutput.d.ts +11 -0
- package/dist/rpc/CommandOutput.d.ts.map +1 -0
- package/dist/rpc/CommandOutput.js +195 -0
- package/dist/rpc/CommandOutput.js.map +1 -0
- package/dist/rpc/EndpointList.d.ts +18 -0
- package/dist/rpc/EndpointList.d.ts.map +1 -0
- package/dist/rpc/EndpointList.js +56 -0
- package/dist/rpc/EndpointList.js.map +1 -0
- package/dist/rpc/EntityExplorerApp.d.ts +15 -0
- package/dist/rpc/EntityExplorerApp.d.ts.map +1 -0
- package/dist/rpc/EntityExplorerApp.js +282 -0
- package/dist/rpc/EntityExplorerApp.js.map +1 -0
- package/dist/rpc/ExecutionResult.d.ts +14 -0
- package/dist/rpc/ExecutionResult.d.ts.map +1 -0
- package/dist/rpc/ExecutionResult.js +51 -0
- package/dist/rpc/ExecutionResult.js.map +1 -0
- package/dist/rpc/FilterForm.d.ts +22 -0
- package/dist/rpc/FilterForm.d.ts.map +1 -0
- package/dist/rpc/FilterForm.js +392 -0
- package/dist/rpc/FilterForm.js.map +1 -0
- package/dist/rpc/InlineError.d.ts +7 -0
- package/dist/rpc/InlineError.d.ts.map +1 -0
- package/dist/rpc/InlineError.js +54 -0
- package/dist/rpc/InlineError.js.map +1 -0
- package/dist/rpc/OperationActionDialog.d.ts +12 -0
- package/dist/rpc/OperationActionDialog.d.ts.map +1 -0
- package/dist/rpc/OperationActionDialog.js +105 -0
- package/dist/rpc/OperationActionDialog.js.map +1 -0
- package/dist/rpc/OperationCatalog.d.ts +21 -0
- package/dist/rpc/OperationCatalog.d.ts.map +1 -0
- package/dist/rpc/OperationCatalog.js +339 -0
- package/dist/rpc/OperationCatalog.js.map +1 -0
- package/dist/rpc/OperationCommandPage.d.ts +22 -0
- package/dist/rpc/OperationCommandPage.d.ts.map +1 -0
- package/dist/rpc/OperationCommandPage.js +484 -0
- package/dist/rpc/OperationCommandPage.js.map +1 -0
- package/dist/rpc/OperationEntityPage.d.ts +23 -0
- package/dist/rpc/OperationEntityPage.d.ts.map +1 -0
- package/dist/rpc/OperationEntityPage.js +218 -0
- package/dist/rpc/OperationEntityPage.js.map +1 -0
- package/dist/rpc/classify.d.ts +8 -0
- package/dist/rpc/classify.d.ts.map +1 -0
- package/dist/rpc/classify.js +76 -0
- package/dist/rpc/classify.js.map +1 -0
- package/dist/rpc/clickyMetadata.d.ts +12 -0
- package/dist/rpc/clickyMetadata.d.ts.map +1 -0
- package/dist/rpc/clickyMetadata.js +71 -0
- package/dist/rpc/clickyMetadata.js.map +1 -0
- package/dist/rpc/formMetadata.d.ts +27 -0
- package/dist/rpc/formMetadata.d.ts.map +1 -0
- package/dist/rpc/formMetadata.js +250 -0
- package/dist/rpc/formMetadata.js.map +1 -0
- package/dist/rpc/types.d.ts +109 -0
- package/dist/rpc/types.d.ts.map +1 -0
- package/dist/rpc/types.js +8 -0
- package/dist/rpc/types.js.map +1 -0
- package/dist/rpc/useOperations.d.ts +346 -0
- package/dist/rpc/useOperations.d.ts.map +1 -0
- package/dist/rpc/useOperations.js +31 -0
- package/dist/rpc/useOperations.js.map +1 -0
- package/dist/rpc.d.ts +14 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +37 -0
- package/dist/rpc.js.map +1 -0
- package/dist/styles.css +2 -0
- package/dist/styles.d.ts +1 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +2 -0
- package/dist/styles.js.map +1 -0
- package/dist/tailwind-preset.d.ts +4 -0
- package/dist/tailwind-preset.d.ts.map +1 -0
- package/dist/tailwind-preset.js +69 -0
- package/dist/tailwind-preset.js.map +1 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +12 -0
- package/dist/utils.js.map +1 -0
- package/package.json +83 -40
- package/dist/index.d.mts +0 -834
- package/dist/index.d.mts.map +0 -1
- package/dist/index.mjs +0 -2918
- package/dist/index.mjs.map +0 -1
- package/dist/tailwind-preset.d.mts +0 -7
- package/dist/tailwind-preset.d.mts.map +0 -1
- package/dist/tailwind-preset.mjs +0 -64
- package/dist/tailwind-preset.mjs.map +0 -1
- package/src/styles/tokens.css +0 -78
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, useState, useRef, useEffect } from "react";
|
|
3
|
+
import { useQuery } from "@tanstack/react-query";
|
|
4
|
+
import { Button } from "../components/button.js";
|
|
5
|
+
import { FilterPill } from "../data/FilterPill.js";
|
|
6
|
+
import { Icon } from "../data/Icon.js";
|
|
7
|
+
import { cn } from "../lib/utils.js";
|
|
8
|
+
import { buildInitialParameterValues, useDebouncedRecord, packParameterValues, parametersToFormConfig, pruneParameterValues, titleCase } from "./formMetadata.js";
|
|
9
|
+
function FilterForm({
|
|
10
|
+
client,
|
|
11
|
+
path,
|
|
12
|
+
method,
|
|
13
|
+
parameters = [],
|
|
14
|
+
initialValues = {},
|
|
15
|
+
lockedValues = {},
|
|
16
|
+
hideLocked = false,
|
|
17
|
+
enableLookup = method.toUpperCase() === "GET",
|
|
18
|
+
autoSubmit = false,
|
|
19
|
+
submitLabel = "Execute request",
|
|
20
|
+
submittingLabel = "Executing…",
|
|
21
|
+
emptyMessage = "This operation does not require input.",
|
|
22
|
+
isSubmitting = false,
|
|
23
|
+
className,
|
|
24
|
+
onSubmit
|
|
25
|
+
}) {
|
|
26
|
+
const resetKey = useMemo(
|
|
27
|
+
() => `${method}:${path}:${JSON.stringify(initialValues)}:${JSON.stringify(lockedValues)}`,
|
|
28
|
+
[initialValues, lockedValues, method, path]
|
|
29
|
+
);
|
|
30
|
+
const [values, setValues] = useState(
|
|
31
|
+
() => buildInitialParameterValues(parameters, method, lockedValues, initialValues)
|
|
32
|
+
);
|
|
33
|
+
const [error, setError] = useState("");
|
|
34
|
+
const debouncedValues = useDebouncedRecord(values, 250);
|
|
35
|
+
const lastAutoSubmitted = useRef(null);
|
|
36
|
+
const lookupQuery = useQuery({
|
|
37
|
+
queryKey: ["filter-form-lookup", method, path, debouncedValues],
|
|
38
|
+
queryFn: async () => {
|
|
39
|
+
var _a;
|
|
40
|
+
return await ((_a = client.lookupFilters) == null ? void 0 : _a.call(
|
|
41
|
+
client,
|
|
42
|
+
path,
|
|
43
|
+
method,
|
|
44
|
+
packParameterValues(debouncedValues, parameters),
|
|
45
|
+
{ Accept: "application/json+clicky" }
|
|
46
|
+
)) ?? { filters: {} };
|
|
47
|
+
},
|
|
48
|
+
enabled: enableLookup && !!client.lookupFilters && parameters.some((param) => param.in === "query"),
|
|
49
|
+
staleTime: 3e4,
|
|
50
|
+
retry: 0
|
|
51
|
+
});
|
|
52
|
+
const formConfig = useMemo(
|
|
53
|
+
() => parametersToFormConfig(parameters, values, setValues, {
|
|
54
|
+
lookup: lookupQuery.data,
|
|
55
|
+
lockedValues,
|
|
56
|
+
hideLocked
|
|
57
|
+
}),
|
|
58
|
+
[hideLocked, lockedValues, lookupQuery.data, parameters, values]
|
|
59
|
+
);
|
|
60
|
+
const hasFields = formConfig.filters.length > 0 || formConfig.timeRange != null;
|
|
61
|
+
async function handleSubmit(event) {
|
|
62
|
+
event == null ? void 0 : event.preventDefault();
|
|
63
|
+
const missingRequired = parameters.filter((param) => {
|
|
64
|
+
if (!param.required) return false;
|
|
65
|
+
const value = lockedValues[param.name] ?? values[param.name] ?? "";
|
|
66
|
+
return value.trim() === "";
|
|
67
|
+
});
|
|
68
|
+
if (missingRequired.length > 0) {
|
|
69
|
+
setError(
|
|
70
|
+
`Missing required fields: ${missingRequired.map((param) => titleCase(param.name)).join(", ")}`
|
|
71
|
+
);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
setError("");
|
|
75
|
+
await onSubmit(pruneParameterValues(values));
|
|
76
|
+
}
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
setValues(buildInitialParameterValues(parameters, method, lockedValues, initialValues));
|
|
79
|
+
setError("");
|
|
80
|
+
lastAutoSubmitted.current = null;
|
|
81
|
+
}, [resetKey]);
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
if (!autoSubmit) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const missingRequired = parameters.filter((param) => {
|
|
87
|
+
if (!param.required) return false;
|
|
88
|
+
const value = lockedValues[param.name] ?? debouncedValues[param.name] ?? "";
|
|
89
|
+
return value.trim() === "";
|
|
90
|
+
});
|
|
91
|
+
if (missingRequired.length > 0) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const submittedValues = pruneParameterValues(debouncedValues);
|
|
95
|
+
const signature = JSON.stringify(submittedValues);
|
|
96
|
+
if (lastAutoSubmitted.current === signature) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
lastAutoSubmitted.current = signature;
|
|
100
|
+
setError("");
|
|
101
|
+
void onSubmit(submittedValues);
|
|
102
|
+
}, [autoSubmit, debouncedValues, lockedValues, onSubmit, parameters]);
|
|
103
|
+
return /* @__PURE__ */ jsxs("form", { className: "space-y-3", onSubmit: handleSubmit, children: [
|
|
104
|
+
hasFields ? /* @__PURE__ */ jsx(
|
|
105
|
+
ParameterGrid,
|
|
106
|
+
{
|
|
107
|
+
autoSubmit,
|
|
108
|
+
filters: formConfig.filters,
|
|
109
|
+
isSubmitting,
|
|
110
|
+
submitLabel,
|
|
111
|
+
submittingLabel,
|
|
112
|
+
...formConfig.timeRange ? { timeRange: formConfig.timeRange } : {},
|
|
113
|
+
...className ? { className } : {}
|
|
114
|
+
}
|
|
115
|
+
) : /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4", children: [
|
|
116
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: emptyMessage }),
|
|
117
|
+
/* @__PURE__ */ jsx(Button, { type: "button", onClick: handleSubmit, disabled: isSubmitting, children: isSubmitting ? submittingLabel : submitLabel })
|
|
118
|
+
] }),
|
|
119
|
+
error && /* @__PURE__ */ jsx("div", { className: "rounded-md border border-destructive/40 bg-destructive/5 p-3 text-sm text-destructive", children: error })
|
|
120
|
+
] });
|
|
121
|
+
}
|
|
122
|
+
function ParameterGrid({
|
|
123
|
+
filters,
|
|
124
|
+
timeRange,
|
|
125
|
+
autoSubmit,
|
|
126
|
+
isSubmitting,
|
|
127
|
+
submitLabel,
|
|
128
|
+
submittingLabel,
|
|
129
|
+
className
|
|
130
|
+
}) {
|
|
131
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-3", className), children: [
|
|
132
|
+
/* @__PURE__ */ jsxs("div", { className: "divide-y divide-border border-y border-border", children: [
|
|
133
|
+
filters.map((filter) => /* @__PURE__ */ jsx(ParameterRow, { filter }, filter.key)),
|
|
134
|
+
timeRange && /* @__PURE__ */ jsx(TimeRangeRow, { timeRange })
|
|
135
|
+
] }),
|
|
136
|
+
!autoSubmit && /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(Button, { type: "submit", disabled: isSubmitting, children: isSubmitting ? submittingLabel : submitLabel }) })
|
|
137
|
+
] });
|
|
138
|
+
}
|
|
139
|
+
function ParameterRow({ filter }) {
|
|
140
|
+
const id = `clicky-param-${filter.key.replace(/[^a-zA-Z0-9_-]/g, "-")}`;
|
|
141
|
+
return /* @__PURE__ */ jsxs(
|
|
142
|
+
"div",
|
|
143
|
+
{
|
|
144
|
+
title: filter.description,
|
|
145
|
+
className: cn(
|
|
146
|
+
"grid grid-cols-1 gap-2 py-2 sm:grid-cols-[minmax(8rem,14rem)_minmax(0,1fr)] sm:items-center",
|
|
147
|
+
filter.disabled && "opacity-60"
|
|
148
|
+
),
|
|
149
|
+
children: [
|
|
150
|
+
/* @__PURE__ */ jsx("label", { htmlFor: id, className: "text-sm font-medium text-muted-foreground", children: filter.label }),
|
|
151
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0", children: renderParameterInput(filter, id) })
|
|
152
|
+
]
|
|
153
|
+
}
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
function renderParameterInput(filter, id) {
|
|
157
|
+
if (filter.kind === "enum") {
|
|
158
|
+
return /* @__PURE__ */ jsxs(
|
|
159
|
+
"select",
|
|
160
|
+
{
|
|
161
|
+
id,
|
|
162
|
+
"aria-label": filter.label,
|
|
163
|
+
className: inputClassName,
|
|
164
|
+
value: filter.value,
|
|
165
|
+
disabled: filter.disabled,
|
|
166
|
+
onChange: (event) => filter.onChange(event.target.value),
|
|
167
|
+
children: [
|
|
168
|
+
/* @__PURE__ */ jsx("option", { value: "", children: filter.placeholder ?? `Any ${filter.label.toLowerCase()}` }),
|
|
169
|
+
filter.options.map((option) => /* @__PURE__ */ jsx("option", { value: option.value, children: option.label ?? option.value }, option.value))
|
|
170
|
+
]
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
if (filter.kind === "boolean") {
|
|
175
|
+
return /* @__PURE__ */ jsx("div", { className: "flex h-8 items-center", children: /* @__PURE__ */ jsx(
|
|
176
|
+
"input",
|
|
177
|
+
{
|
|
178
|
+
id,
|
|
179
|
+
type: "checkbox",
|
|
180
|
+
"aria-label": filter.label,
|
|
181
|
+
className: "h-4 w-4 accent-primary disabled:cursor-not-allowed",
|
|
182
|
+
checked: filter.value,
|
|
183
|
+
disabled: filter.disabled,
|
|
184
|
+
onChange: (event) => filter.onChange(event.target.checked)
|
|
185
|
+
}
|
|
186
|
+
) });
|
|
187
|
+
}
|
|
188
|
+
if (filter.kind === "lookup") {
|
|
189
|
+
const listId = `${id}-options`;
|
|
190
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
191
|
+
/* @__PURE__ */ jsx(
|
|
192
|
+
"input",
|
|
193
|
+
{
|
|
194
|
+
id,
|
|
195
|
+
type: filter.inputType === "number" ? "number" : "text",
|
|
196
|
+
"aria-label": filter.label,
|
|
197
|
+
className: inputClassName,
|
|
198
|
+
placeholder: filter.placeholder ?? "Value",
|
|
199
|
+
value: filter.value,
|
|
200
|
+
list: listId,
|
|
201
|
+
disabled: filter.disabled,
|
|
202
|
+
onChange: (event) => filter.onChange(event.target.value)
|
|
203
|
+
}
|
|
204
|
+
),
|
|
205
|
+
/* @__PURE__ */ jsx("datalist", { id: listId, children: filter.options.map((option) => /* @__PURE__ */ jsx(
|
|
206
|
+
"option",
|
|
207
|
+
{
|
|
208
|
+
value: option.value,
|
|
209
|
+
label: option.label ?? option.value,
|
|
210
|
+
disabled: option.disabled
|
|
211
|
+
},
|
|
212
|
+
option.value
|
|
213
|
+
)) })
|
|
214
|
+
] });
|
|
215
|
+
}
|
|
216
|
+
if (filter.kind === "lookup-multi") {
|
|
217
|
+
const listId = `${id}-options`;
|
|
218
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
219
|
+
/* @__PURE__ */ jsx(
|
|
220
|
+
"input",
|
|
221
|
+
{
|
|
222
|
+
id,
|
|
223
|
+
type: "text",
|
|
224
|
+
"aria-label": filter.label,
|
|
225
|
+
className: inputClassName,
|
|
226
|
+
placeholder: filter.placeholder ?? "value-1, value-2",
|
|
227
|
+
value: filter.value.join(", "),
|
|
228
|
+
list: listId,
|
|
229
|
+
disabled: filter.disabled,
|
|
230
|
+
onChange: (event) => filter.onChange(splitCommaValues(event.target.value))
|
|
231
|
+
}
|
|
232
|
+
),
|
|
233
|
+
/* @__PURE__ */ jsx("datalist", { id: listId, children: filter.options.map((option) => /* @__PURE__ */ jsx(
|
|
234
|
+
"option",
|
|
235
|
+
{
|
|
236
|
+
value: option.value,
|
|
237
|
+
label: option.label ?? option.value,
|
|
238
|
+
disabled: option.disabled
|
|
239
|
+
},
|
|
240
|
+
option.value
|
|
241
|
+
)) })
|
|
242
|
+
] });
|
|
243
|
+
}
|
|
244
|
+
if (filter.kind === "multi") {
|
|
245
|
+
return /* @__PURE__ */ jsx(MultiParameterInput, { filter, id });
|
|
246
|
+
}
|
|
247
|
+
if (filter.kind === "text") {
|
|
248
|
+
return /* @__PURE__ */ jsx(
|
|
249
|
+
"input",
|
|
250
|
+
{
|
|
251
|
+
id,
|
|
252
|
+
type: "text",
|
|
253
|
+
"aria-label": filter.label,
|
|
254
|
+
className: inputClassName,
|
|
255
|
+
placeholder: filter.placeholder ?? "Value",
|
|
256
|
+
value: filter.value,
|
|
257
|
+
disabled: filter.disabled,
|
|
258
|
+
onChange: (event) => filter.onChange(event.target.value)
|
|
259
|
+
}
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
return /* @__PURE__ */ jsx(
|
|
263
|
+
"input",
|
|
264
|
+
{
|
|
265
|
+
id,
|
|
266
|
+
type: "text",
|
|
267
|
+
"aria-label": filter.label,
|
|
268
|
+
className: inputClassName,
|
|
269
|
+
value: JSON.stringify(filter.value),
|
|
270
|
+
disabled: true,
|
|
271
|
+
readOnly: true
|
|
272
|
+
}
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
function MultiParameterInput({ filter, id }) {
|
|
276
|
+
const [query, setQuery] = useState("");
|
|
277
|
+
const showOptionFilter = filter.options.length > 7;
|
|
278
|
+
const visibleOptions = useMemo(() => {
|
|
279
|
+
const normalized = query.trim().toLowerCase();
|
|
280
|
+
if (!normalized) return filter.options;
|
|
281
|
+
return filter.options.filter(
|
|
282
|
+
(option) => multiOptionText(option).toLowerCase().includes(normalized)
|
|
283
|
+
);
|
|
284
|
+
}, [filter.options, query]);
|
|
285
|
+
const setMode = (value, mode) => {
|
|
286
|
+
if (filter.disabled) return;
|
|
287
|
+
const next = { ...filter.value };
|
|
288
|
+
if (mode === "include" || mode === "exclude") {
|
|
289
|
+
next[value] = mode;
|
|
290
|
+
} else {
|
|
291
|
+
delete next[value];
|
|
292
|
+
}
|
|
293
|
+
filter.onChange(next);
|
|
294
|
+
};
|
|
295
|
+
return /* @__PURE__ */ jsxs(
|
|
296
|
+
"div",
|
|
297
|
+
{
|
|
298
|
+
id,
|
|
299
|
+
role: "group",
|
|
300
|
+
"aria-label": filter.label,
|
|
301
|
+
className: "rounded-md border border-input bg-background p-2",
|
|
302
|
+
children: [
|
|
303
|
+
showOptionFilter && /* @__PURE__ */ jsxs("label", { className: "mb-2 flex items-center gap-2 rounded-md border border-input bg-background px-2", children: [
|
|
304
|
+
/* @__PURE__ */ jsx(Icon, { name: "codicon:search", className: "shrink-0 text-muted-foreground" }),
|
|
305
|
+
/* @__PURE__ */ jsx(
|
|
306
|
+
"input",
|
|
307
|
+
{
|
|
308
|
+
type: "search",
|
|
309
|
+
"aria-label": `Filter ${filter.label} options`,
|
|
310
|
+
className: "h-8 min-w-0 flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground",
|
|
311
|
+
placeholder: `Filter ${filter.label.toLowerCase()}`,
|
|
312
|
+
value: query,
|
|
313
|
+
disabled: filter.disabled,
|
|
314
|
+
onChange: (event) => setQuery(event.target.value)
|
|
315
|
+
}
|
|
316
|
+
)
|
|
317
|
+
] }),
|
|
318
|
+
/* @__PURE__ */ jsxs("div", { className: "max-h-56 space-y-1 overflow-auto", children: [
|
|
319
|
+
visibleOptions.map((option) => {
|
|
320
|
+
const mode = filter.value[option.value] ?? "neutral";
|
|
321
|
+
return /* @__PURE__ */ jsx(
|
|
322
|
+
FilterPill,
|
|
323
|
+
{
|
|
324
|
+
className: "w-full justify-between",
|
|
325
|
+
label: option.label,
|
|
326
|
+
mode,
|
|
327
|
+
title: option.title ?? multiOptionText(option),
|
|
328
|
+
togglePosition: "right",
|
|
329
|
+
onModeChange: (next) => setMode(option.value, next)
|
|
330
|
+
},
|
|
331
|
+
option.value
|
|
332
|
+
);
|
|
333
|
+
}),
|
|
334
|
+
visibleOptions.length === 0 && /* @__PURE__ */ jsx("div", { className: "px-2 py-3 text-sm text-muted-foreground", children: "No options found" })
|
|
335
|
+
] })
|
|
336
|
+
]
|
|
337
|
+
}
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
function multiOptionText(option) {
|
|
341
|
+
const label = typeof option.label === "string" ? option.label : "";
|
|
342
|
+
return [option.value, label, option.title ?? ""].filter(Boolean).join(" ");
|
|
343
|
+
}
|
|
344
|
+
function TimeRangeRow({ timeRange }) {
|
|
345
|
+
const fromId = "clicky-param-from";
|
|
346
|
+
const toId = "clicky-param-to";
|
|
347
|
+
const from = timeRange.from ?? "";
|
|
348
|
+
const to = timeRange.to ?? "";
|
|
349
|
+
return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-2 py-2 sm:grid-cols-[minmax(8rem,14rem)_minmax(0,1fr)] sm:items-center", children: [
|
|
350
|
+
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium text-muted-foreground", children: "Time range" }),
|
|
351
|
+
/* @__PURE__ */ jsxs("div", { className: "grid min-w-0 grid-cols-1 gap-2 sm:grid-cols-2", children: [
|
|
352
|
+
/* @__PURE__ */ jsxs("label", { className: "min-w-0", children: [
|
|
353
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "From" }),
|
|
354
|
+
/* @__PURE__ */ jsx(
|
|
355
|
+
"input",
|
|
356
|
+
{
|
|
357
|
+
id: fromId,
|
|
358
|
+
type: "text",
|
|
359
|
+
"aria-label": "From",
|
|
360
|
+
className: inputClassName,
|
|
361
|
+
placeholder: timeRange.fromPlaceholder ?? "From",
|
|
362
|
+
value: from,
|
|
363
|
+
onChange: (event) => timeRange.onApply(event.target.value, to)
|
|
364
|
+
}
|
|
365
|
+
)
|
|
366
|
+
] }),
|
|
367
|
+
/* @__PURE__ */ jsxs("label", { className: "min-w-0", children: [
|
|
368
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "To" }),
|
|
369
|
+
/* @__PURE__ */ jsx(
|
|
370
|
+
"input",
|
|
371
|
+
{
|
|
372
|
+
id: toId,
|
|
373
|
+
type: "text",
|
|
374
|
+
"aria-label": "To",
|
|
375
|
+
className: inputClassName,
|
|
376
|
+
placeholder: timeRange.toPlaceholder ?? "To",
|
|
377
|
+
value: to,
|
|
378
|
+
onChange: (event) => timeRange.onApply(from, event.target.value)
|
|
379
|
+
}
|
|
380
|
+
)
|
|
381
|
+
] })
|
|
382
|
+
] })
|
|
383
|
+
] });
|
|
384
|
+
}
|
|
385
|
+
function splitCommaValues(value) {
|
|
386
|
+
return value.split(",").map((item) => item.trim()).filter(Boolean);
|
|
387
|
+
}
|
|
388
|
+
const inputClassName = "h-8 w-full min-w-0 rounded-md border border-input bg-background px-2 text-sm text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:bg-muted/40 focus-visible:ring-2 focus-visible:ring-ring";
|
|
389
|
+
export {
|
|
390
|
+
FilterForm
|
|
391
|
+
};
|
|
392
|
+
//# sourceMappingURL=FilterForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FilterForm.js","sources":["../../src/rpc/FilterForm.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useState, type FormEvent } from \"react\";\nimport { useQuery } from \"@tanstack/react-query\";\nimport { Button } from \"../components/button\";\nimport type {\n FilterBarFilter,\n FilterBarMultiFilter,\n FilterBarRangeProps,\n} from \"../components/FilterBar\";\nimport { FilterPill, type FilterMode } from \"../data/FilterPill\";\nimport { Icon } from \"../data/Icon\";\nimport { cn } from \"../lib/utils\";\nimport {\n packParameterValues,\n parametersToFormConfig,\n pruneParameterValues,\n buildInitialParameterValues,\n titleCase,\n useDebouncedRecord,\n type ParameterValues,\n} from \"./formMetadata\";\nimport type { OpenAPIParameter } from \"./types\";\nimport type { OperationsApiClient } from \"./useOperations\";\n\nexport type FilterFormProps = {\n client: OperationsApiClient;\n path: string;\n method: string;\n parameters?: OpenAPIParameter[];\n initialValues?: ParameterValues | undefined;\n lockedValues?: ParameterValues | undefined;\n hideLocked?: boolean | undefined;\n enableLookup?: boolean | undefined;\n autoSubmit?: boolean | undefined;\n submitLabel?: string | undefined;\n submittingLabel?: string | undefined;\n emptyMessage?: string | undefined;\n isSubmitting?: boolean | undefined;\n className?: string | undefined;\n onSubmit: (values: ParameterValues) => void | Promise<void>;\n};\n\nexport function FilterForm({\n client,\n path,\n method,\n parameters = [],\n initialValues = {},\n lockedValues = {},\n hideLocked = false,\n enableLookup = method.toUpperCase() === \"GET\",\n autoSubmit = false,\n submitLabel = \"Execute request\",\n submittingLabel = \"Executing…\",\n emptyMessage = \"This operation does not require input.\",\n isSubmitting = false,\n className,\n onSubmit,\n}: FilterFormProps) {\n const resetKey = useMemo(\n () => `${method}:${path}:${JSON.stringify(initialValues)}:${JSON.stringify(lockedValues)}`,\n [initialValues, lockedValues, method, path],\n );\n const [values, setValues] = useState<ParameterValues>(() =>\n buildInitialParameterValues(parameters, method, lockedValues, initialValues),\n );\n const [error, setError] = useState(\"\");\n const debouncedValues = useDebouncedRecord(values, 250);\n const lastAutoSubmitted = useRef<string | null>(null);\n\n const lookupQuery = useQuery({\n queryKey: [\"filter-form-lookup\", method, path, debouncedValues],\n queryFn: async () =>\n (await client.lookupFilters?.(\n path,\n method,\n packParameterValues(debouncedValues, parameters),\n { Accept: \"application/json+clicky\" },\n )) ?? { filters: {} },\n enabled:\n enableLookup && !!client.lookupFilters && parameters.some((param) => param.in === \"query\"),\n staleTime: 30_000,\n retry: 0,\n });\n\n const formConfig = useMemo(\n () =>\n parametersToFormConfig(parameters, values, setValues, {\n lookup: lookupQuery.data,\n lockedValues,\n hideLocked,\n }),\n [hideLocked, lockedValues, lookupQuery.data, parameters, values],\n );\n\n const hasFields = formConfig.filters.length > 0 || formConfig.timeRange != null;\n\n async function handleSubmit(event?: FormEvent) {\n event?.preventDefault();\n\n const missingRequired = parameters.filter((param) => {\n if (!param.required) return false;\n const value = lockedValues[param.name] ?? values[param.name] ?? \"\";\n return value.trim() === \"\";\n });\n\n if (missingRequired.length > 0) {\n setError(\n `Missing required fields: ${missingRequired.map((param) => titleCase(param.name)).join(\", \")}`,\n );\n return;\n }\n\n setError(\"\");\n await onSubmit(pruneParameterValues(values));\n }\n\n useEffect(() => {\n setValues(buildInitialParameterValues(parameters, method, lockedValues, initialValues));\n setError(\"\");\n lastAutoSubmitted.current = null;\n }, [resetKey]);\n\n useEffect(() => {\n if (!autoSubmit) {\n return;\n }\n\n const missingRequired = parameters.filter((param) => {\n if (!param.required) return false;\n const value = lockedValues[param.name] ?? debouncedValues[param.name] ?? \"\";\n return value.trim() === \"\";\n });\n if (missingRequired.length > 0) {\n return;\n }\n\n const submittedValues = pruneParameterValues(debouncedValues);\n const signature = JSON.stringify(submittedValues);\n if (lastAutoSubmitted.current === signature) {\n return;\n }\n\n lastAutoSubmitted.current = signature;\n setError(\"\");\n void onSubmit(submittedValues);\n }, [autoSubmit, debouncedValues, lockedValues, onSubmit, parameters]);\n\n return (\n <form className=\"space-y-3\" onSubmit={handleSubmit}>\n {hasFields ? (\n <ParameterGrid\n autoSubmit={autoSubmit}\n filters={formConfig.filters}\n isSubmitting={isSubmitting}\n submitLabel={submitLabel}\n submittingLabel={submittingLabel}\n {...(formConfig.timeRange ? { timeRange: formConfig.timeRange } : {})}\n {...(className ? { className } : {})}\n />\n ) : (\n <div className=\"flex items-center justify-between gap-4\">\n <p className=\"text-sm text-muted-foreground\">{emptyMessage}</p>\n <Button type=\"button\" onClick={handleSubmit} disabled={isSubmitting}>\n {isSubmitting ? submittingLabel : submitLabel}\n </Button>\n </div>\n )}\n\n {error && (\n <div className=\"rounded-md border border-destructive/40 bg-destructive/5 p-3 text-sm text-destructive\">\n {error}\n </div>\n )}\n </form>\n );\n}\n\ntype ParameterGridProps = {\n filters: FilterBarFilter[];\n timeRange?: FilterBarRangeProps | undefined;\n autoSubmit: boolean;\n isSubmitting: boolean;\n submitLabel: string;\n submittingLabel: string;\n className?: string | undefined;\n};\n\nfunction ParameterGrid({\n filters,\n timeRange,\n autoSubmit,\n isSubmitting,\n submitLabel,\n submittingLabel,\n className,\n}: ParameterGridProps) {\n return (\n <div className={cn(\"space-y-3\", className)}>\n <div className=\"divide-y divide-border border-y border-border\">\n {filters.map((filter) => (\n <ParameterRow key={filter.key} filter={filter} />\n ))}\n {timeRange && <TimeRangeRow timeRange={timeRange} />}\n </div>\n\n {!autoSubmit && (\n <div className=\"flex justify-end\">\n <Button type=\"submit\" disabled={isSubmitting}>\n {isSubmitting ? submittingLabel : submitLabel}\n </Button>\n </div>\n )}\n </div>\n );\n}\n\nfunction ParameterRow({ filter }: { filter: FilterBarFilter }) {\n const id = `clicky-param-${filter.key.replace(/[^a-zA-Z0-9_-]/g, \"-\")}`;\n\n return (\n <div\n title={filter.description}\n className={cn(\n \"grid grid-cols-1 gap-2 py-2 sm:grid-cols-[minmax(8rem,14rem)_minmax(0,1fr)] sm:items-center\",\n filter.disabled && \"opacity-60\",\n )}\n >\n <label htmlFor={id} className=\"text-sm font-medium text-muted-foreground\">\n {filter.label}\n </label>\n <div className=\"min-w-0\">{renderParameterInput(filter, id)}</div>\n </div>\n );\n}\n\nfunction renderParameterInput(filter: FilterBarFilter, id: string) {\n if (filter.kind === \"enum\") {\n return (\n <select\n id={id}\n aria-label={filter.label}\n className={inputClassName}\n value={filter.value}\n disabled={filter.disabled}\n onChange={(event) => filter.onChange(event.target.value)}\n >\n <option value=\"\">{filter.placeholder ?? `Any ${filter.label.toLowerCase()}`}</option>\n {filter.options.map((option) => (\n <option key={option.value} value={option.value}>\n {option.label ?? option.value}\n </option>\n ))}\n </select>\n );\n }\n\n if (filter.kind === \"boolean\") {\n return (\n <div className=\"flex h-8 items-center\">\n <input\n id={id}\n type=\"checkbox\"\n aria-label={filter.label}\n className=\"h-4 w-4 accent-primary disabled:cursor-not-allowed\"\n checked={filter.value}\n disabled={filter.disabled}\n onChange={(event) => filter.onChange(event.target.checked)}\n />\n </div>\n );\n }\n\n if (filter.kind === \"lookup\") {\n const listId = `${id}-options`;\n return (\n <>\n <input\n id={id}\n type={filter.inputType === \"number\" ? \"number\" : \"text\"}\n aria-label={filter.label}\n className={inputClassName}\n placeholder={filter.placeholder ?? \"Value\"}\n value={filter.value}\n list={listId}\n disabled={filter.disabled}\n onChange={(event) => filter.onChange(event.target.value)}\n />\n <datalist id={listId}>\n {filter.options.map((option) => (\n <option\n key={option.value}\n value={option.value}\n label={option.label ?? option.value}\n disabled={option.disabled}\n />\n ))}\n </datalist>\n </>\n );\n }\n\n if (filter.kind === \"lookup-multi\") {\n const listId = `${id}-options`;\n return (\n <>\n <input\n id={id}\n type=\"text\"\n aria-label={filter.label}\n className={inputClassName}\n placeholder={filter.placeholder ?? \"value-1, value-2\"}\n value={filter.value.join(\", \")}\n list={listId}\n disabled={filter.disabled}\n onChange={(event) => filter.onChange(splitCommaValues(event.target.value))}\n />\n <datalist id={listId}>\n {filter.options.map((option) => (\n <option\n key={option.value}\n value={option.value}\n label={option.label ?? option.value}\n disabled={option.disabled}\n />\n ))}\n </datalist>\n </>\n );\n }\n\n if (filter.kind === \"multi\") {\n return <MultiParameterInput filter={filter} id={id} />;\n }\n\n if (filter.kind === \"text\") {\n return (\n <input\n id={id}\n type=\"text\"\n aria-label={filter.label}\n className={inputClassName}\n placeholder={filter.placeholder ?? \"Value\"}\n value={filter.value}\n disabled={filter.disabled}\n onChange={(event) => filter.onChange(event.target.value)}\n />\n );\n }\n\n return (\n <input\n id={id}\n type=\"text\"\n aria-label={filter.label}\n className={inputClassName}\n value={JSON.stringify(filter.value)}\n disabled\n readOnly\n />\n );\n}\n\nfunction MultiParameterInput({ filter, id }: { filter: FilterBarMultiFilter; id: string }) {\n const [query, setQuery] = useState(\"\");\n const showOptionFilter = filter.options.length > 7;\n const visibleOptions = useMemo(() => {\n const normalized = query.trim().toLowerCase();\n if (!normalized) return filter.options;\n return filter.options.filter((option) =>\n multiOptionText(option).toLowerCase().includes(normalized),\n );\n }, [filter.options, query]);\n\n const setMode = (value: string, mode: FilterMode) => {\n if (filter.disabled) return;\n const next = { ...filter.value };\n if (mode === \"include\" || mode === \"exclude\") {\n next[value] = mode;\n } else {\n delete next[value];\n }\n filter.onChange(next);\n };\n\n return (\n <div\n id={id}\n role=\"group\"\n aria-label={filter.label}\n className=\"rounded-md border border-input bg-background p-2\"\n >\n {showOptionFilter && (\n <label className=\"mb-2 flex items-center gap-2 rounded-md border border-input bg-background px-2\">\n <Icon name=\"codicon:search\" className=\"shrink-0 text-muted-foreground\" />\n <input\n type=\"search\"\n aria-label={`Filter ${filter.label} options`}\n className=\"h-8 min-w-0 flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground\"\n placeholder={`Filter ${filter.label.toLowerCase()}`}\n value={query}\n disabled={filter.disabled}\n onChange={(event) => setQuery(event.target.value)}\n />\n </label>\n )}\n\n <div className=\"max-h-56 space-y-1 overflow-auto\">\n {visibleOptions.map((option) => {\n const mode: FilterMode = filter.value[option.value] ?? \"neutral\";\n return (\n <FilterPill\n key={option.value}\n className=\"w-full justify-between\"\n label={option.label}\n mode={mode}\n title={option.title ?? multiOptionText(option)}\n togglePosition=\"right\"\n onModeChange={(next) => setMode(option.value, next)}\n />\n );\n })}\n {visibleOptions.length === 0 && (\n <div className=\"px-2 py-3 text-sm text-muted-foreground\">No options found</div>\n )}\n </div>\n </div>\n );\n}\n\nfunction multiOptionText(option: FilterBarMultiFilter[\"options\"][number]) {\n const label = typeof option.label === \"string\" ? option.label : \"\";\n return [option.value, label, option.title ?? \"\"].filter(Boolean).join(\" \");\n}\n\nfunction TimeRangeRow({ timeRange }: { timeRange: FilterBarRangeProps }) {\n const fromId = \"clicky-param-from\";\n const toId = \"clicky-param-to\";\n const from = timeRange.from ?? \"\";\n const to = timeRange.to ?? \"\";\n\n return (\n <div className=\"grid grid-cols-1 gap-2 py-2 sm:grid-cols-[minmax(8rem,14rem)_minmax(0,1fr)] sm:items-center\">\n <div className=\"text-sm font-medium text-muted-foreground\">Time range</div>\n <div className=\"grid min-w-0 grid-cols-1 gap-2 sm:grid-cols-2\">\n <label className=\"min-w-0\">\n <span className=\"sr-only\">From</span>\n <input\n id={fromId}\n type=\"text\"\n aria-label=\"From\"\n className={inputClassName}\n placeholder={timeRange.fromPlaceholder ?? \"From\"}\n value={from}\n onChange={(event) => timeRange.onApply(event.target.value, to)}\n />\n </label>\n <label className=\"min-w-0\">\n <span className=\"sr-only\">To</span>\n <input\n id={toId}\n type=\"text\"\n aria-label=\"To\"\n className={inputClassName}\n placeholder={timeRange.toPlaceholder ?? \"To\"}\n value={to}\n onChange={(event) => timeRange.onApply(from, event.target.value)}\n />\n </label>\n </div>\n </div>\n );\n}\n\nfunction splitCommaValues(value: string) {\n return value\n .split(\",\")\n .map((item) => item.trim())\n .filter(Boolean);\n}\n\nconst inputClassName =\n \"h-8 w-full min-w-0 rounded-md border border-input bg-background px-2 text-sm text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:bg-muted/40 focus-visible:ring-2 focus-visible:ring-ring\";\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InlineError.d.ts","sourceRoot":"","sources":["../../src/rpc/InlineError.tsx"],"names":[],"mappings":"AAGA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AASF,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,gBAAgB,2CAsCxE"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Icon } from "../data/Icon.js";
|
|
3
|
+
import { cn } from "../lib/utils.js";
|
|
4
|
+
function InlineError({ title, error, className }) {
|
|
5
|
+
const message = error instanceof Error ? error.message : String(error ?? "");
|
|
6
|
+
const details = getErrorDetails(error);
|
|
7
|
+
const hasDetails = Boolean(details.responseBody || details.status || details.url);
|
|
8
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("rounded-xl border border-dashed border-red-300 p-6 text-sm", className), children: [
|
|
9
|
+
/* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
10
|
+
/* @__PURE__ */ jsx("div", { className: "font-medium text-red-600", children: title }),
|
|
11
|
+
message && /* @__PURE__ */ jsx("div", { className: "mt-1 text-muted-foreground", children: message })
|
|
12
|
+
] }),
|
|
13
|
+
hasDetails && /* @__PURE__ */ jsxs("details", { className: "group mt-3", children: [
|
|
14
|
+
/* @__PURE__ */ jsxs("summary", { className: "flex cursor-pointer items-center justify-center gap-1 text-xs text-muted-foreground hover:text-foreground", children: [
|
|
15
|
+
/* @__PURE__ */ jsx(
|
|
16
|
+
Icon,
|
|
17
|
+
{
|
|
18
|
+
name: "codicon:chevron-right",
|
|
19
|
+
className: "transition-transform group-open:rotate-90"
|
|
20
|
+
}
|
|
21
|
+
),
|
|
22
|
+
"More details"
|
|
23
|
+
] }),
|
|
24
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-2 space-y-2 text-left font-mono text-xs", children: [
|
|
25
|
+
(details.method || details.url || details.status) && /* @__PURE__ */ jsxs("div", { className: "text-muted-foreground", children: [
|
|
26
|
+
details.method && /* @__PURE__ */ jsxs("span", { children: [
|
|
27
|
+
details.method,
|
|
28
|
+
" "
|
|
29
|
+
] }),
|
|
30
|
+
details.url,
|
|
31
|
+
details.status != null && /* @__PURE__ */ jsxs("span", { children: [
|
|
32
|
+
" - ",
|
|
33
|
+
details.status
|
|
34
|
+
] })
|
|
35
|
+
] }),
|
|
36
|
+
details.responseBody && /* @__PURE__ */ jsx("pre", { className: "max-h-64 overflow-auto rounded-md bg-muted p-2 text-xs", children: details.responseBody })
|
|
37
|
+
] })
|
|
38
|
+
] })
|
|
39
|
+
] });
|
|
40
|
+
}
|
|
41
|
+
function getErrorDetails(error) {
|
|
42
|
+
if (error == null || typeof error !== "object") return {};
|
|
43
|
+
const record = error;
|
|
44
|
+
const details = {};
|
|
45
|
+
if (typeof record.method === "string") details.method = record.method;
|
|
46
|
+
if (typeof record.url === "string") details.url = record.url;
|
|
47
|
+
if (typeof record.status === "number") details.status = record.status;
|
|
48
|
+
if (typeof record.responseBody === "string") details.responseBody = record.responseBody;
|
|
49
|
+
return details;
|
|
50
|
+
}
|
|
51
|
+
export {
|
|
52
|
+
InlineError
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=InlineError.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"InlineError.js","sources":["../../src/rpc/InlineError.tsx"],"sourcesContent":["import { Icon } from \"../data/Icon\";\nimport { cn } from \"../lib/utils\";\n\nexport type InlineErrorProps = {\n title: string;\n error: unknown;\n className?: string;\n};\n\ntype ErrorDetails = {\n method?: string;\n url?: string;\n status?: number;\n responseBody?: string;\n};\n\nexport function InlineError({ title, error, className }: InlineErrorProps) {\n const message = error instanceof Error ? error.message : String(error ?? \"\");\n const details = getErrorDetails(error);\n const hasDetails = Boolean(details.responseBody || details.status || details.url);\n\n return (\n <div className={cn(\"rounded-xl border border-dashed border-red-300 p-6 text-sm\", className)}>\n <div className=\"text-center\">\n <div className=\"font-medium text-red-600\">{title}</div>\n {message && <div className=\"mt-1 text-muted-foreground\">{message}</div>}\n </div>\n {hasDetails && (\n <details className=\"group mt-3\">\n <summary className=\"flex cursor-pointer items-center justify-center gap-1 text-xs text-muted-foreground hover:text-foreground\">\n <Icon\n name=\"codicon:chevron-right\"\n className=\"transition-transform group-open:rotate-90\"\n />\n More details\n </summary>\n <div className=\"mt-2 space-y-2 text-left font-mono text-xs\">\n {(details.method || details.url || details.status) && (\n <div className=\"text-muted-foreground\">\n {details.method && <span>{details.method} </span>}\n {details.url}\n {details.status != null && <span> - {details.status}</span>}\n </div>\n )}\n {details.responseBody && (\n <pre className=\"max-h-64 overflow-auto rounded-md bg-muted p-2 text-xs\">\n {details.responseBody}\n </pre>\n )}\n </div>\n </details>\n )}\n </div>\n );\n}\n\nfunction getErrorDetails(error: unknown): ErrorDetails {\n if (error == null || typeof error !== \"object\") return {};\n const record = error as Record<string, unknown>;\n const details: ErrorDetails = {};\n if (typeof record.method === \"string\") details.method = record.method;\n if (typeof record.url === \"string\") details.url = record.url;\n if (typeof record.status === \"number\") details.status = record.status;\n if (typeof record.responseBody === \"string\") details.responseBody = record.responseBody;\n return details;\n}\n"],"names":[],"mappings":";;;AAgBO,SAAS,YAAY,EAAE,OAAO,OAAO,aAA+B;AACzE,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,SAAS,EAAE;AAC3E,QAAM,UAAU,gBAAgB,KAAK;AACrC,QAAM,aAAa,QAAQ,QAAQ,gBAAgB,QAAQ,UAAU,QAAQ,GAAG;AAEhF,8BACG,OAAA,EAAI,WAAW,GAAG,8DAA8D,SAAS,GACxF,UAAA;AAAA,IAAA,qBAAC,OAAA,EAAI,WAAU,eACb,UAAA;AAAA,MAAA,oBAAC,OAAA,EAAI,WAAU,4BAA4B,UAAA,OAAM;AAAA,MAChD,WAAW,oBAAC,OAAA,EAAI,WAAU,8BAA8B,UAAA,QAAA,CAAQ;AAAA,IAAA,GACnE;AAAA,IACC,cACC,qBAAC,WAAA,EAAQ,WAAU,cACjB,UAAA;AAAA,MAAA,qBAAC,WAAA,EAAQ,WAAU,6GACjB,UAAA;AAAA,QAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,UAAA;AAAA,QAAA;AAAA,QACV;AAAA,MAAA,GAEJ;AAAA,MACA,qBAAC,OAAA,EAAI,WAAU,8CACX,UAAA;AAAA,SAAA,QAAQ,UAAU,QAAQ,OAAO,QAAQ,WACzC,qBAAC,OAAA,EAAI,WAAU,yBACZ,UAAA;AAAA,UAAA,QAAQ,+BAAW,QAAA,EAAM,UAAA;AAAA,YAAA,QAAQ;AAAA,YAAO;AAAA,UAAA,GAAC;AAAA,UACzC,QAAQ;AAAA,UACR,QAAQ,UAAU,QAAQ,qBAAC,QAAA,EAAK,UAAA;AAAA,YAAA;AAAA,YAAI,QAAQ;AAAA,UAAA,EAAA,CAAO;AAAA,QAAA,GACtD;AAAA,QAED,QAAQ,gBACP,oBAAC,SAAI,WAAU,0DACZ,kBAAQ,aAAA,CACX;AAAA,MAAA,EAAA,CAEJ;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,GAEJ;AAEJ;AAEA,SAAS,gBAAgB,OAA8B;AACrD,MAAI,SAAS,QAAQ,OAAO,UAAU,iBAAiB,CAAA;AACvD,QAAM,SAAS;AACf,QAAM,UAAwB,CAAA;AAC9B,MAAI,OAAO,OAAO,WAAW,SAAU,SAAQ,SAAS,OAAO;AAC/D,MAAI,OAAO,OAAO,QAAQ,SAAU,SAAQ,MAAM,OAAO;AACzD,MAAI,OAAO,OAAO,WAAW,SAAU,SAAQ,SAAS,OAAO;AAC/D,MAAI,OAAO,OAAO,iBAAiB,SAAU,SAAQ,eAAe,OAAO;AAC3E,SAAO;AACT;"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ResolvedOperation } from './types';
|
|
2
|
+
import { OperationsApiClient } from './useOperations';
|
|
3
|
+
export type OperationActionDialogProps = {
|
|
4
|
+
operation: ResolvedOperation;
|
|
5
|
+
client: OperationsApiClient;
|
|
6
|
+
initialValues: Record<string, string>;
|
|
7
|
+
label: string;
|
|
8
|
+
defaultAccept?: string;
|
|
9
|
+
onNavigateAction?: (href: string) => void;
|
|
10
|
+
};
|
|
11
|
+
export declare function OperationActionDialog({ operation, client, initialValues, label, defaultAccept, onNavigateAction, }: OperationActionDialogProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
//# sourceMappingURL=OperationActionDialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OperationActionDialog.d.ts","sourceRoot":"","sources":["../../src/rpc/OperationActionDialog.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAqB,iBAAiB,EAAE,MAAM,SAAS,CAAC;AACpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,MAAM,MAAM,0BAA0B,GAAG;IACvC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,MAAM,EAAE,mBAAmB,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC3C,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,MAAM,EACN,aAAa,EACb,KAAK,EACL,aAAyC,EACzC,gBAAgB,GACjB,EAAE,0BAA0B,2CAuD5B"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { jsxs, Fragment, jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Button } from "../components/button.js";
|
|
4
|
+
import { Icon } from "../data/Icon.js";
|
|
5
|
+
import { Modal } from "../overlay/Modal.js";
|
|
6
|
+
import { CommandForm } from "./CommandForm.js";
|
|
7
|
+
import { CommandOutput } from "./CommandOutput.js";
|
|
8
|
+
import { InlineError } from "./InlineError.js";
|
|
9
|
+
function OperationActionDialog({
|
|
10
|
+
operation,
|
|
11
|
+
client,
|
|
12
|
+
initialValues,
|
|
13
|
+
label,
|
|
14
|
+
defaultAccept = "application/clicky+json",
|
|
15
|
+
onNavigateAction
|
|
16
|
+
}) {
|
|
17
|
+
const [open, setOpen] = useState(false);
|
|
18
|
+
const [isExecuting, setIsExecuting] = useState(false);
|
|
19
|
+
const [response, setResponse] = useState(null);
|
|
20
|
+
const [error, setError] = useState(null);
|
|
21
|
+
async function handleExecute(params, headers) {
|
|
22
|
+
if (onNavigateAction) {
|
|
23
|
+
const href = hrefForOperationAction(operation.path, params);
|
|
24
|
+
if (!href) return;
|
|
25
|
+
const separator = href.includes("?") ? "&" : "?";
|
|
26
|
+
onNavigateAction(`${href}${separator}autoRun=1`);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
setIsExecuting(true);
|
|
30
|
+
setError(null);
|
|
31
|
+
setResponse(null);
|
|
32
|
+
try {
|
|
33
|
+
const result = await client.executeCommand(operation.path, operation.method, params, headers);
|
|
34
|
+
setResponse(result);
|
|
35
|
+
} catch (err) {
|
|
36
|
+
setError(err);
|
|
37
|
+
} finally {
|
|
38
|
+
setIsExecuting(false);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
42
|
+
/* @__PURE__ */ jsxs(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setOpen(true), children: [
|
|
43
|
+
/* @__PURE__ */ jsx(Icon, { name: "codicon:play" }),
|
|
44
|
+
label
|
|
45
|
+
] }),
|
|
46
|
+
/* @__PURE__ */ jsx(Modal, { open, onClose: () => setOpen(false), title: label, size: "lg", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
47
|
+
/* @__PURE__ */ jsx(
|
|
48
|
+
CommandForm,
|
|
49
|
+
{
|
|
50
|
+
parameters: operation.operation.parameters ?? [],
|
|
51
|
+
onExecute: handleExecute,
|
|
52
|
+
isPending: isExecuting,
|
|
53
|
+
method: operation.method,
|
|
54
|
+
path: operation.path,
|
|
55
|
+
accept: defaultAccept,
|
|
56
|
+
initialValues
|
|
57
|
+
}
|
|
58
|
+
),
|
|
59
|
+
error ? /* @__PURE__ */ jsx(InlineError, { title: `Failed to execute ${operation.path}`, error }) : response ? /* @__PURE__ */ jsx(CommandOutput, { response }) : null
|
|
60
|
+
] }) })
|
|
61
|
+
] });
|
|
62
|
+
}
|
|
63
|
+
function hrefForOperationAction(path, params) {
|
|
64
|
+
const nextParams = { ...params };
|
|
65
|
+
const args = parseArgsParam(params.args);
|
|
66
|
+
let route = apiPathToRoutePath(path);
|
|
67
|
+
for (const [index, name] of pathParamNames(path).entries()) {
|
|
68
|
+
const value = nextParams[name] || args[index];
|
|
69
|
+
if (!value) return void 0;
|
|
70
|
+
route = route.replace(`:${name}`, encodeURIComponent(value));
|
|
71
|
+
delete nextParams[name];
|
|
72
|
+
if (!nextParams[name] && value === args[index]) {
|
|
73
|
+
delete nextParams.args;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const search = new URLSearchParams();
|
|
77
|
+
for (const [key, value] of Object.entries(nextParams)) {
|
|
78
|
+
if (value && key !== "autoRun") search.set(key, value);
|
|
79
|
+
}
|
|
80
|
+
const query = search.toString();
|
|
81
|
+
return query ? `${route}?${query}` : route;
|
|
82
|
+
}
|
|
83
|
+
function apiPathToRoutePath(path) {
|
|
84
|
+
const cliPath = path.trim().replace(/^\/api\/v1\/?/, "").replace(/^\/+/, "").replace(/\/+$/, "");
|
|
85
|
+
if (!cliPath) return "/";
|
|
86
|
+
return `/${cliPath.replace(/\{([^}]+)\}/g, ":$1")}`;
|
|
87
|
+
}
|
|
88
|
+
function pathParamNames(path) {
|
|
89
|
+
return [...path.matchAll(/\{([^}]+)\}/g)].map((match) => match[1]).filter((name) => Boolean(name));
|
|
90
|
+
}
|
|
91
|
+
function parseArgsParam(value) {
|
|
92
|
+
if (!value) return [];
|
|
93
|
+
const trimmed = value.trim();
|
|
94
|
+
if (!trimmed || trimmed === "[]" || trimmed.toLowerCase() === "null") return [];
|
|
95
|
+
try {
|
|
96
|
+
const parsed = JSON.parse(trimmed);
|
|
97
|
+
if (Array.isArray(parsed)) return parsed.map(String).filter(Boolean);
|
|
98
|
+
} catch {
|
|
99
|
+
}
|
|
100
|
+
return trimmed.split(",").map((part) => part.trim()).filter(Boolean);
|
|
101
|
+
}
|
|
102
|
+
export {
|
|
103
|
+
OperationActionDialog
|
|
104
|
+
};
|
|
105
|
+
//# sourceMappingURL=OperationActionDialog.js.map
|