@asteby/metacore-runtime-react 23.8.0 → 23.9.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/CHANGELOG.md +46 -0
- package/dist/custom-stages.d.ts +96 -1
- package/dist/custom-stages.d.ts.map +1 -1
- package/dist/custom-stages.js +259 -24
- package/dist/dynamic-form-schema.d.ts +18 -1
- package/dist/dynamic-form-schema.d.ts.map +1 -1
- package/dist/dynamic-form-schema.js +43 -0
- package/dist/dynamic-form.d.ts.map +1 -1
- package/dist/dynamic-form.js +30 -9
- package/dist/dynamic-kanban.d.ts +8 -0
- package/dist/dynamic-kanban.d.ts.map +1 -1
- package/dist/dynamic-kanban.js +188 -16
- package/dist/dynamic-line-items.d.ts.map +1 -1
- package/dist/dynamic-line-items.js +24 -3
- package/dist/dynamic-table.d.ts.map +1 -1
- package/dist/dynamic-table.js +5 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/stage-overrides.d.ts +25 -0
- package/dist/stage-overrides.d.ts.map +1 -0
- package/dist/stage-overrides.js +64 -0
- package/dist/types.d.ts +69 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/dependent-enum-form.test.tsx +84 -0
- package/src/__tests__/dependent-enum-options.test.ts +67 -0
- package/src/__tests__/dynamic-kanban.test.tsx +75 -0
- package/src/__tests__/stage-overrides.test.tsx +293 -0
- package/src/custom-stages.tsx +716 -109
- package/src/dynamic-form-schema.ts +44 -1
- package/src/dynamic-form.tsx +76 -28
- package/src/dynamic-kanban.tsx +236 -25
- package/src/dynamic-line-items.tsx +26 -2
- package/src/dynamic-table.tsx +4 -0
- package/src/index.ts +13 -0
- package/src/stage-overrides.ts +95 -0
- package/src/types.ts +63 -1
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,SAAS,CAAA;AACvB,cAAc,mBAAmB,CAAA;AACjC,cAAc,iBAAiB,CAAA;AAC/B,OAAO,EACH,aAAa,EACb,KAAK,kBAAkB,EACvB,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,GAClB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACH,mBAAmB,EACnB,sBAAsB,EACtB,WAAW,EACX,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,GACnC,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,eAAe,EACf,sBAAsB,EACtB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,SAAS,EACT,mBAAmB,EACnB,uBAAuB,EACvB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -8,8 +8,9 @@ export * from './options-context';
|
|
|
8
8
|
export * from './dynamic-table';
|
|
9
9
|
export { DynamicKanban, deriveStages, groupByStage, isTransitionAllowed, applyOptimisticMove, selectCardColumns, UNASSIGNED_LANE, } from './dynamic-kanban';
|
|
10
10
|
export { useStageAutomations, StageAutomationsButton, isTagColumn, automationFieldOptions, groupAutomationsByStage, activeAutomationCount, } from './stage-automations';
|
|
11
|
-
export { useCustomStages, splitCustomStages, mergeLaneStages, resolveSmartLanes, smartLaneParams, customStageFilterFields, isCustomStageDraftValid, slugifyStageKey, emptyCustomStageFilter, AddStageColumn, CustomStageLaneMenu, CustomStageDialog, CustomStageDeleteDialog, SmartLane, CUSTOM_STAGE_COLORS, CUSTOM_STAGE_FILTER_OPS, } from './custom-stages';
|
|
11
|
+
export { useCustomStages, splitCustomStages, mergeLaneStages, resolveSmartLanes, smartLaneParams, cardMatchesStageFilters, customStageFilterFields, isCustomStageDraftValid, slugifyStageKey, emptyCustomStageFilter, AddStageColumn, CustomStageLaneMenu, CustomStageDialog, CustomStageDeleteDialog, StageConditionBuilder, StageConfigDialog, stageFilterOpSymbol, SmartLane, CUSTOM_STAGE_COLORS, CUSTOM_STAGE_FILTER_OPS, } from './custom-stages';
|
|
12
12
|
export { useStageLayout, } from './stage-layout';
|
|
13
|
+
export { useStageOverrides, } from './stage-overrides';
|
|
13
14
|
export { DynamicView, resolveViewRenderer, readViewFromSearch, resolveActiveView, } from './dynamic-view';
|
|
14
15
|
export { useDynamicFilters, } from './use-dynamic-filters';
|
|
15
16
|
export * from './dynamic-form';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { CustomStageFilter } from './custom-stages';
|
|
2
|
+
/** Fields a stage override can carry. All optional — send only what changed. */
|
|
3
|
+
export interface StageOverridePatch {
|
|
4
|
+
label?: string;
|
|
5
|
+
color?: string;
|
|
6
|
+
/** Extra lane conditions (same shape/ops as smart-lane filters). */
|
|
7
|
+
filters?: CustomStageFilter[];
|
|
8
|
+
}
|
|
9
|
+
export interface UseStageOverridesResult {
|
|
10
|
+
/** True only after a successful GET — gates the per-lane gear on declared stages. */
|
|
11
|
+
available: boolean;
|
|
12
|
+
/** Upsert a declared lane's override (label/color/conditions). Throws on failure. */
|
|
13
|
+
save: (stageKey: string, patch: StageOverridePatch) => Promise<void>;
|
|
14
|
+
/** Reset a declared lane to its manifest default (drops the stored override). */
|
|
15
|
+
reset: (stageKey: string) => Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Learns whether the host wired `/stage-overrides` (so the gear can appear on
|
|
19
|
+
* declared lanes) and exposes save/reset. A missing endpoint degrades to
|
|
20
|
+
* `available: false`; a real save/reset failure re-throws so the caller can
|
|
21
|
+
* surface an error + revert. The overridden VALUES themselves are read off
|
|
22
|
+
* `metadata.stages` (the kernel applies them), so this hook doesn't cache a list.
|
|
23
|
+
*/
|
|
24
|
+
export declare function useStageOverrides(model: string): UseStageOverridesResult;
|
|
25
|
+
//# sourceMappingURL=stage-overrides.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stage-overrides.d.ts","sourceRoot":"","sources":["../src/stage-overrides.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAExD,gFAAgF;AAChF,MAAM,WAAW,kBAAkB;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,oEAAoE;IACpE,OAAO,CAAC,EAAE,iBAAiB,EAAE,CAAA;CAChC;AAED,MAAM,WAAW,uBAAuB;IACpC,qFAAqF;IACrF,SAAS,EAAE,OAAO,CAAA;IAClB,qFAAqF;IACrF,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACpE,iFAAiF;IACjF,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7C;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,uBAAuB,CA8CxE"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Stage overrides — per-org customization of a model's DECLARED kanban lanes
|
|
2
|
+
// (Backlog, Done, …). A user can rename a lane, recolor it, and attach extra
|
|
3
|
+
// "conditions" (a field/operator/value builder) that narrow which cards the lane
|
|
4
|
+
// shows and counts — all without touching the addon manifest. The chosen values
|
|
5
|
+
// are stored server-side and the kernel serves each declared stage already
|
|
6
|
+
// carrying the overridden label/color (+ an `overridden` flag and the extra
|
|
7
|
+
// `filters`), so the board paints them straight from `metadata.stages`.
|
|
8
|
+
//
|
|
9
|
+
// Custom stages (`custom: true`) are NOT edited here — they keep their own CRUD
|
|
10
|
+
// (`/custom-stages`); this hook only owns the DECLARED-lane overrides.
|
|
11
|
+
//
|
|
12
|
+
// Non-intrusive by design: mirrors `useStageLayout`. If the host wires no
|
|
13
|
+
// `/stage-overrides` endpoint, the GET 404s, `available` stays false, and the
|
|
14
|
+
// per-lane gear (⚙) simply never renders on declared stages — the kanban keeps
|
|
15
|
+
// working untouched.
|
|
16
|
+
//
|
|
17
|
+
// Contract (matches the ops backend; envelope is {success, data} → read .data):
|
|
18
|
+
// GET /stage-overrides?model=<m> → [{ stage_key, label?, color?, filters? }] | null
|
|
19
|
+
// PUT /stage-overrides { model, stage_key, label?, color?, filters? } (upsert)
|
|
20
|
+
// DELETE /stage-overrides?model=<m>&stage_key=<k> → reset the lane to its declared default
|
|
21
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
22
|
+
import { useApi } from './api-context';
|
|
23
|
+
/**
|
|
24
|
+
* Learns whether the host wired `/stage-overrides` (so the gear can appear on
|
|
25
|
+
* declared lanes) and exposes save/reset. A missing endpoint degrades to
|
|
26
|
+
* `available: false`; a real save/reset failure re-throws so the caller can
|
|
27
|
+
* surface an error + revert. The overridden VALUES themselves are read off
|
|
28
|
+
* `metadata.stages` (the kernel applies them), so this hook doesn't cache a list.
|
|
29
|
+
*/
|
|
30
|
+
export function useStageOverrides(model) {
|
|
31
|
+
const api = useApi();
|
|
32
|
+
const [available, setAvailable] = useState(false);
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
let cancelled = false;
|
|
35
|
+
api
|
|
36
|
+
.get(`/stage-overrides?model=${encodeURIComponent(model)}`)
|
|
37
|
+
.then(() => {
|
|
38
|
+
if (!cancelled)
|
|
39
|
+
setAvailable(true);
|
|
40
|
+
})
|
|
41
|
+
.catch(() => {
|
|
42
|
+
// Endpoint absent or errored — leave the gear off on declared lanes.
|
|
43
|
+
if (!cancelled)
|
|
44
|
+
setAvailable(false);
|
|
45
|
+
});
|
|
46
|
+
return () => {
|
|
47
|
+
cancelled = true;
|
|
48
|
+
};
|
|
49
|
+
}, [api, model]);
|
|
50
|
+
const save = useCallback(async (stageKey, patch) => {
|
|
51
|
+
const res = (await api.put('/stage-overrides', {
|
|
52
|
+
model,
|
|
53
|
+
stage_key: stageKey,
|
|
54
|
+
...patch,
|
|
55
|
+
}));
|
|
56
|
+
if (res?.data && res.data.success === false) {
|
|
57
|
+
throw new Error(res.data.message || 'stage_override_save_failed');
|
|
58
|
+
}
|
|
59
|
+
}, [api, model]);
|
|
60
|
+
const reset = useCallback(async (stageKey) => {
|
|
61
|
+
await api.delete(`/stage-overrides?model=${encodeURIComponent(model)}&stage_key=${encodeURIComponent(stageKey)}`);
|
|
62
|
+
}, [api, model]);
|
|
63
|
+
return { available, save, reset };
|
|
64
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -73,6 +73,42 @@ export interface StageMeta {
|
|
|
73
73
|
* Editar/Eliminar menu on it.
|
|
74
74
|
*/
|
|
75
75
|
custom?: boolean;
|
|
76
|
+
/**
|
|
77
|
+
* True when a per-org stage override (label/color/conditions) has been
|
|
78
|
+
* applied to this DECLARED lane (ops stage-overrides). The kernel serves the
|
|
79
|
+
* lane already carrying the overridden label/color; this flag only drives the
|
|
80
|
+
* "Restablecer etapa" affordance in the config dialog. Absent on hosts without
|
|
81
|
+
* stage overrides — purely additive.
|
|
82
|
+
*/
|
|
83
|
+
overridden?: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Extra per-lane conditions layered on top of the stage's own `group_by`
|
|
86
|
+
* scope (ops stage-overrides). When present the lane queries its data — and
|
|
87
|
+
* counts its header — with the stage filter PLUS these conditions (serialized
|
|
88
|
+
* the same way as smart-lane filters). The lane stays a normal drop target;
|
|
89
|
+
* dropping a card only sets the stage value. Absent → the lane behaves as a
|
|
90
|
+
* plain declared stage. Snake_case ops as the kernel serves them.
|
|
91
|
+
*/
|
|
92
|
+
filters?: {
|
|
93
|
+
field: string;
|
|
94
|
+
op: string;
|
|
95
|
+
value: string;
|
|
96
|
+
}[];
|
|
97
|
+
/**
|
|
98
|
+
* The manifest ORIGINAL (pre-override) label/color/conditions, served
|
|
99
|
+
* alongside an overridden declared lane so the "Restablecer al original"
|
|
100
|
+
* confirm can spell out exactly what reverts. Optional — hosts that don't
|
|
101
|
+
* snapshot the original simply omit it and the SDK shows a generic confirm.
|
|
102
|
+
*/
|
|
103
|
+
original?: {
|
|
104
|
+
label?: string;
|
|
105
|
+
color?: string;
|
|
106
|
+
filters?: {
|
|
107
|
+
field: string;
|
|
108
|
+
op: string;
|
|
109
|
+
value: string;
|
|
110
|
+
}[];
|
|
111
|
+
};
|
|
76
112
|
}
|
|
77
113
|
/**
|
|
78
114
|
* A virtual "smart" lane (ops #704) served in `TableMetadata.smart_lanes`. It's
|
|
@@ -251,15 +287,44 @@ export interface FieldValidation {
|
|
|
251
287
|
custom?: string;
|
|
252
288
|
}
|
|
253
289
|
export type FieldWidget = 'text' | 'textarea' | 'richtext' | 'color' | 'number' | 'date' | 'select' | 'dynamic_select' | 'switch' | 'upload';
|
|
290
|
+
/**
|
|
291
|
+
* Per-option visibility gate for a STATIC enum (`options[]`). The option is only
|
|
292
|
+
* offered when the value of a sibling field (`field`, defaulting to the
|
|
293
|
+
* containing field's `dependsOn`) passes: value ∈ `in` and value ∉ `notIn`.
|
|
294
|
+
* Comparison is by string. Mirrors the kernel v3 `option.when` block; the SDK
|
|
295
|
+
* tolerates both the snake_case (`not_in`) the kernel serves and camelCase.
|
|
296
|
+
* An option WITHOUT a `when` always applies (retrocompat).
|
|
297
|
+
*/
|
|
298
|
+
export interface OptionWhen {
|
|
299
|
+
/** Sibling field whose value gates this option. Falls back to `dependsOn`. */
|
|
300
|
+
field?: string;
|
|
301
|
+
/** The option applies when the gating field's value is in this list. */
|
|
302
|
+
in?: string[];
|
|
303
|
+
/** The option applies when the gating field's value is NOT in this list. */
|
|
304
|
+
notIn?: string[];
|
|
305
|
+
/** snake_case alias served by the kernel manifest for `notIn`. */
|
|
306
|
+
not_in?: string[];
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* A single static enum option. `value`/`label` are the core pair; `icon`,
|
|
310
|
+
* `color` and `image` drive the option's leading visual where the renderer
|
|
311
|
+
* supports it. `when` gates the option's visibility by a sibling field's value
|
|
312
|
+
* (see {@link OptionWhen}) — used for dependent/cascading STATIC enums.
|
|
313
|
+
*/
|
|
314
|
+
export interface OptionDef {
|
|
315
|
+
value: string;
|
|
316
|
+
label: string;
|
|
317
|
+
icon?: string;
|
|
318
|
+
color?: string;
|
|
319
|
+
image?: string;
|
|
320
|
+
when?: OptionWhen;
|
|
321
|
+
}
|
|
254
322
|
export interface ActionFieldDef {
|
|
255
323
|
key: string;
|
|
256
324
|
label: string;
|
|
257
325
|
type: string;
|
|
258
326
|
required?: boolean;
|
|
259
|
-
options?:
|
|
260
|
-
value: string;
|
|
261
|
-
label: string;
|
|
262
|
-
}[];
|
|
327
|
+
options?: OptionDef[];
|
|
263
328
|
defaultValue?: any;
|
|
264
329
|
placeholder?: string;
|
|
265
330
|
searchEndpoint?: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,gBAAgB,EAAE,CAAA;IAC3B,OAAO,EAAE,gBAAgB,EAAE,CAAA;IAC3B,OAAO,CAAC,EAAE,gBAAgB,EAAE,CAAA;IAC5B,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,MAAM,CAAA;IACzB,iBAAiB,EAAE,OAAO,CAAA;IAC1B,UAAU,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,YAAY,EAAE,CAAA;IAC1B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;IAC9C;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,SAAS,EAAE,CAAA;IACpB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,aAAa,EAAE,CAAA;IAC7B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,eAAe,EAAE,CAAA;CAClC;AAED;;;;;GAKG;AACH,MAAM,WAAW,SAAS;IACtB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asteby/metacore-runtime-react",
|
|
3
|
-
"version": "23.
|
|
3
|
+
"version": "23.9.1",
|
|
4
4
|
"description": "React runtime for metacore hosts — renders addon contributions dynamically",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"sonner": ">=1.7",
|
|
39
39
|
"zustand": ">=5",
|
|
40
40
|
"@asteby/metacore-sdk": "^3.2.0",
|
|
41
|
-
"@asteby/metacore-ui": "^2.9.
|
|
41
|
+
"@asteby/metacore-ui": "^2.9.2"
|
|
42
42
|
},
|
|
43
43
|
"peerDependenciesMeta": {
|
|
44
44
|
"@tanstack/react-router": {
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"vitest": "^4.0.0",
|
|
69
69
|
"zustand": "^5.0.0",
|
|
70
70
|
"@asteby/metacore-sdk": "3.2.0",
|
|
71
|
-
"@asteby/metacore-ui": "2.9.
|
|
71
|
+
"@asteby/metacore-ui": "2.9.2"
|
|
72
72
|
},
|
|
73
73
|
"scripts": {
|
|
74
74
|
"build": "tsc -p tsconfig.json",
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
//
|
|
3
|
+
// Dependent STATIC enum options in DynamicForm:
|
|
4
|
+
// - a static `select` whose options are gated by a sibling field's value
|
|
5
|
+
// shows only the applicable options;
|
|
6
|
+
// - when the sibling value invalidates the current selection, it resets;
|
|
7
|
+
// - when no option applies, the whole field (label included) is hidden.
|
|
8
|
+
//
|
|
9
|
+
// The gating (parent) field here is a plain text field rather than a second
|
|
10
|
+
// Radix `select`. That is deliberate: under happy-dom a Radix Select rendered
|
|
11
|
+
// inside a <form> mounts a hidden native <select> (BubbleSelect) whose value,
|
|
12
|
+
// when set programmatically before its <option> list is present, collapses to
|
|
13
|
+
// '' and dispatches a spurious change event that resets the parent — a
|
|
14
|
+
// test-environment artifact that does not occur in a real browser. Driving the
|
|
15
|
+
// sibling through a text field exercises the exact same gating path
|
|
16
|
+
// (`applyOptionWhen` reads `values[gate]` regardless of the sibling's widget)
|
|
17
|
+
// without that artifact. The pure string-comparison semantics of `when`
|
|
18
|
+
// (in/not_in, field fallback) are covered by dependent-enum-options.test.ts.
|
|
19
|
+
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
20
|
+
import { act, cleanup, render, screen } from '@testing-library/react'
|
|
21
|
+
import { useState } from 'react'
|
|
22
|
+
|
|
23
|
+
vi.mock('react-i18next', () => ({
|
|
24
|
+
useTranslation: () => ({ t: (k: string) => k }),
|
|
25
|
+
}))
|
|
26
|
+
|
|
27
|
+
import { DynamicForm } from '../dynamic-form'
|
|
28
|
+
import type { ActionFieldDef } from '../types'
|
|
29
|
+
|
|
30
|
+
afterEach(cleanup)
|
|
31
|
+
|
|
32
|
+
const fields: ActionFieldDef[] = [
|
|
33
|
+
{
|
|
34
|
+
key: 'type',
|
|
35
|
+
label: 'Type',
|
|
36
|
+
type: 'text',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
key: 'provider',
|
|
40
|
+
label: 'Provider',
|
|
41
|
+
type: 'select',
|
|
42
|
+
dependsOn: 'type',
|
|
43
|
+
options: [
|
|
44
|
+
{ value: 'qr', label: 'QR', when: { field: 'type', in: ['whatsapp'] } },
|
|
45
|
+
{ value: 'meta', label: 'Meta', when: { field: 'type', in: ['whatsapp'] } },
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
// Harness that lets the test drive `type` and observe the submitted `provider`.
|
|
51
|
+
function Harness({ onSubmit }: { onSubmit: (v: Record<string, any>) => void }) {
|
|
52
|
+
const [initial, setInitial] = useState<Record<string, any>>({ type: 'whatsapp', provider: 'qr' })
|
|
53
|
+
return (
|
|
54
|
+
<div>
|
|
55
|
+
<button type="button" onClick={() => setInitial({ type: 'sms', provider: 'qr' })}>
|
|
56
|
+
to-sms
|
|
57
|
+
</button>
|
|
58
|
+
<DynamicForm fields={fields} initialValues={initial} onSubmit={onSubmit} />
|
|
59
|
+
</div>
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
describe('DynamicForm dependent static enum', () => {
|
|
64
|
+
it('hides the gated select and resets its value when no option applies', async () => {
|
|
65
|
+
const onSubmit = vi.fn()
|
|
66
|
+
render(<Harness onSubmit={onSubmit} />)
|
|
67
|
+
|
|
68
|
+
// type=whatsapp → provider field visible.
|
|
69
|
+
expect(screen.getByText('Provider')).toBeTruthy()
|
|
70
|
+
|
|
71
|
+
// Switch type to sms → no provider option applies → field hidden.
|
|
72
|
+
await act(async () => {
|
|
73
|
+
screen.getByText('to-sms').click()
|
|
74
|
+
})
|
|
75
|
+
expect(screen.queryByText('Provider')).toBeNull()
|
|
76
|
+
|
|
77
|
+
// The invalidated selection was reset — submit carries empty provider.
|
|
78
|
+
await act(async () => {
|
|
79
|
+
screen.getByText('Guardar').click()
|
|
80
|
+
})
|
|
81
|
+
expect(onSubmit).toHaveBeenCalled()
|
|
82
|
+
expect(onSubmit.mock.calls[0][0].provider).toBe('')
|
|
83
|
+
})
|
|
84
|
+
})
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { applyOptionWhen } from '../dynamic-form-schema'
|
|
3
|
+
import type { OptionDef } from '../types'
|
|
4
|
+
|
|
5
|
+
// A cascading STATIC enum: `provider` options only apply when the sibling
|
|
6
|
+
// `type` field is "whatsapp". Mirrors the link-inbox Device use case, but the
|
|
7
|
+
// helper is fully domain-agnostic.
|
|
8
|
+
const providerOptions: OptionDef[] = [
|
|
9
|
+
{ value: 'qr', label: 'QR', when: { field: 'type', in: ['whatsapp'] } },
|
|
10
|
+
{ value: 'meta', label: 'Meta', when: { field: 'type', in: ['whatsapp'] } },
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
describe('applyOptionWhen', () => {
|
|
14
|
+
it('keeps only options whose `when.in` matches the parent value', () => {
|
|
15
|
+
const kept = applyOptionWhen(providerOptions, { type: 'whatsapp' })
|
|
16
|
+
expect(kept.map((o) => o.value)).toEqual(['qr', 'meta'])
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
it('drops all gated options when the parent value is not in `in`', () => {
|
|
20
|
+
expect(applyOptionWhen(providerOptions, { type: 'sms' })).toEqual([])
|
|
21
|
+
expect(applyOptionWhen(providerOptions, { type: '' })).toEqual([])
|
|
22
|
+
expect(applyOptionWhen(providerOptions, {})).toEqual([])
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('falls back to `dependsOn` when `when.field` is omitted', () => {
|
|
26
|
+
const opts: OptionDef[] = [
|
|
27
|
+
{ value: 'a', label: 'A', when: { in: ['x'] } },
|
|
28
|
+
{ value: 'b', label: 'B', when: { in: ['y'] } },
|
|
29
|
+
]
|
|
30
|
+
expect(applyOptionWhen(opts, { kind: 'x' }, 'kind').map((o) => o.value)).toEqual(['a'])
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('supports `not_in` (snake_case) and `notIn` (camelCase)', () => {
|
|
34
|
+
const opts: OptionDef[] = [
|
|
35
|
+
{ value: 'a', label: 'A', when: { field: 'type', not_in: ['hidden'] } },
|
|
36
|
+
{ value: 'b', label: 'B', when: { field: 'type', notIn: ['hidden'] } },
|
|
37
|
+
]
|
|
38
|
+
expect(applyOptionWhen(opts, { type: 'shown' }).map((o) => o.value)).toEqual(['a', 'b'])
|
|
39
|
+
expect(applyOptionWhen(opts, { type: 'hidden' })).toEqual([])
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
it('compares values as strings', () => {
|
|
43
|
+
const opts: OptionDef[] = [{ value: 'a', label: 'A', when: { field: 'n', in: ['1'] } }]
|
|
44
|
+
expect(applyOptionWhen(opts, { n: 1 }).map((o) => o.value)).toEqual(['a'])
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('includes an option with no `when` regardless of parent value (retrocompat)', () => {
|
|
48
|
+
const opts: OptionDef[] = [
|
|
49
|
+
{ value: 'always', label: 'Always' },
|
|
50
|
+
{ value: 'gated', label: 'Gated', when: { field: 'type', in: ['whatsapp'] } },
|
|
51
|
+
]
|
|
52
|
+
expect(applyOptionWhen(opts, { type: 'sms' }).map((o) => o.value)).toEqual(['always'])
|
|
53
|
+
expect(applyOptionWhen(opts, { type: 'whatsapp' }).map((o) => o.value)).toEqual([
|
|
54
|
+
'always',
|
|
55
|
+
'gated',
|
|
56
|
+
])
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('includes a gated option when neither `when.field` nor `dependsOn` is present', () => {
|
|
60
|
+
const opts: OptionDef[] = [{ value: 'a', label: 'A', when: { in: ['x'] } }]
|
|
61
|
+
expect(applyOptionWhen(opts, { anything: 'x' }).map((o) => o.value)).toEqual(['a'])
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it('returns [] for undefined options', () => {
|
|
65
|
+
expect(applyOptionWhen(undefined, {})).toEqual([])
|
|
66
|
+
})
|
|
67
|
+
})
|
|
@@ -495,6 +495,81 @@ describe('DynamicKanban filter bar', () => {
|
|
|
495
495
|
})
|
|
496
496
|
})
|
|
497
497
|
|
|
498
|
+
// ---------------------------------------------------------------------------
|
|
499
|
+
// Stage config gear (⚙) + stage-override conditions on a declared lane
|
|
500
|
+
// ---------------------------------------------------------------------------
|
|
501
|
+
|
|
502
|
+
describe('DynamicKanban stage config', () => {
|
|
503
|
+
it('renders the ⚙ gear on declared lanes when /stage-overrides is wired', async () => {
|
|
504
|
+
useMetadataCache.getState().setMetadata('issue', meta())
|
|
505
|
+
render(
|
|
506
|
+
<ApiProvider client={fakeApi()}>
|
|
507
|
+
<DynamicKanban model="issue" />
|
|
508
|
+
</ApiProvider>,
|
|
509
|
+
)
|
|
510
|
+
// fakeApi answers every GET ok, so /stage-overrides resolves → gear shows.
|
|
511
|
+
expect(await screen.findByTestId('lane-config-backlog')).toBeTruthy()
|
|
512
|
+
expect(screen.getByTestId('lane-config-done')).toBeTruthy()
|
|
513
|
+
})
|
|
514
|
+
|
|
515
|
+
it('hides the gear on declared lanes when /stage-overrides 404s', async () => {
|
|
516
|
+
useMetadataCache.getState().setMetadata('issue', meta())
|
|
517
|
+
const get = vi.fn(async (url: string) => {
|
|
518
|
+
if (url.startsWith('/metadata/table/'))
|
|
519
|
+
return { data: { success: true, data: meta() } }
|
|
520
|
+
if (url.startsWith('/stage-overrides'))
|
|
521
|
+
return Promise.reject(new Error('404'))
|
|
522
|
+
return { data: { success: true, data: CARDS } }
|
|
523
|
+
})
|
|
524
|
+
render(
|
|
525
|
+
<ApiProvider client={fakeApi({ get })}>
|
|
526
|
+
<DynamicKanban model="issue" />
|
|
527
|
+
</ApiProvider>,
|
|
528
|
+
)
|
|
529
|
+
await screen.findByText('Backlog')
|
|
530
|
+
await waitFor(() =>
|
|
531
|
+
expect(screen.queryByTestId('lane-config-backlog')).toBeNull(),
|
|
532
|
+
)
|
|
533
|
+
})
|
|
534
|
+
|
|
535
|
+
it('queries a lane that carries override filters with the extra f_ params + shows the conditions indicator', async () => {
|
|
536
|
+
// A declared "backlog" lane with an extra condition (priority = high).
|
|
537
|
+
const withFilters = meta({
|
|
538
|
+
stages: [
|
|
539
|
+
{ key: 'backlog', label: 'Backlog', color: 'slate', order: 0, overridden: true, filters: [{ field: 'priority', op: 'eq', value: 'high' }] },
|
|
540
|
+
{ key: 'done', label: 'Done', color: 'green', order: 1 },
|
|
541
|
+
],
|
|
542
|
+
})
|
|
543
|
+
useMetadataCache.getState().setMetadata('issue', withFilters)
|
|
544
|
+
const get = vi.fn(async (url: string) => {
|
|
545
|
+
if (url.startsWith('/metadata/table/'))
|
|
546
|
+
return { data: { success: true, data: withFilters } }
|
|
547
|
+
return { data: { success: true, data: CARDS, meta: { total: 1 } } }
|
|
548
|
+
})
|
|
549
|
+
render(
|
|
550
|
+
<ApiProvider client={fakeApi({ get })}>
|
|
551
|
+
<DynamicKanban model="issue" />
|
|
552
|
+
</ApiProvider>,
|
|
553
|
+
)
|
|
554
|
+
await screen.findByText('Backlog')
|
|
555
|
+
// The eager per-lane total request for backlog carries BOTH the stage
|
|
556
|
+
// scope and the override condition serialized like a smart-lane filter.
|
|
557
|
+
await waitFor(() =>
|
|
558
|
+
expect(get).toHaveBeenCalledWith(
|
|
559
|
+
'/data/issue',
|
|
560
|
+
expect.objectContaining({
|
|
561
|
+
params: expect.objectContaining({
|
|
562
|
+
f_stage: 'backlog',
|
|
563
|
+
f_priority: 'EQ:high',
|
|
564
|
+
}),
|
|
565
|
+
}),
|
|
566
|
+
),
|
|
567
|
+
)
|
|
568
|
+
// The header carries the conditions indicator (dot + tooltip).
|
|
569
|
+
expect(screen.getByTestId('lane-conditions-backlog')).toBeTruthy()
|
|
570
|
+
})
|
|
571
|
+
})
|
|
572
|
+
|
|
498
573
|
// ---------------------------------------------------------------------------
|
|
499
574
|
// 5. Per-lane search — the inline lane header search narrows ONLY that lane's
|
|
500
575
|
// already-fetched cards, client-side, by title + field values.
|