@flanksource/clicky-ui 0.3.47 → 0.3.48

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.
Files changed (169) hide show
  1. package/README.md +49 -0
  2. package/dist/comments/CommentSidePanel.cjs +10 -4
  3. package/dist/comments/CommentSidePanel.cjs.map +1 -1
  4. package/dist/comments/CommentSidePanel.d.ts +2 -0
  5. package/dist/comments/CommentSidePanel.d.ts.map +1 -1
  6. package/dist/comments/CommentSidePanel.js +10 -4
  7. package/dist/comments/CommentSidePanel.js.map +1 -1
  8. package/dist/comments/CommentThread.cjs +2 -0
  9. package/dist/comments/CommentThread.cjs.map +1 -1
  10. package/dist/comments/CommentThread.d.ts +2 -1
  11. package/dist/comments/CommentThread.d.ts.map +1 -1
  12. package/dist/comments/CommentThread.js +2 -0
  13. package/dist/comments/CommentThread.js.map +1 -1
  14. package/dist/comments/CommentThreadList.cjs +3 -0
  15. package/dist/comments/CommentThreadList.cjs.map +1 -1
  16. package/dist/comments/CommentThreadList.d.ts +3 -1
  17. package/dist/comments/CommentThreadList.d.ts.map +1 -1
  18. package/dist/comments/CommentThreadList.js +3 -0
  19. package/dist/comments/CommentThreadList.js.map +1 -1
  20. package/dist/data/CodeLine.cjs +4 -2
  21. package/dist/data/CodeLine.cjs.map +1 -1
  22. package/dist/data/CodeLine.d.ts.map +1 -1
  23. package/dist/data/CodeLine.js +4 -2
  24. package/dist/data/CodeLine.js.map +1 -1
  25. package/dist/data/SymbolBadge.cjs +61 -0
  26. package/dist/data/SymbolBadge.cjs.map +1 -0
  27. package/dist/data/SymbolBadge.d.ts +21 -0
  28. package/dist/data/SymbolBadge.d.ts.map +1 -0
  29. package/dist/data/SymbolBadge.js +61 -0
  30. package/dist/data/SymbolBadge.js.map +1 -0
  31. package/dist/data/test-runner/TestDetailPanel.cjs +26 -12
  32. package/dist/data/test-runner/TestDetailPanel.cjs.map +1 -1
  33. package/dist/data/test-runner/TestDetailPanel.d.ts.map +1 -1
  34. package/dist/data/test-runner/TestDetailPanel.js +27 -13
  35. package/dist/data/test-runner/TestDetailPanel.js.map +1 -1
  36. package/dist/data/test-runner/TestRunner.cjs +6 -0
  37. package/dist/data/test-runner/TestRunner.cjs.map +1 -1
  38. package/dist/data/test-runner/TestRunner.d.ts +3 -1
  39. package/dist/data/test-runner/TestRunner.d.ts.map +1 -1
  40. package/dist/data/test-runner/TestRunner.js +6 -0
  41. package/dist/data/test-runner/TestRunner.js.map +1 -1
  42. package/dist/data/test-runner/TestTreeNode.cjs +2 -1
  43. package/dist/data/test-runner/TestTreeNode.cjs.map +1 -1
  44. package/dist/data/test-runner/TestTreeNode.d.ts.map +1 -1
  45. package/dist/data/test-runner/TestTreeNode.js +2 -1
  46. package/dist/data/test-runner/TestTreeNode.js.map +1 -1
  47. package/dist/data/test-runner/adapter.cjs +4 -0
  48. package/dist/data/test-runner/adapter.cjs.map +1 -1
  49. package/dist/data/test-runner/adapter.d.ts +9 -0
  50. package/dist/data/test-runner/adapter.d.ts.map +1 -1
  51. package/dist/data/test-runner/adapter.js +4 -0
  52. package/dist/data/test-runner/adapter.js.map +1 -1
  53. package/dist/data/test-runner/context.cjs.map +1 -1
  54. package/dist/data/test-runner/context.d.ts +2 -0
  55. package/dist/data/test-runner/context.d.ts.map +1 -1
  56. package/dist/data/test-runner/context.js.map +1 -1
  57. package/dist/data/test-runner/index.d.ts +2 -2
  58. package/dist/data/test-runner/index.d.ts.map +1 -1
  59. package/dist/data/test-runner/marks.cjs +42 -1
  60. package/dist/data/test-runner/marks.cjs.map +1 -1
  61. package/dist/data/test-runner/marks.d.ts +10 -0
  62. package/dist/data/test-runner/marks.d.ts.map +1 -1
  63. package/dist/data/test-runner/marks.js +42 -1
  64. package/dist/data/test-runner/marks.js.map +1 -1
  65. package/dist/data/traces/TerminalCastPlayer.d.ts +21 -0
  66. package/dist/data/traces/TerminalCastPlayer.d.ts.map +1 -0
  67. package/dist/data/traces/TraceHarView.d.ts +13 -0
  68. package/dist/data/traces/TraceHarView.d.ts.map +1 -0
  69. package/dist/data/traces/cast.d.ts +9 -0
  70. package/dist/data/traces/cast.d.ts.map +1 -0
  71. package/dist/data/traces/fixtures.d.ts +8 -0
  72. package/dist/data/traces/fixtures.d.ts.map +1 -0
  73. package/dist/data/traces/har-adapter.d.ts +13 -0
  74. package/dist/data/traces/har-adapter.d.ts.map +1 -0
  75. package/dist/data/traces/terminal-screen.d.ts +45 -0
  76. package/dist/data/traces/terminal-screen.d.ts.map +1 -0
  77. package/dist/data/traces/terminal-timeline.d.ts +26 -0
  78. package/dist/data/traces/terminal-timeline.d.ts.map +1 -0
  79. package/dist/data/traces/types.d.ts +141 -0
  80. package/dist/data/traces/types.d.ts.map +1 -0
  81. package/dist/data/verification/VerificationResults.cjs +4 -0
  82. package/dist/data/verification/VerificationResults.cjs.map +1 -1
  83. package/dist/data/verification/VerificationResults.d.ts +3 -1
  84. package/dist/data/verification/VerificationResults.d.ts.map +1 -1
  85. package/dist/data/verification/VerificationResults.js +4 -0
  86. package/dist/data/verification/VerificationResults.js.map +1 -1
  87. package/dist/data/verification/adapterViews.cjs +12 -3
  88. package/dist/data/verification/adapterViews.cjs.map +1 -1
  89. package/dist/data/verification/adapterViews.d.ts +4 -1
  90. package/dist/data/verification/adapterViews.d.ts.map +1 -1
  91. package/dist/data/verification/adapterViews.js +12 -3
  92. package/dist/data/verification/adapterViews.js.map +1 -1
  93. package/dist/data/verification/adapters.cjs +53 -10
  94. package/dist/data/verification/adapters.cjs.map +1 -1
  95. package/dist/data/verification/adapters.d.ts +7 -1
  96. package/dist/data/verification/adapters.d.ts.map +1 -1
  97. package/dist/data/verification/adapters.js +53 -10
  98. package/dist/data/verification/adapters.js.map +1 -1
  99. package/dist/data/verification/index.d.ts +4 -2
  100. package/dist/data/verification/index.d.ts.map +1 -1
  101. package/dist/data/verification/stepKind.cjs +217 -0
  102. package/dist/data/verification/stepKind.cjs.map +1 -0
  103. package/dist/data/verification/stepKind.d.ts +87 -0
  104. package/dist/data/verification/stepKind.d.ts.map +1 -0
  105. package/dist/data/verification/stepKind.js +217 -0
  106. package/dist/data/verification/stepKind.js.map +1 -0
  107. package/dist/data/verification/stepKindViews.cjs +111 -0
  108. package/dist/data/verification/stepKindViews.cjs.map +1 -0
  109. package/dist/data/verification/stepKindViews.d.ts +18 -0
  110. package/dist/data/verification/stepKindViews.d.ts.map +1 -0
  111. package/dist/data/verification/stepKindViews.js +111 -0
  112. package/dist/data/verification/stepKindViews.js.map +1 -0
  113. package/dist/data/verification/verifyReportTests.cjs +1 -0
  114. package/dist/data/verification/verifyReportTests.cjs.map +1 -1
  115. package/dist/data/verification/verifyReportTests.d.ts +2 -1
  116. package/dist/data/verification/verifyReportTests.d.ts.map +1 -1
  117. package/dist/data/verification/verifyReportTests.js +1 -0
  118. package/dist/data/verification/verifyReportTests.js.map +1 -1
  119. package/dist/data/version-info.cjs +3 -3
  120. package/dist/data/version-info.js +3 -3
  121. package/dist/data.cjs +14 -0
  122. package/dist/data.cjs.map +1 -1
  123. package/dist/data.d.ts +1 -0
  124. package/dist/data.d.ts.map +1 -1
  125. package/dist/data.js +16 -2
  126. package/dist/data.js.map +1 -1
  127. package/dist/index.cjs +16 -0
  128. package/dist/index.cjs.map +1 -1
  129. package/dist/index.js +18 -2
  130. package/dist/index.js.map +1 -1
  131. package/dist/rpc/FilterForm.cjs +9 -0
  132. package/dist/rpc/FilterForm.cjs.map +1 -1
  133. package/dist/rpc/FilterForm.d.ts +5 -1
  134. package/dist/rpc/FilterForm.d.ts.map +1 -1
  135. package/dist/rpc/FilterForm.js +9 -0
  136. package/dist/rpc/FilterForm.js.map +1 -1
  137. package/dist/rpc/OperationArgsForm.cjs +153 -0
  138. package/dist/rpc/OperationArgsForm.cjs.map +1 -0
  139. package/dist/rpc/OperationArgsForm.d.ts +16 -0
  140. package/dist/rpc/OperationArgsForm.d.ts.map +1 -0
  141. package/dist/rpc/OperationArgsForm.js +153 -0
  142. package/dist/rpc/OperationArgsForm.js.map +1 -0
  143. package/dist/rpc/OperationScheduleDialog.cjs +61 -17
  144. package/dist/rpc/OperationScheduleDialog.cjs.map +1 -1
  145. package/dist/rpc/OperationScheduleDialog.d.ts +3 -0
  146. package/dist/rpc/OperationScheduleDialog.d.ts.map +1 -1
  147. package/dist/rpc/OperationScheduleDialog.js +62 -18
  148. package/dist/rpc/OperationScheduleDialog.js.map +1 -1
  149. package/dist/rpc/OperationSchedules.cjs +6 -1
  150. package/dist/rpc/OperationSchedules.cjs.map +1 -1
  151. package/dist/rpc/OperationSchedules.d.ts.map +1 -1
  152. package/dist/rpc/OperationSchedules.js +6 -1
  153. package/dist/rpc/OperationSchedules.js.map +1 -1
  154. package/dist/rpc/operation-schedule-model.cjs +0 -7
  155. package/dist/rpc/operation-schedule-model.cjs.map +1 -1
  156. package/dist/rpc/operation-schedule-model.d.ts +0 -2
  157. package/dist/rpc/operation-schedule-model.d.ts.map +1 -1
  158. package/dist/rpc/operation-schedule-model.js +0 -7
  159. package/dist/rpc/operation-schedule-model.js.map +1 -1
  160. package/dist/rpc/operation-schedule-types.d.ts +6 -1
  161. package/dist/rpc/operation-schedule-types.d.ts.map +1 -1
  162. package/dist/rpc.cjs +2 -0
  163. package/dist/rpc.cjs.map +1 -1
  164. package/dist/rpc.d.ts +1 -0
  165. package/dist/rpc.d.ts.map +1 -1
  166. package/dist/rpc.js +2 -0
  167. package/dist/rpc.js.map +1 -1
  168. package/dist/styles.css +1 -1
  169. package/package.json +1 -1
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const jsxRuntime = require("react/jsx-runtime");
4
+ const react = require("react");
5
+ const FilterForm = require("./FilterForm.cjs");
6
+ const clickyMetadata = require("./clickyMetadata.cjs");
7
+ const formMetadata = require("./formMetadata.cjs");
8
+ const NO_PARAMETERS = [];
9
+ function OperationArgsForm({
10
+ client,
11
+ operation,
12
+ args,
13
+ onChange,
14
+ onValidityChange,
15
+ className
16
+ }) {
17
+ var _a;
18
+ const parameters = operation.operation.parameters ?? NO_PARAMETERS;
19
+ const [initial] = react.useState(
20
+ () => storedArgsToValues(args, parameters, operation.method)
21
+ );
22
+ const [values, setValues] = react.useState(initial.values);
23
+ const problems = react.useMemo(
24
+ () => parameterProblems(parameters, values),
25
+ [parameters, values]
26
+ );
27
+ const valid = problems.length === 0;
28
+ react.useEffect(() => {
29
+ onValidityChange == null ? void 0 : onValidityChange(valid);
30
+ }, [onValidityChange, valid]);
31
+ const handleChange = (next) => {
32
+ setValues(next);
33
+ onChange(
34
+ valuesToArgs({
35
+ parameters,
36
+ method: operation.method,
37
+ values: next,
38
+ stored: initial.names
39
+ })
40
+ );
41
+ };
42
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
43
+ /* @__PURE__ */ jsxRuntime.jsx(
44
+ FilterForm.FilterForm,
45
+ {
46
+ client,
47
+ path: operation.path,
48
+ method: operation.method,
49
+ parameters,
50
+ initialValues: initial.values,
51
+ enableLookup: Boolean((_a = clickyMetadata.getOperationClickyMeta(operation)) == null ? void 0 : _a.supportsLookup),
52
+ showSubmit: false,
53
+ onChange: handleChange,
54
+ onSubmit: () => void 0,
55
+ ...className ? { className } : {}
56
+ }
57
+ ),
58
+ initial.dropped.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground", children: [
59
+ "Dropped arguments this operation no longer accepts:",
60
+ " ",
61
+ initial.dropped.join(", ")
62
+ ] }) : null,
63
+ problems.map((problem) => /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: problem }, problem))
64
+ ] });
65
+ }
66
+ function storedArgsToValues(args, parameters, method) {
67
+ const known = new Set(parameters.map((parameter) => parameter.name));
68
+ const stored = {};
69
+ const dropped = [];
70
+ for (const [name, value] of Object.entries(args)) {
71
+ if (!known.has(name)) {
72
+ dropped.push(name);
73
+ continue;
74
+ }
75
+ stored[name] = storedValueToString(name, value);
76
+ }
77
+ return {
78
+ values: formMetadata.buildInitialParameterValues(parameters, method, {}, stored),
79
+ names: new Set(Object.keys(stored)),
80
+ dropped
81
+ };
82
+ }
83
+ function storedValueToString(name, value) {
84
+ if (Array.isArray(value)) return value.map(String).join(",");
85
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
86
+ return String(value);
87
+ }
88
+ throw new Error(
89
+ `Stored argument ${name} has an unsupported value: ${JSON.stringify(value)}`
90
+ );
91
+ }
92
+ function valuesToArgs({
93
+ parameters,
94
+ method,
95
+ values,
96
+ stored
97
+ }) {
98
+ const args = {};
99
+ for (const parameter of parameters) {
100
+ const raw = values[parameter.name] ?? "";
101
+ if (raw.trim() === "") continue;
102
+ const isDefault = raw === effectiveDefault(parameter, method);
103
+ if (isDefault && !parameter.required && !stored.has(parameter.name)) continue;
104
+ args[parameter.name] = typedValue(parameter, raw);
105
+ }
106
+ return args;
107
+ }
108
+ function effectiveDefault(parameter, method) {
109
+ var _a;
110
+ const value = formMetadata.defaultValueForParameter(parameter, method);
111
+ return ((_a = parameter.schema) == null ? void 0 : _a.type) === "boolean" && value === "" ? "false" : value;
112
+ }
113
+ function typedValue(parameter, raw) {
114
+ var _a;
115
+ switch ((_a = parameter.schema) == null ? void 0 : _a.type) {
116
+ case "boolean":
117
+ return raw === "true";
118
+ case "integer":
119
+ return isWholeNumber(raw) ? Number(raw) : raw;
120
+ case "number":
121
+ return isNumber(raw) ? Number(raw) : raw;
122
+ case "array":
123
+ return raw.split(",").map((item) => item.trim()).filter(Boolean);
124
+ default:
125
+ return raw;
126
+ }
127
+ }
128
+ function parameterProblems(parameters, values) {
129
+ var _a, _b;
130
+ const missing = parameters.filter(
131
+ (parameter) => parameter.required && (values[parameter.name] ?? "").trim() === ""
132
+ ).map((parameter) => formMetadata.titleCase(parameter.name));
133
+ const problems = missing.length > 0 ? [`Missing required fields: ${missing.join(", ")}`] : [];
134
+ for (const parameter of parameters) {
135
+ const raw = (values[parameter.name] ?? "").trim();
136
+ if (raw === "") continue;
137
+ const label = formMetadata.titleCase(parameter.name);
138
+ if (((_a = parameter.schema) == null ? void 0 : _a.type) === "integer" && !isWholeNumber(raw)) {
139
+ problems.push(`${label} must be a whole number.`);
140
+ } else if (((_b = parameter.schema) == null ? void 0 : _b.type) === "number" && !isNumber(raw)) {
141
+ problems.push(`${label} must be a number.`);
142
+ }
143
+ }
144
+ return problems;
145
+ }
146
+ function isWholeNumber(raw) {
147
+ return /^-?\d+$/.test(raw.trim());
148
+ }
149
+ function isNumber(raw) {
150
+ return raw.trim() !== "" && Number.isFinite(Number(raw));
151
+ }
152
+ exports.OperationArgsForm = OperationArgsForm;
153
+ //# sourceMappingURL=OperationArgsForm.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OperationArgsForm.cjs","sources":["../../src/rpc/OperationArgsForm.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport { FilterForm } from \"./FilterForm\";\nimport { getOperationClickyMeta } from \"./clickyMetadata\";\nimport {\n buildInitialParameterValues,\n defaultValueForParameter,\n titleCase,\n type ParameterValues,\n} from \"./formMetadata\";\nimport type { OpenAPIParameter, ResolvedOperation } from \"./types\";\nimport type { OperationsApiClient } from \"./useOperations\";\n\nexport type OperationArgs = Record<string, unknown>;\n\nexport type OperationArgsFormProps = {\n client: OperationsApiClient;\n operation: ResolvedOperation;\n /** Stored args. Read when the form mounts; remount it (key) to load others. */\n args: OperationArgs;\n /** Called with the typed args (booleans, numbers, lists) on every change. */\n onChange: (args: OperationArgs) => void;\n /** Called with false while a required parameter is missing or a value is malformed. */\n onValidityChange?: ((valid: boolean) => void) | undefined;\n className?: string | undefined;\n};\n\nconst NO_PARAMETERS: OpenAPIParameter[] = [];\n\n// OperationArgsForm renders an operation's own parameter form — the FilterForm\n// its action button opens, with the operation's lookups — as a field set whose\n// value is a stored args object, for surfaces that save or queue a run (the\n// schedule dialog, a Run now confirmation) rather than execute it.\nexport function OperationArgsForm({\n client,\n operation,\n args,\n onChange,\n onValidityChange,\n className,\n}: OperationArgsFormProps) {\n const parameters = operation.operation.parameters ?? NO_PARAMETERS;\n const [initial] = useState(() =>\n storedArgsToValues(args, parameters, operation.method),\n );\n const [values, setValues] = useState(initial.values);\n const problems = useMemo(\n () => parameterProblems(parameters, values),\n [parameters, values],\n );\n const valid = problems.length === 0;\n\n useEffect(() => {\n onValidityChange?.(valid);\n }, [onValidityChange, valid]);\n\n const handleChange = (next: ParameterValues) => {\n setValues(next);\n onChange(\n valuesToArgs({\n parameters,\n method: operation.method,\n values: next,\n stored: initial.names,\n }),\n );\n };\n\n return (\n <div className=\"space-y-2\">\n <FilterForm\n client={client}\n path={operation.path}\n method={operation.method}\n parameters={parameters}\n initialValues={initial.values}\n enableLookup={Boolean(getOperationClickyMeta(operation)?.supportsLookup)}\n showSubmit={false}\n onChange={handleChange}\n onSubmit={() => undefined}\n {...(className ? { className } : {})}\n />\n {initial.dropped.length > 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n Dropped arguments this operation no longer accepts:{\" \"}\n {initial.dropped.join(\", \")}\n </p>\n ) : null}\n {problems.map((problem) => (\n <p key={problem} className=\"text-sm text-destructive\">\n {problem}\n </p>\n ))}\n </div>\n );\n}\n\nfunction storedArgsToValues(\n args: OperationArgs,\n parameters: OpenAPIParameter[],\n method: string,\n) {\n const known = new Set(parameters.map((parameter) => parameter.name));\n const stored: ParameterValues = {};\n const dropped: string[] = [];\n for (const [name, value] of Object.entries(args)) {\n if (!known.has(name)) {\n dropped.push(name);\n continue;\n }\n stored[name] = storedValueToString(name, value);\n }\n return {\n values: buildInitialParameterValues(parameters, method, {}, stored),\n names: new Set(Object.keys(stored)),\n dropped,\n };\n}\n\nfunction storedValueToString(name: string, value: unknown): string {\n if (Array.isArray(value)) return value.map(String).join(\",\");\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return String(value);\n }\n throw new Error(\n `Stored argument ${name} has an unsupported value: ${JSON.stringify(value)}`,\n );\n}\n\n// valuesToArgs keeps what the schedule names: values that differ from the\n// parameter's default, required ones, and ones the stored args already held.\n// Untouched defaults stay out so the server keeps applying its own default.\nfunction valuesToArgs({\n parameters,\n method,\n values,\n stored,\n}: {\n parameters: OpenAPIParameter[];\n method: string;\n values: ParameterValues;\n stored: ReadonlySet<string>;\n}): OperationArgs {\n const args: OperationArgs = {};\n for (const parameter of parameters) {\n const raw = values[parameter.name] ?? \"\";\n if (raw.trim() === \"\") continue;\n const isDefault = raw === effectiveDefault(parameter, method);\n if (isDefault && !parameter.required && !stored.has(parameter.name)) continue;\n args[parameter.name] = typedValue(parameter, raw);\n }\n return args;\n}\n\nfunction effectiveDefault(parameter: OpenAPIParameter, method: string): string {\n const value = defaultValueForParameter(parameter, method);\n return parameter.schema?.type === \"boolean\" && value === \"\" ? \"false\" : value;\n}\n\nfunction typedValue(parameter: OpenAPIParameter, raw: string): unknown {\n switch (parameter.schema?.type) {\n case \"boolean\":\n return raw === \"true\";\n case \"integer\":\n return isWholeNumber(raw) ? Number(raw) : raw;\n case \"number\":\n return isNumber(raw) ? Number(raw) : raw;\n case \"array\":\n return raw\n .split(\",\")\n .map((item) => item.trim())\n .filter(Boolean);\n default:\n return raw;\n }\n}\n\nfunction parameterProblems(\n parameters: OpenAPIParameter[],\n values: ParameterValues,\n): string[] {\n const missing = parameters\n .filter(\n (parameter) =>\n parameter.required && (values[parameter.name] ?? \"\").trim() === \"\",\n )\n .map((parameter) => titleCase(parameter.name));\n const problems =\n missing.length > 0 ? [`Missing required fields: ${missing.join(\", \")}`] : [];\n for (const parameter of parameters) {\n const raw = (values[parameter.name] ?? \"\").trim();\n if (raw === \"\") continue;\n const label = titleCase(parameter.name);\n if (parameter.schema?.type === \"integer\" && !isWholeNumber(raw)) {\n problems.push(`${label} must be a whole number.`);\n } else if (parameter.schema?.type === \"number\" && !isNumber(raw)) {\n problems.push(`${label} must be a number.`);\n }\n }\n return problems;\n}\n\nfunction isWholeNumber(raw: string): boolean {\n return /^-?\\d+$/.test(raw.trim());\n}\n\nfunction isNumber(raw: string): boolean {\n return raw.trim() !== \"\" && Number.isFinite(Number(raw));\n}\n"],"names":["useState","useMemo","useEffect","jsxs","jsx","FilterForm","getOperationClickyMeta","buildInitialParameterValues","defaultValueForParameter","titleCase"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { ResolvedOperation } from './types.js';
2
+ import { OperationsApiClient } from './useOperations.js';
3
+ export type OperationArgs = Record<string, unknown>;
4
+ export type OperationArgsFormProps = {
5
+ client: OperationsApiClient;
6
+ operation: ResolvedOperation;
7
+ /** Stored args. Read when the form mounts; remount it (key) to load others. */
8
+ args: OperationArgs;
9
+ /** Called with the typed args (booleans, numbers, lists) on every change. */
10
+ onChange: (args: OperationArgs) => void;
11
+ /** Called with false while a required parameter is missing or a value is malformed. */
12
+ onValidityChange?: ((valid: boolean) => void) | undefined;
13
+ className?: string | undefined;
14
+ };
15
+ export declare function OperationArgsForm({ client, operation, args, onChange, onValidityChange, className, }: OperationArgsFormProps): import("react").JSX.Element;
16
+ //# sourceMappingURL=OperationArgsForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OperationArgsForm.d.ts","sourceRoot":"","sources":["../../src/rpc/OperationArgsForm.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAoB,iBAAiB,EAAE,MAAM,SAAS,CAAC;AACnE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEpD,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,mBAAmB,CAAC;IAC5B,SAAS,EAAE,iBAAiB,CAAC;IAC7B,+EAA+E;IAC/E,IAAI,EAAE,aAAa,CAAC;IACpB,6EAA6E;IAC7E,QAAQ,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;IACxC,uFAAuF;IACvF,gBAAgB,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAC1D,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,CAAC;AAQF,wBAAgB,iBAAiB,CAAC,EAChC,MAAM,EACN,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,gBAAgB,EAChB,SAAS,GACV,EAAE,sBAAsB,+BAuDxB"}
@@ -0,0 +1,153 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { useState, useMemo, useEffect } from "react";
3
+ import { FilterForm } from "./FilterForm.js";
4
+ import { getOperationClickyMeta } from "./clickyMetadata.js";
5
+ import { buildInitialParameterValues, titleCase, defaultValueForParameter } from "./formMetadata.js";
6
+ const NO_PARAMETERS = [];
7
+ function OperationArgsForm({
8
+ client,
9
+ operation,
10
+ args,
11
+ onChange,
12
+ onValidityChange,
13
+ className
14
+ }) {
15
+ var _a;
16
+ const parameters = operation.operation.parameters ?? NO_PARAMETERS;
17
+ const [initial] = useState(
18
+ () => storedArgsToValues(args, parameters, operation.method)
19
+ );
20
+ const [values, setValues] = useState(initial.values);
21
+ const problems = useMemo(
22
+ () => parameterProblems(parameters, values),
23
+ [parameters, values]
24
+ );
25
+ const valid = problems.length === 0;
26
+ useEffect(() => {
27
+ onValidityChange == null ? void 0 : onValidityChange(valid);
28
+ }, [onValidityChange, valid]);
29
+ const handleChange = (next) => {
30
+ setValues(next);
31
+ onChange(
32
+ valuesToArgs({
33
+ parameters,
34
+ method: operation.method,
35
+ values: next,
36
+ stored: initial.names
37
+ })
38
+ );
39
+ };
40
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
41
+ /* @__PURE__ */ jsx(
42
+ FilterForm,
43
+ {
44
+ client,
45
+ path: operation.path,
46
+ method: operation.method,
47
+ parameters,
48
+ initialValues: initial.values,
49
+ enableLookup: Boolean((_a = getOperationClickyMeta(operation)) == null ? void 0 : _a.supportsLookup),
50
+ showSubmit: false,
51
+ onChange: handleChange,
52
+ onSubmit: () => void 0,
53
+ ...className ? { className } : {}
54
+ }
55
+ ),
56
+ initial.dropped.length > 0 ? /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
57
+ "Dropped arguments this operation no longer accepts:",
58
+ " ",
59
+ initial.dropped.join(", ")
60
+ ] }) : null,
61
+ problems.map((problem) => /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: problem }, problem))
62
+ ] });
63
+ }
64
+ function storedArgsToValues(args, parameters, method) {
65
+ const known = new Set(parameters.map((parameter) => parameter.name));
66
+ const stored = {};
67
+ const dropped = [];
68
+ for (const [name, value] of Object.entries(args)) {
69
+ if (!known.has(name)) {
70
+ dropped.push(name);
71
+ continue;
72
+ }
73
+ stored[name] = storedValueToString(name, value);
74
+ }
75
+ return {
76
+ values: buildInitialParameterValues(parameters, method, {}, stored),
77
+ names: new Set(Object.keys(stored)),
78
+ dropped
79
+ };
80
+ }
81
+ function storedValueToString(name, value) {
82
+ if (Array.isArray(value)) return value.map(String).join(",");
83
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
84
+ return String(value);
85
+ }
86
+ throw new Error(
87
+ `Stored argument ${name} has an unsupported value: ${JSON.stringify(value)}`
88
+ );
89
+ }
90
+ function valuesToArgs({
91
+ parameters,
92
+ method,
93
+ values,
94
+ stored
95
+ }) {
96
+ const args = {};
97
+ for (const parameter of parameters) {
98
+ const raw = values[parameter.name] ?? "";
99
+ if (raw.trim() === "") continue;
100
+ const isDefault = raw === effectiveDefault(parameter, method);
101
+ if (isDefault && !parameter.required && !stored.has(parameter.name)) continue;
102
+ args[parameter.name] = typedValue(parameter, raw);
103
+ }
104
+ return args;
105
+ }
106
+ function effectiveDefault(parameter, method) {
107
+ var _a;
108
+ const value = defaultValueForParameter(parameter, method);
109
+ return ((_a = parameter.schema) == null ? void 0 : _a.type) === "boolean" && value === "" ? "false" : value;
110
+ }
111
+ function typedValue(parameter, raw) {
112
+ var _a;
113
+ switch ((_a = parameter.schema) == null ? void 0 : _a.type) {
114
+ case "boolean":
115
+ return raw === "true";
116
+ case "integer":
117
+ return isWholeNumber(raw) ? Number(raw) : raw;
118
+ case "number":
119
+ return isNumber(raw) ? Number(raw) : raw;
120
+ case "array":
121
+ return raw.split(",").map((item) => item.trim()).filter(Boolean);
122
+ default:
123
+ return raw;
124
+ }
125
+ }
126
+ function parameterProblems(parameters, values) {
127
+ var _a, _b;
128
+ const missing = parameters.filter(
129
+ (parameter) => parameter.required && (values[parameter.name] ?? "").trim() === ""
130
+ ).map((parameter) => titleCase(parameter.name));
131
+ const problems = missing.length > 0 ? [`Missing required fields: ${missing.join(", ")}`] : [];
132
+ for (const parameter of parameters) {
133
+ const raw = (values[parameter.name] ?? "").trim();
134
+ if (raw === "") continue;
135
+ const label = titleCase(parameter.name);
136
+ if (((_a = parameter.schema) == null ? void 0 : _a.type) === "integer" && !isWholeNumber(raw)) {
137
+ problems.push(`${label} must be a whole number.`);
138
+ } else if (((_b = parameter.schema) == null ? void 0 : _b.type) === "number" && !isNumber(raw)) {
139
+ problems.push(`${label} must be a number.`);
140
+ }
141
+ }
142
+ return problems;
143
+ }
144
+ function isWholeNumber(raw) {
145
+ return /^-?\d+$/.test(raw.trim());
146
+ }
147
+ function isNumber(raw) {
148
+ return raw.trim() !== "" && Number.isFinite(Number(raw));
149
+ }
150
+ export {
151
+ OperationArgsForm
152
+ };
153
+ //# sourceMappingURL=OperationArgsForm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OperationArgsForm.js","sources":["../../src/rpc/OperationArgsForm.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from \"react\";\nimport { FilterForm } from \"./FilterForm\";\nimport { getOperationClickyMeta } from \"./clickyMetadata\";\nimport {\n buildInitialParameterValues,\n defaultValueForParameter,\n titleCase,\n type ParameterValues,\n} from \"./formMetadata\";\nimport type { OpenAPIParameter, ResolvedOperation } from \"./types\";\nimport type { OperationsApiClient } from \"./useOperations\";\n\nexport type OperationArgs = Record<string, unknown>;\n\nexport type OperationArgsFormProps = {\n client: OperationsApiClient;\n operation: ResolvedOperation;\n /** Stored args. Read when the form mounts; remount it (key) to load others. */\n args: OperationArgs;\n /** Called with the typed args (booleans, numbers, lists) on every change. */\n onChange: (args: OperationArgs) => void;\n /** Called with false while a required parameter is missing or a value is malformed. */\n onValidityChange?: ((valid: boolean) => void) | undefined;\n className?: string | undefined;\n};\n\nconst NO_PARAMETERS: OpenAPIParameter[] = [];\n\n// OperationArgsForm renders an operation's own parameter form — the FilterForm\n// its action button opens, with the operation's lookups — as a field set whose\n// value is a stored args object, for surfaces that save or queue a run (the\n// schedule dialog, a Run now confirmation) rather than execute it.\nexport function OperationArgsForm({\n client,\n operation,\n args,\n onChange,\n onValidityChange,\n className,\n}: OperationArgsFormProps) {\n const parameters = operation.operation.parameters ?? NO_PARAMETERS;\n const [initial] = useState(() =>\n storedArgsToValues(args, parameters, operation.method),\n );\n const [values, setValues] = useState(initial.values);\n const problems = useMemo(\n () => parameterProblems(parameters, values),\n [parameters, values],\n );\n const valid = problems.length === 0;\n\n useEffect(() => {\n onValidityChange?.(valid);\n }, [onValidityChange, valid]);\n\n const handleChange = (next: ParameterValues) => {\n setValues(next);\n onChange(\n valuesToArgs({\n parameters,\n method: operation.method,\n values: next,\n stored: initial.names,\n }),\n );\n };\n\n return (\n <div className=\"space-y-2\">\n <FilterForm\n client={client}\n path={operation.path}\n method={operation.method}\n parameters={parameters}\n initialValues={initial.values}\n enableLookup={Boolean(getOperationClickyMeta(operation)?.supportsLookup)}\n showSubmit={false}\n onChange={handleChange}\n onSubmit={() => undefined}\n {...(className ? { className } : {})}\n />\n {initial.dropped.length > 0 ? (\n <p className=\"text-xs text-muted-foreground\">\n Dropped arguments this operation no longer accepts:{\" \"}\n {initial.dropped.join(\", \")}\n </p>\n ) : null}\n {problems.map((problem) => (\n <p key={problem} className=\"text-sm text-destructive\">\n {problem}\n </p>\n ))}\n </div>\n );\n}\n\nfunction storedArgsToValues(\n args: OperationArgs,\n parameters: OpenAPIParameter[],\n method: string,\n) {\n const known = new Set(parameters.map((parameter) => parameter.name));\n const stored: ParameterValues = {};\n const dropped: string[] = [];\n for (const [name, value] of Object.entries(args)) {\n if (!known.has(name)) {\n dropped.push(name);\n continue;\n }\n stored[name] = storedValueToString(name, value);\n }\n return {\n values: buildInitialParameterValues(parameters, method, {}, stored),\n names: new Set(Object.keys(stored)),\n dropped,\n };\n}\n\nfunction storedValueToString(name: string, value: unknown): string {\n if (Array.isArray(value)) return value.map(String).join(\",\");\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return String(value);\n }\n throw new Error(\n `Stored argument ${name} has an unsupported value: ${JSON.stringify(value)}`,\n );\n}\n\n// valuesToArgs keeps what the schedule names: values that differ from the\n// parameter's default, required ones, and ones the stored args already held.\n// Untouched defaults stay out so the server keeps applying its own default.\nfunction valuesToArgs({\n parameters,\n method,\n values,\n stored,\n}: {\n parameters: OpenAPIParameter[];\n method: string;\n values: ParameterValues;\n stored: ReadonlySet<string>;\n}): OperationArgs {\n const args: OperationArgs = {};\n for (const parameter of parameters) {\n const raw = values[parameter.name] ?? \"\";\n if (raw.trim() === \"\") continue;\n const isDefault = raw === effectiveDefault(parameter, method);\n if (isDefault && !parameter.required && !stored.has(parameter.name)) continue;\n args[parameter.name] = typedValue(parameter, raw);\n }\n return args;\n}\n\nfunction effectiveDefault(parameter: OpenAPIParameter, method: string): string {\n const value = defaultValueForParameter(parameter, method);\n return parameter.schema?.type === \"boolean\" && value === \"\" ? \"false\" : value;\n}\n\nfunction typedValue(parameter: OpenAPIParameter, raw: string): unknown {\n switch (parameter.schema?.type) {\n case \"boolean\":\n return raw === \"true\";\n case \"integer\":\n return isWholeNumber(raw) ? Number(raw) : raw;\n case \"number\":\n return isNumber(raw) ? Number(raw) : raw;\n case \"array\":\n return raw\n .split(\",\")\n .map((item) => item.trim())\n .filter(Boolean);\n default:\n return raw;\n }\n}\n\nfunction parameterProblems(\n parameters: OpenAPIParameter[],\n values: ParameterValues,\n): string[] {\n const missing = parameters\n .filter(\n (parameter) =>\n parameter.required && (values[parameter.name] ?? \"\").trim() === \"\",\n )\n .map((parameter) => titleCase(parameter.name));\n const problems =\n missing.length > 0 ? [`Missing required fields: ${missing.join(\", \")}`] : [];\n for (const parameter of parameters) {\n const raw = (values[parameter.name] ?? \"\").trim();\n if (raw === \"\") continue;\n const label = titleCase(parameter.name);\n if (parameter.schema?.type === \"integer\" && !isWholeNumber(raw)) {\n problems.push(`${label} must be a whole number.`);\n } else if (parameter.schema?.type === \"number\" && !isNumber(raw)) {\n problems.push(`${label} must be a number.`);\n }\n }\n return problems;\n}\n\nfunction isWholeNumber(raw: string): boolean {\n return /^-?\\d+$/.test(raw.trim());\n}\n\nfunction isNumber(raw: string): boolean {\n return raw.trim() !== \"\" && Number.isFinite(Number(raw));\n}\n"],"names":[],"mappings":"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"}
@@ -7,16 +7,17 @@ const Combobox = require("../components/Combobox.cjs");
7
7
  const CopyButton = require("../components/CopyButton.cjs");
8
8
  const Field = require("../components/Field.cjs");
9
9
  const InputField = require("../components/InputField.cjs");
10
- const JsonSchemaForm = require("../components/JsonSchemaForm.cjs");
11
10
  const ScheduleEditor = require("../components/ScheduleEditor.cjs");
12
11
  const Modal = require("../overlay/Modal.cjs");
13
12
  const operationScheduleModel = require("./operation-schedule-model.cjs");
14
13
  const operationCliCommand = require("./operation-cli-command.cjs");
15
14
  const InlineError = require("./InlineError.cjs");
15
+ const OperationArgsForm = require("./OperationArgsForm.cjs");
16
16
  const OperationPicker = require("./OperationPicker.cjs");
17
17
  function OperationScheduleDialog(_props) {
18
18
  var _a, _b, _c, _d;
19
19
  const {
20
+ client,
20
21
  open,
21
22
  operations,
22
23
  schedule,
@@ -34,19 +35,34 @@ function OperationScheduleDialog(_props) {
34
35
  const [pending, setPending] = react.useState();
35
36
  const [error, setError] = react.useState();
36
37
  const [confirmingRun, setConfirmingRun] = react.useState(false);
38
+ const [concurrencyText, setConcurrencyText] = react.useState("1");
39
+ const [argsValid, setArgsValid] = react.useState(true);
40
+ const [argsSession, setArgsSession] = react.useState(0);
37
41
  react.useEffect(() => {
38
42
  if (!open) return;
43
+ setArgsSession((session) => session + 1);
39
44
  setInput(
40
45
  schedule ? operationScheduleModel.scheduleToInput(schedule) : {
41
46
  ...operationScheduleModel.newOperationScheduleInput(),
42
47
  targets: [...defaultTargets ?? []]
43
48
  }
44
49
  );
50
+ setConcurrencyText(String((schedule == null ? void 0 : schedule.concurrency) ?? 1));
45
51
  setError(void 0);
46
52
  setConfirmingRun(false);
47
53
  }, [open, schedule, defaultTargets]);
54
+ const multiTarget = input.targets.length > 1;
55
+ const concurrency = Number(concurrencyText);
56
+ const concurrencyValid = !multiTarget || concurrencyText.trim() !== "" && Number.isInteger(concurrency) && concurrency >= 1 && concurrency <= input.targets.length;
57
+ const concurrencyPayload = multiTarget ? { concurrency } : {};
58
+ const changeTargets = (targets) => {
59
+ setInput({ ...input, targets });
60
+ const limit = Math.max(1, targets.length);
61
+ setConcurrencyText(
62
+ (current) => Number(current) > limit ? String(limit) : current
63
+ );
64
+ };
48
65
  const operation = operationScheduleModel.operationByID(operations, input.operationId);
49
- const schema = operationScheduleModel.operationInputSchema(operation);
50
66
  const suggestions = ((_b = (_a = operation == null ? void 0 : operation.operation["x-clicky"]) == null ? void 0 : _a.schedule) == null ? void 0 : _b.suggestions) ?? [];
51
67
  const destructive = ((_d = (_c = operation == null ? void 0 : operation.operation["x-clicky"]) == null ? void 0 : _c.toolHints) == null ? void 0 : _d.destructiveHint) === true;
52
68
  const cliCommand = (cli == null ? void 0 : cli.targetFlag) ? input.targets.map(
@@ -72,7 +88,7 @@ function OperationScheduleDialog(_props) {
72
88
  setPending("save");
73
89
  setError(void 0);
74
90
  try {
75
- await onSave(input);
91
+ await onSave({ ...input, ...concurrencyPayload });
76
92
  onClose();
77
93
  } catch (nextError) {
78
94
  setError(nextError);
@@ -87,7 +103,8 @@ function OperationScheduleDialog(_props) {
87
103
  await onRunNow({
88
104
  operationId: input.operationId,
89
105
  args: input.args,
90
- targets: input.targets
106
+ targets: input.targets,
107
+ ...concurrencyPayload
91
108
  });
92
109
  setConfirmingRun(false);
93
110
  onClose();
@@ -99,9 +116,11 @@ function OperationScheduleDialog(_props) {
99
116
  }
100
117
  };
101
118
  const canSave = Boolean(
102
- input.name.trim() && input.operationId && input.cron.trim() && input.targets.length
119
+ input.name.trim() && input.operationId && input.cron.trim() && input.targets.length && concurrencyValid && argsValid
120
+ );
121
+ const canRun = Boolean(
122
+ input.operationId && input.targets.length && concurrencyValid && argsValid
103
123
  );
104
- const canRun = Boolean(input.operationId && input.targets.length);
105
124
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
106
125
  /* @__PURE__ */ jsxRuntime.jsx(
107
126
  Modal.Modal,
@@ -152,11 +171,34 @@ function OperationScheduleDialog(_props) {
152
171
  allowCustomValue: false,
153
172
  options: targetOptions,
154
173
  value: input.targets,
155
- onChange: (targets) => setInput({ ...input, targets })
174
+ onChange: changeTargets
156
175
  }
157
176
  )
158
177
  }
159
178
  ),
179
+ multiTarget ? /* @__PURE__ */ jsxRuntime.jsx(
180
+ Field.Field,
181
+ {
182
+ label: `${targetLabel} at once`,
183
+ htmlFor: "operation-schedule-concurrency",
184
+ error: concurrencyValid ? void 0 : `Enter a whole number from 1 to ${input.targets.length}.`,
185
+ helper: `How many of the ${input.targets.length} selected run at the same time; the rest wait their turn.`,
186
+ children: /* @__PURE__ */ jsxRuntime.jsx(
187
+ InputField.InputField,
188
+ {
189
+ id: "operation-schedule-concurrency",
190
+ type: "number",
191
+ inputMode: "numeric",
192
+ min: 1,
193
+ max: input.targets.length,
194
+ step: 1,
195
+ invalid: !concurrencyValid,
196
+ value: concurrencyText,
197
+ onChange: setConcurrencyText
198
+ }
199
+ )
200
+ }
201
+ ) : null,
160
202
  /* @__PURE__ */ jsxRuntime.jsx(
161
203
  Field.Field,
162
204
  {
@@ -182,19 +224,20 @@ function OperationScheduleDialog(_props) {
182
224
  onChange: selectOperation
183
225
  }
184
226
  ),
185
- operation ? schema && Object.keys(schema.properties ?? {}).length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-2", children: [
227
+ operation ? /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-2", children: [
186
228
  /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-semibold", children: "Arguments" }),
187
229
  /* @__PURE__ */ jsxRuntime.jsx(
188
- JsonSchemaForm.JsonSchemaForm,
230
+ OperationArgsForm.OperationArgsForm,
189
231
  {
190
- schema,
191
- value: input.args,
192
- onChange: (args) => setInput({ ...input, args }),
193
- idPrefix: "operation-schedule-args",
194
- showPreferencesMenu: false
195
- }
232
+ client,
233
+ operation,
234
+ args: input.args,
235
+ onChange: (args) => setInput((current) => ({ ...current, args })),
236
+ onValidityChange: setArgsValid
237
+ },
238
+ `${argsSession}:${input.operationId}`
196
239
  )
197
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "This operation has no arguments." }) : null,
240
+ ] }) : null,
198
241
  cliCommand ? /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-1", children: [
199
242
  /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-semibold", children: "Equivalent CLI command" }),
200
243
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 rounded-md border bg-muted/30 px-3 py-2", children: [
@@ -249,7 +292,8 @@ function OperationScheduleDialog(_props) {
249
292
  /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-2 text-sm", children: [
250
293
  targetLabel,
251
294
  ": ",
252
- input.targets.join(", ")
295
+ input.targets.join(", "),
296
+ multiTarget ? ` (${concurrency} at once)` : ""
253
297
  ] })
254
298
  ]
255
299
  }
@@ -1 +1 @@
1
- {"version":3,"file":"OperationScheduleDialog.cjs","sources":["../../src/rpc/OperationScheduleDialog.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { Button } from \"../components/button\";\nimport { Combobox } from \"../components/Combobox\";\nimport type { ComboboxOption } from \"../components/combobox-types\";\nimport { CopyButton } from \"../components/CopyButton\";\nimport { Field } from \"../components/Field\";\nimport { InputField } from \"../components/InputField\";\nimport { JsonSchemaForm } from \"../components/JsonSchemaForm\";\nimport { ScheduleEditor } from \"../components/ScheduleEditor\";\nimport { Modal } from \"../overlay/Modal\";\nimport {\n newOperationScheduleInput,\n operationByID,\n operationInputSchema,\n operationLabel,\n scheduleToInput,\n} from \"./operation-schedule-model\";\nimport { operationCLICommand } from \"./operation-cli-command\";\nimport type {\n OperationSchedule,\n OperationScheduleCLI,\n OperationScheduleInput,\n OperationScheduleRunInput,\n} from \"./operation-schedule-types\";\nimport type { ResolvedOperation } from \"./types\";\nimport { InlineError } from \"./InlineError\";\nimport { OperationPicker } from \"./OperationPicker\";\n\nexport interface OperationScheduleDialogProps {\n open: boolean;\n operations: readonly ResolvedOperation[];\n targetOptions: ComboboxOption[];\n defaultTargets?: string[];\n targetLabel?: string;\n schedule?: OperationSchedule;\n cli?: OperationScheduleCLI;\n onClose: () => void;\n onSave: (input: OperationScheduleInput) => Promise<unknown>;\n onRunNow: (input: OperationScheduleRunInput) => Promise<unknown>;\n}\n\nexport function OperationScheduleDialog(_props: OperationScheduleDialogProps) {\n const {\n open,\n operations,\n schedule,\n cli,\n targetOptions,\n defaultTargets,\n targetLabel = \"Targets\",\n onClose,\n onSave,\n onRunNow,\n } = _props;\n const [input, setInput] = useState<OperationScheduleInput>(\n newOperationScheduleInput,\n );\n const [pending, setPending] = useState<\"save\" | \"run\">();\n const [error, setError] = useState<unknown>();\n const [confirmingRun, setConfirmingRun] = useState(false);\n\n useEffect(() => {\n if (!open) return;\n setInput(\n schedule\n ? scheduleToInput(schedule)\n : {\n ...newOperationScheduleInput(),\n targets: [...(defaultTargets ?? [])],\n },\n );\n setError(undefined);\n setConfirmingRun(false);\n }, [open, schedule, defaultTargets]);\n\n const operation = operationByID(operations, input.operationId);\n const schema = operationInputSchema(operation);\n const suggestions =\n operation?.operation[\"x-clicky\"]?.schedule?.suggestions ?? [];\n const destructive =\n operation?.operation[\"x-clicky\"]?.toolHints?.destructiveHint === true;\n const cliCommand = cli?.targetFlag\n ? input.targets\n .map((target) =>\n operationCLICommand(operation, input.args, {\n ...cli,\n globalFlags: { ...cli.globalFlags, [cli.targetFlag!]: target },\n }),\n )\n .join(\"\\n\")\n : operationCLICommand(operation, input.args, cli);\n\n const selectOperation = (operationId: string) => {\n const selected = operationByID(operations, operationId);\n setInput((current) => ({\n ...current,\n operationId,\n args: {},\n name: current.name || operationLabel(selected),\n cron:\n selected?.operation[\"x-clicky\"]?.schedule?.suggestions?.[0]?.cron ??\n current.cron,\n }));\n };\n\n const save = async () => {\n setPending(\"save\");\n setError(undefined);\n try {\n await onSave(input);\n onClose();\n } catch (nextError) {\n setError(nextError);\n } finally {\n setPending(undefined);\n }\n };\n\n const run = async () => {\n setPending(\"run\");\n setError(undefined);\n try {\n await onRunNow({\n operationId: input.operationId,\n args: input.args,\n targets: input.targets,\n });\n setConfirmingRun(false);\n onClose();\n } catch (nextError) {\n setError(nextError);\n setConfirmingRun(false);\n } finally {\n setPending(undefined);\n }\n };\n\n const canSave = Boolean(\n input.name.trim() &&\n input.operationId &&\n input.cron.trim() &&\n input.targets.length,\n );\n const canRun = Boolean(input.operationId && input.targets.length);\n\n return (\n <>\n <Modal\n open={open}\n onClose={onClose}\n title={schedule ? \"Edit schedule\" : \"Add schedule\"}\n size=\"xl\"\n footer={\n <div className=\"flex w-full flex-wrap justify-end gap-2\">\n <Button type=\"button\" variant=\"outline\" onClick={onClose}>\n Cancel\n </Button>\n <Button\n type=\"button\"\n variant={destructive ? \"destructive\" : \"secondary\"}\n disabled={!canRun}\n loading={pending === \"run\"}\n onClick={() => setConfirmingRun(true)}\n >\n Run now\n </Button>\n <Button\n type=\"button\"\n disabled={!canSave}\n loading={pending === \"save\"}\n onClick={save}\n >\n Save schedule\n </Button>\n </div>\n }\n >\n <div className=\"space-y-5\">\n <Field\n label={targetLabel}\n htmlFor=\"operation-schedule-targets\"\n required\n >\n <Combobox\n id=\"operation-schedule-targets\"\n multiple\n variant=\"tags\"\n ariaLabel={targetLabel}\n ariaRequired\n allowCustomValue={false}\n options={targetOptions}\n value={input.targets}\n onChange={(targets) => setInput({ ...input, targets })}\n />\n </Field>\n <Field\n label=\"Schedule name\"\n htmlFor=\"operation-schedule-name\"\n required\n >\n <InputField\n id=\"operation-schedule-name\"\n value={input.name}\n onChange={(name) => setInput({ ...input, name })}\n />\n </Field>\n <OperationPicker\n id=\"operation-schedule-operation\"\n operations={operations}\n value={input.operationId}\n onChange={selectOperation}\n />\n {operation ? (\n schema && Object.keys(schema.properties ?? {}).length > 0 ? (\n <section className=\"space-y-2\">\n <h3 className=\"text-sm font-semibold\">Arguments</h3>\n <JsonSchemaForm\n schema={schema}\n value={input.args}\n onChange={(args) => setInput({ ...input, args })}\n idPrefix=\"operation-schedule-args\"\n showPreferencesMenu={false}\n />\n </section>\n ) : (\n <p className=\"text-sm text-muted-foreground\">\n This operation has no arguments.\n </p>\n )\n ) : null}\n {cliCommand ? (\n <section className=\"space-y-1\">\n <h3 className=\"text-sm font-semibold\">Equivalent CLI command</h3>\n <div className=\"flex items-center gap-2 rounded-md border bg-muted/30 px-3 py-2\">\n <code className=\"min-w-0 flex-1 overflow-x-auto whitespace-pre text-xs\">\n {cliCommand}\n </code>\n <CopyButton value={cliCommand} label=\"Copy CLI command\" />\n </div>\n </section>\n ) : null}\n <ScheduleEditor\n id=\"operation-schedule\"\n value={input}\n onChange={(timing) => setInput({ ...input, ...timing })}\n cronSuggestions={suggestions}\n timezoneSuggestions={[input.timezone, \"UTC\"]}\n />\n {error ? (\n <InlineError title=\"Schedule action failed\" error={error} />\n ) : null}\n </div>\n </Modal>\n <Modal\n open={confirmingRun}\n onClose={() => setConfirmingRun(false)}\n title={`Run ${operationLabel(operation)} now?`}\n size=\"sm\"\n footer={\n <div className=\"flex w-full justify-end gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setConfirmingRun(false)}\n >\n Cancel\n </Button>\n <Button\n type=\"button\"\n variant={destructive ? \"destructive\" : \"default\"}\n loading={pending === \"run\"}\n onClick={run}\n >\n Run now\n </Button>\n </div>\n }\n >\n <p className=\"text-sm text-muted-foreground\">\n This runs the configured operation once without creating or changing a\n recurring schedule.\n </p>\n <p className=\"mt-2 text-sm\">\n {targetLabel}: {input.targets.join(\", \")}\n </p>\n </Modal>\n </>\n );\n}\n"],"names":["useState","newOperationScheduleInput","useEffect","scheduleToInput","operationByID","operationInputSchema","operationCLICommand","operationLabel","_d","_c","_b","_a","jsxs","Fragment","jsx","Modal","Button","Field","Combobox","InputField","OperationPicker","JsonSchemaForm","CopyButton","ScheduleEditor","InlineError"],"mappings":"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"}
1
+ {"version":3,"file":"OperationScheduleDialog.cjs","sources":["../../src/rpc/OperationScheduleDialog.tsx"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { Button } from \"../components/button\";\nimport { Combobox } from \"../components/Combobox\";\nimport type { ComboboxOption } from \"../components/combobox-types\";\nimport { CopyButton } from \"../components/CopyButton\";\nimport { Field } from \"../components/Field\";\nimport { InputField } from \"../components/InputField\";\nimport { ScheduleEditor } from \"../components/ScheduleEditor\";\nimport { Modal } from \"../overlay/Modal\";\nimport {\n newOperationScheduleInput,\n operationByID,\n operationLabel,\n scheduleToInput,\n} from \"./operation-schedule-model\";\nimport { operationCLICommand } from \"./operation-cli-command\";\nimport type {\n OperationSchedule,\n OperationScheduleCLI,\n OperationScheduleInput,\n OperationScheduleRunInput,\n} from \"./operation-schedule-types\";\nimport type { ResolvedOperation } from \"./types\";\nimport type { OperationsApiClient } from \"./useOperations\";\nimport { InlineError } from \"./InlineError\";\nimport { OperationArgsForm } from \"./OperationArgsForm\";\nimport { OperationPicker } from \"./OperationPicker\";\n\nexport interface OperationScheduleDialogProps {\n /** Client for the argument form's lookups (the operation's parameter pickers). */\n client: OperationsApiClient;\n open: boolean;\n operations: readonly ResolvedOperation[];\n targetOptions: ComboboxOption[];\n defaultTargets?: string[];\n targetLabel?: string;\n schedule?: OperationSchedule;\n cli?: OperationScheduleCLI;\n onClose: () => void;\n onSave: (input: OperationScheduleInput) => Promise<unknown>;\n onRunNow: (input: OperationScheduleRunInput) => Promise<unknown>;\n}\n\nexport function OperationScheduleDialog(_props: OperationScheduleDialogProps) {\n const {\n client,\n open,\n operations,\n schedule,\n cli,\n targetOptions,\n defaultTargets,\n targetLabel = \"Targets\",\n onClose,\n onSave,\n onRunNow,\n } = _props;\n const [input, setInput] = useState<OperationScheduleInput>(\n newOperationScheduleInput,\n );\n const [pending, setPending] = useState<\"save\" | \"run\">();\n const [error, setError] = useState<unknown>();\n const [confirmingRun, setConfirmingRun] = useState(false);\n const [concurrencyText, setConcurrencyText] = useState(\"1\");\n const [argsValid, setArgsValid] = useState(true);\n // Each opening remounts the argument form so it loads the args set below,\n // not the ones a previous opening left in input.\n const [argsSession, setArgsSession] = useState(0);\n\n useEffect(() => {\n if (!open) return;\n setArgsSession((session) => session + 1);\n setInput(\n schedule\n ? scheduleToInput(schedule)\n : {\n ...newOperationScheduleInput(),\n targets: [...(defaultTargets ?? [])],\n },\n );\n setConcurrencyText(String(schedule?.concurrency ?? 1));\n setError(undefined);\n setConfirmingRun(false);\n }, [open, schedule, defaultTargets]);\n\n const multiTarget = input.targets.length > 1;\n const concurrency = Number(concurrencyText);\n const concurrencyValid =\n !multiTarget ||\n (concurrencyText.trim() !== \"\" &&\n Number.isInteger(concurrency) &&\n concurrency >= 1 &&\n concurrency <= input.targets.length);\n const concurrencyPayload = multiTarget ? { concurrency } : {};\n\n const changeTargets = (targets: string[]) => {\n setInput({ ...input, targets });\n const limit = Math.max(1, targets.length);\n setConcurrencyText((current) =>\n Number(current) > limit ? String(limit) : current,\n );\n };\n\n const operation = operationByID(operations, input.operationId);\n const suggestions =\n operation?.operation[\"x-clicky\"]?.schedule?.suggestions ?? [];\n const destructive =\n operation?.operation[\"x-clicky\"]?.toolHints?.destructiveHint === true;\n const cliCommand = cli?.targetFlag\n ? input.targets\n .map((target) =>\n operationCLICommand(operation, input.args, {\n ...cli,\n globalFlags: { ...cli.globalFlags, [cli.targetFlag!]: target },\n }),\n )\n .join(\"\\n\")\n : operationCLICommand(operation, input.args, cli);\n\n const selectOperation = (operationId: string) => {\n const selected = operationByID(operations, operationId);\n setInput((current) => ({\n ...current,\n operationId,\n args: {},\n name: current.name || operationLabel(selected),\n cron:\n selected?.operation[\"x-clicky\"]?.schedule?.suggestions?.[0]?.cron ??\n current.cron,\n }));\n };\n\n const save = async () => {\n setPending(\"save\");\n setError(undefined);\n try {\n await onSave({ ...input, ...concurrencyPayload });\n onClose();\n } catch (nextError) {\n setError(nextError);\n } finally {\n setPending(undefined);\n }\n };\n\n const run = async () => {\n setPending(\"run\");\n setError(undefined);\n try {\n await onRunNow({\n operationId: input.operationId,\n args: input.args,\n targets: input.targets,\n ...concurrencyPayload,\n });\n setConfirmingRun(false);\n onClose();\n } catch (nextError) {\n setError(nextError);\n setConfirmingRun(false);\n } finally {\n setPending(undefined);\n }\n };\n\n const canSave = Boolean(\n input.name.trim() &&\n input.operationId &&\n input.cron.trim() &&\n input.targets.length &&\n concurrencyValid &&\n argsValid,\n );\n const canRun = Boolean(\n input.operationId && input.targets.length && concurrencyValid && argsValid,\n );\n\n return (\n <>\n <Modal\n open={open}\n onClose={onClose}\n title={schedule ? \"Edit schedule\" : \"Add schedule\"}\n size=\"xl\"\n footer={\n <div className=\"flex w-full flex-wrap justify-end gap-2\">\n <Button type=\"button\" variant=\"outline\" onClick={onClose}>\n Cancel\n </Button>\n <Button\n type=\"button\"\n variant={destructive ? \"destructive\" : \"secondary\"}\n disabled={!canRun}\n loading={pending === \"run\"}\n onClick={() => setConfirmingRun(true)}\n >\n Run now\n </Button>\n <Button\n type=\"button\"\n disabled={!canSave}\n loading={pending === \"save\"}\n onClick={save}\n >\n Save schedule\n </Button>\n </div>\n }\n >\n <div className=\"space-y-5\">\n <Field\n label={targetLabel}\n htmlFor=\"operation-schedule-targets\"\n required\n >\n <Combobox\n id=\"operation-schedule-targets\"\n multiple\n variant=\"tags\"\n ariaLabel={targetLabel}\n ariaRequired\n allowCustomValue={false}\n options={targetOptions}\n value={input.targets}\n onChange={changeTargets}\n />\n </Field>\n {multiTarget ? (\n <Field\n label={`${targetLabel} at once`}\n htmlFor=\"operation-schedule-concurrency\"\n error={\n concurrencyValid\n ? undefined\n : `Enter a whole number from 1 to ${input.targets.length}.`\n }\n helper={`How many of the ${input.targets.length} selected run at the same time; the rest wait their turn.`}\n >\n <InputField\n id=\"operation-schedule-concurrency\"\n type=\"number\"\n inputMode=\"numeric\"\n min={1}\n max={input.targets.length}\n step={1}\n invalid={!concurrencyValid}\n value={concurrencyText}\n onChange={setConcurrencyText}\n />\n </Field>\n ) : null}\n <Field\n label=\"Schedule name\"\n htmlFor=\"operation-schedule-name\"\n required\n >\n <InputField\n id=\"operation-schedule-name\"\n value={input.name}\n onChange={(name) => setInput({ ...input, name })}\n />\n </Field>\n <OperationPicker\n id=\"operation-schedule-operation\"\n operations={operations}\n value={input.operationId}\n onChange={selectOperation}\n />\n {operation ? (\n <section className=\"space-y-2\">\n <h3 className=\"text-sm font-semibold\">Arguments</h3>\n <OperationArgsForm\n key={`${argsSession}:${input.operationId}`}\n client={client}\n operation={operation}\n args={input.args}\n onChange={(args) =>\n setInput((current) => ({ ...current, args }))\n }\n onValidityChange={setArgsValid}\n />\n </section>\n ) : null}\n {cliCommand ? (\n <section className=\"space-y-1\">\n <h3 className=\"text-sm font-semibold\">Equivalent CLI command</h3>\n <div className=\"flex items-center gap-2 rounded-md border bg-muted/30 px-3 py-2\">\n <code className=\"min-w-0 flex-1 overflow-x-auto whitespace-pre text-xs\">\n {cliCommand}\n </code>\n <CopyButton value={cliCommand} label=\"Copy CLI command\" />\n </div>\n </section>\n ) : null}\n <ScheduleEditor\n id=\"operation-schedule\"\n value={input}\n onChange={(timing) => setInput({ ...input, ...timing })}\n cronSuggestions={suggestions}\n timezoneSuggestions={[input.timezone, \"UTC\"]}\n />\n {error ? (\n <InlineError title=\"Schedule action failed\" error={error} />\n ) : null}\n </div>\n </Modal>\n <Modal\n open={confirmingRun}\n onClose={() => setConfirmingRun(false)}\n title={`Run ${operationLabel(operation)} now?`}\n size=\"sm\"\n footer={\n <div className=\"flex w-full justify-end gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => setConfirmingRun(false)}\n >\n Cancel\n </Button>\n <Button\n type=\"button\"\n variant={destructive ? \"destructive\" : \"default\"}\n loading={pending === \"run\"}\n onClick={run}\n >\n Run now\n </Button>\n </div>\n }\n >\n <p className=\"text-sm text-muted-foreground\">\n This runs the configured operation once without creating or changing a\n recurring schedule.\n </p>\n <p className=\"mt-2 text-sm\">\n {targetLabel}: {input.targets.join(\", \")}\n {multiTarget ? ` (${concurrency} at once)` : \"\"}\n </p>\n </Modal>\n </>\n );\n}\n"],"names":["useState","newOperationScheduleInput","useEffect","scheduleToInput","operationByID","operationCLICommand","operationLabel","_d","_c","_b","_a","jsxs","Fragment","jsx","Modal","Button","Field","Combobox","InputField","OperationPicker","OperationArgsForm","CopyButton","ScheduleEditor","InlineError"],"mappings":"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"}
@@ -1,7 +1,10 @@
1
1
  import { ComboboxOption } from '../components/combobox-types.js';
2
2
  import { OperationSchedule, OperationScheduleCLI, OperationScheduleInput, OperationScheduleRunInput } from './operation-schedule-types.js';
3
3
  import { ResolvedOperation } from './types.js';
4
+ import { OperationsApiClient } from './useOperations.js';
4
5
  export interface OperationScheduleDialogProps {
6
+ /** Client for the argument form's lookups (the operation's parameter pickers). */
7
+ client: OperationsApiClient;
5
8
  open: boolean;
6
9
  operations: readonly ResolvedOperation[];
7
10
  targetOptions: ComboboxOption[];
@@ -1 +1 @@
1
- {"version":3,"file":"OperationScheduleDialog.d.ts","sourceRoot":"","sources":["../../src/rpc/OperationScheduleDialog.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAenE,OAAO,KAAK,EACV,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,yBAAyB,EAC1B,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAIjD,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACzC,aAAa,EAAE,cAAc,EAAE,CAAC;IAChC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,GAAG,CAAC,EAAE,oBAAoB,CAAC;IAC3B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,QAAQ,EAAE,CAAC,KAAK,EAAE,yBAAyB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAClE;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,4BAA4B,+BAuP3E"}
1
+ {"version":3,"file":"OperationScheduleDialog.d.ts","sourceRoot":"","sources":["../../src/rpc/OperationScheduleDialog.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAanE,OAAO,KAAK,EACV,iBAAiB,EACjB,oBAAoB,EACpB,sBAAsB,EACtB,yBAAyB,EAC1B,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAK3D,MAAM,WAAW,4BAA4B;IAC3C,kFAAkF;IAClF,MAAM,EAAE,mBAAmB,CAAC;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACzC,aAAa,EAAE,cAAc,EAAE,CAAC;IAChC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,GAAG,CAAC,EAAE,oBAAoB,CAAC;IAC3B,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,QAAQ,EAAE,CAAC,KAAK,EAAE,yBAAyB,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAClE;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,4BAA4B,+BA2S3E"}