@nnkogift/dhis2-form-utils-devtools 0.1.0-alpha.5 → 0.1.0-alpha.6
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/dist/EffectBadge.d.ts +17 -0
- package/dist/EffectBadge.js +55 -0
- package/dist/EffectBadge.js.map +1 -0
- package/dist/RuleDetailsModal.d.ts +30 -0
- package/dist/RuleDetailsModal.js +403 -0
- package/dist/RuleDetailsModal.js.map +1 -0
- package/dist/RuleDevtoolsScope.d.ts +14 -0
- package/dist/RuleDevtoolsScope.js +25 -0
- package/dist/RuleDevtoolsScope.js.map +1 -0
- package/dist/RuleGraphModal.d.ts +17 -0
- package/dist/RuleGraphModal.js +35 -0
- package/dist/RuleGraphModal.js.map +1 -0
- package/dist/RuleGraphView.d.ts +43 -0
- package/dist/RuleGraphView.js +401 -0
- package/dist/RuleGraphView.js.map +1 -0
- package/dist/RulesPanel.d.ts +19 -0
- package/dist/RulesPanel.js +463 -0
- package/dist/RulesPanel.js.map +1 -0
- package/dist/RulesPanelGraphFallback.d.ts +5 -0
- package/dist/RulesPanelGraphFallback.js +19 -0
- package/dist/RulesPanelGraphFallback.js.map +1 -0
- package/dist/TraceTimeline.d.ts +16 -0
- package/dist/TraceTimeline.js +227 -0
- package/dist/TraceTimeline.js.map +1 -0
- package/dist/attach.d.ts +12 -0
- package/dist/attach.js +14 -0
- package/dist/attach.js.map +1 -0
- package/dist/buildGraph.d.ts +25 -0
- package/dist/buildGraph.js +67 -0
- package/dist/buildGraph.js.map +1 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.js +5 -0
- package/dist/constants.js.map +1 -0
- package/dist/createLabelLookup.d.ts +25 -0
- package/dist/createLabelLookup.js +81 -0
- package/dist/createLabelLookup.js.map +1 -0
- package/dist/effectStyles.d.ts +28 -0
- package/dist/effectStyles.js +142 -0
- package/dist/effectStyles.js.map +1 -0
- package/dist/formatAgo.d.ts +3 -0
- package/dist/formatAgo.js +25 -0
- package/dist/formatAgo.js.map +1 -0
- package/dist/formatRuleActionSummary.d.ts +33 -0
- package/dist/formatRuleActionSummary.js +61 -0
- package/dist/formatRuleActionSummary.js.map +1 -0
- package/dist/graphLayout.d.ts +48 -0
- package/dist/graphLayout.js +137 -0
- package/dist/graphLayout.js.map +1 -0
- package/dist/graphNodeStyles.d.ts +9 -0
- package/dist/graphNodeStyles.js +22 -0
- package/dist/graphNodeStyles.js.map +1 -0
- package/dist/i18n.d.ts +4 -0
- package/dist/i18n.js +9 -0
- package/dist/i18n.js.map +1 -0
- package/dist/index.cjs +1230 -1089
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.cts +12 -90
- package/dist/index.d.ts +12 -90
- package/dist/index.js +5 -2240
- package/dist/index.js.map +1 -1
- package/dist/programRuleDetailQuery.d.ts +70 -0
- package/dist/programRuleDetailQuery.js +42 -0
- package/dist/programRuleDetailQuery.js.map +1 -0
- package/dist/resolveProgramRulesList.d.ts +21 -0
- package/dist/resolveProgramRulesList.js +45 -0
- package/dist/resolveProgramRulesList.js.map +1 -0
- package/dist/traceEntry.d.ts +12 -0
- package/dist/traceEntry.js +20 -0
- package/dist/traceEntry.js.map +1 -0
- package/dist/traceStore.d.ts +12 -0
- package/dist/traceStore.js +39 -0
- package/dist/traceStore.js.map +1 -0
- package/dist/useFlipReorder.d.ts +8 -0
- package/dist/useFlipReorder.js +52 -0
- package/dist/useFlipReorder.js.map +1 -0
- package/dist/useProgramRuleDetail.d.ts +17 -0
- package/dist/useProgramRuleDetail.js +30 -0
- package/dist/useProgramRuleDetail.js.map +1 -0
- package/package.json +24 -4
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { EffectVisualVariant } from './effectStyles.js';
|
|
4
|
+
import '@dhis2/ui';
|
|
5
|
+
|
|
6
|
+
type EffectBadgeProps = {
|
|
7
|
+
type: string;
|
|
8
|
+
children?: ReactNode;
|
|
9
|
+
className?: string;
|
|
10
|
+
};
|
|
11
|
+
declare function EffectBadge({ type, children, className }: EffectBadgeProps): react_jsx_runtime.JSX.Element;
|
|
12
|
+
type EffectLegendProps = {
|
|
13
|
+
activeVariants: ReadonlySet<EffectVisualVariant>;
|
|
14
|
+
};
|
|
15
|
+
declare function EffectLegend({ activeVariants }: EffectLegendProps): react_jsx_runtime.JSX.Element | null;
|
|
16
|
+
|
|
17
|
+
export { EffectBadge, type EffectBadgeProps, EffectLegend, type EffectLegendProps };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Tag } from '@dhis2/ui';
|
|
3
|
+
import { getEffectVariant, EFFECT_ICONS, getEffectTagRenderProps, getEffectTagRenderPropsForVariant } from './effectStyles.js';
|
|
4
|
+
import { translate } from './i18n.js';
|
|
5
|
+
|
|
6
|
+
function EffectBadge({ type, children, className = "" }) {
|
|
7
|
+
const variant = getEffectVariant(type);
|
|
8
|
+
const Icon = EFFECT_ICONS[variant];
|
|
9
|
+
const tagProps = getEffectTagRenderProps(type);
|
|
10
|
+
const label = children ?? type;
|
|
11
|
+
return /* @__PURE__ */ jsx(
|
|
12
|
+
Tag,
|
|
13
|
+
{
|
|
14
|
+
...tagProps,
|
|
15
|
+
icon: /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" }),
|
|
16
|
+
className: [tagProps.className, className].filter(Boolean).join(" "),
|
|
17
|
+
maxWidth: "100%",
|
|
18
|
+
children: label
|
|
19
|
+
}
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
const LEGEND_VARIANTS = [
|
|
23
|
+
{ variant: "read", label: translate("Read") },
|
|
24
|
+
{ variant: "hide", label: translate("Hide") },
|
|
25
|
+
{ variant: "show", label: translate("Show") },
|
|
26
|
+
{ variant: "assign", label: translate("Assign") },
|
|
27
|
+
{ variant: "mandatory", label: translate("Required") },
|
|
28
|
+
{ variant: "warning", label: translate("Warning") },
|
|
29
|
+
{ variant: "error", label: translate("Error") },
|
|
30
|
+
{ variant: "feedback", label: translate("Feedback") }
|
|
31
|
+
];
|
|
32
|
+
function EffectLegend({ activeVariants }) {
|
|
33
|
+
const items = LEGEND_VARIANTS.filter((item) => activeVariants.has(item.variant));
|
|
34
|
+
if (!items.length) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
return /* @__PURE__ */ jsx("div", { className: "flex min-w-0 flex-wrap items-center gap-dp8 border-t border-dhis2-grey-200 px-dp12 py-dp8", children: items.map((item) => {
|
|
38
|
+
const Icon = EFFECT_ICONS[item.variant];
|
|
39
|
+
const tagProps = getEffectTagRenderPropsForVariant(item.variant);
|
|
40
|
+
return /* @__PURE__ */ jsx(
|
|
41
|
+
Tag,
|
|
42
|
+
{
|
|
43
|
+
...tagProps,
|
|
44
|
+
icon: /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" }),
|
|
45
|
+
maxWidth: "100%",
|
|
46
|
+
children: item.label
|
|
47
|
+
},
|
|
48
|
+
item.variant
|
|
49
|
+
);
|
|
50
|
+
}) });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { EffectBadge, EffectLegend };
|
|
54
|
+
//# sourceMappingURL=EffectBadge.js.map
|
|
55
|
+
//# sourceMappingURL=EffectBadge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/EffectBadge.tsx"],"names":[],"mappings":";;;;;AAiBO,SAAS,YAAY,EAAE,IAAA,EAAM,QAAA,EAAU,SAAA,GAAY,IAAG,EAAqB;AAC9E,EAAA,MAAM,OAAA,GAAU,iBAAiB,IAAI,CAAA;AACrC,EAAA,MAAM,IAAA,GAAO,aAAa,OAAO,CAAA;AACjC,EAAA,MAAM,QAAA,GAAW,wBAAwB,IAAI,CAAA;AAC7C,EAAA,MAAM,QAAQ,QAAA,IAAY,IAAA;AAE1B,EAAA,uBACI,GAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACI,GAAG,QAAA;AAAA,MACJ,IAAA,kBAAM,GAAA,CAAC,IAAA,EAAA,EAAK,aAAA,EAAY,MAAA,EAAO,CAAA;AAAA,MAC/B,SAAA,EAAW,CAAC,QAAA,CAAS,SAAA,EAAW,SAAS,EAAE,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA,CAAK,GAAG,CAAA;AAAA,MACnE,QAAA,EAAS,MAAA;AAAA,MAER,QAAA,EAAA;AAAA;AAAA,GACL;AAER;AAEA,MAAM,eAAA,GAA0E;AAAA,EAC5E,EAAE,OAAA,EAAS,MAAA,EAAQ,KAAA,EAAO,SAAA,CAAU,MAAM,CAAA,EAAE;AAAA,EAC5C,EAAE,OAAA,EAAS,MAAA,EAAQ,KAAA,EAAO,SAAA,CAAU,MAAM,CAAA,EAAE;AAAA,EAC5C,EAAE,OAAA,EAAS,MAAA,EAAQ,KAAA,EAAO,SAAA,CAAU,MAAM,CAAA,EAAE;AAAA,EAC5C,EAAE,OAAA,EAAS,QAAA,EAAU,KAAA,EAAO,SAAA,CAAU,QAAQ,CAAA,EAAE;AAAA,EAChD,EAAE,OAAA,EAAS,WAAA,EAAa,KAAA,EAAO,SAAA,CAAU,UAAU,CAAA,EAAE;AAAA,EACrD,EAAE,OAAA,EAAS,SAAA,EAAW,KAAA,EAAO,SAAA,CAAU,SAAS,CAAA,EAAE;AAAA,EAClD,EAAE,OAAA,EAAS,OAAA,EAAS,KAAA,EAAO,SAAA,CAAU,OAAO,CAAA,EAAE;AAAA,EAC9C,EAAE,OAAA,EAAS,UAAA,EAAY,KAAA,EAAO,SAAA,CAAU,UAAU,CAAA;AACtD,CAAA;AAMO,SAAS,YAAA,CAAa,EAAE,cAAA,EAAe,EAAsB;AAChE,EAAA,MAAM,KAAA,GAAQ,gBAAgB,MAAA,CAAO,CAAC,SAAS,cAAA,CAAe,GAAA,CAAI,IAAA,CAAK,OAAO,CAAC,CAAA;AAE/E,EAAA,IAAI,CAAC,MAAM,MAAA,EAAQ;AACf,IAAA,OAAO,IAAA;AAAA,EACX;AAEA,EAAA,2BACK,KAAA,EAAA,EAAI,SAAA,EAAU,6FACV,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAC,IAAA,KAAS;AACjB,IAAA,MAAM,IAAA,GAAO,YAAA,CAAa,IAAA,CAAK,OAAO,CAAA;AACtC,IAAA,MAAM,QAAA,GAAW,iCAAA,CAAkC,IAAA,CAAK,OAAO,CAAA;AAE/D,IAAA,uBACI,GAAA;AAAA,MAAC,GAAA;AAAA,MAAA;AAAA,QAEI,GAAG,QAAA;AAAA,QACJ,IAAA,kBAAM,GAAA,CAAC,IAAA,EAAA,EAAK,aAAA,EAAY,MAAA,EAAO,CAAA;AAAA,QAC/B,QAAA,EAAS,MAAA;AAAA,QAER,QAAA,EAAA,IAAA,CAAK;AAAA,OAAA;AAAA,MALD,IAAA,CAAK;AAAA,KAMd;AAAA,EAER,CAAC,CAAA,EACL,CAAA;AAER","file":"EffectBadge.js","sourcesContent":["import { Tag } from '@dhis2/ui';\nimport type { ReactNode } from 'react';\nimport {\n EFFECT_ICONS,\n getEffectTagRenderProps,\n getEffectTagRenderPropsForVariant,\n getEffectVariant,\n type EffectVisualVariant,\n} from './effectStyles.js';\nimport { translate } from './i18n.js';\n\nexport type EffectBadgeProps = {\n type: string;\n children?: ReactNode;\n className?: string;\n};\n\nexport function EffectBadge({ type, children, className = '' }: EffectBadgeProps) {\n const variant = getEffectVariant(type);\n const Icon = EFFECT_ICONS[variant];\n const tagProps = getEffectTagRenderProps(type);\n const label = children ?? type;\n\n return (\n <Tag\n {...tagProps}\n icon={<Icon aria-hidden=\"true\" />}\n className={[tagProps.className, className].filter(Boolean).join(' ')}\n maxWidth=\"100%\"\n >\n {label}\n </Tag>\n );\n}\n\nconst LEGEND_VARIANTS: Array<{ variant: EffectVisualVariant; label: string }> = [\n { variant: 'read', label: translate('Read') },\n { variant: 'hide', label: translate('Hide') },\n { variant: 'show', label: translate('Show') },\n { variant: 'assign', label: translate('Assign') },\n { variant: 'mandatory', label: translate('Required') },\n { variant: 'warning', label: translate('Warning') },\n { variant: 'error', label: translate('Error') },\n { variant: 'feedback', label: translate('Feedback') },\n];\n\nexport type EffectLegendProps = {\n activeVariants: ReadonlySet<EffectVisualVariant>;\n};\n\nexport function EffectLegend({ activeVariants }: EffectLegendProps) {\n const items = LEGEND_VARIANTS.filter((item) => activeVariants.has(item.variant));\n\n if (!items.length) {\n return null;\n }\n\n return (\n <div className=\"flex min-w-0 flex-wrap items-center gap-dp8 border-t border-dhis2-grey-200 px-dp12 py-dp8\">\n {items.map((item) => {\n const Icon = EFFECT_ICONS[item.variant];\n const tagProps = getEffectTagRenderPropsForVariant(item.variant);\n\n return (\n <Tag\n key={item.variant}\n {...tagProps}\n icon={<Icon aria-hidden=\"true\" />}\n maxWidth=\"100%\"\n >\n {item.label}\n </Tag>\n );\n })}\n </div>\n );\n}\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
type RuleDetailsStatus = 'firing' | 'idle' | 'out-of-scope';
|
|
4
|
+
/**
|
|
5
|
+
* Structural subset of `ProgramRuleVariable` (event) / the tracker `programRuleVariables` entry
|
|
6
|
+
* shape — those two are distinct generated types (tracker variables never carry `dataElement`),
|
|
7
|
+
* so this only asks for what condition-token resolution actually needs.
|
|
8
|
+
*/
|
|
9
|
+
type ProgramRuleVariableLike = {
|
|
10
|
+
name?: string;
|
|
11
|
+
dataElement?: {
|
|
12
|
+
displayName?: string;
|
|
13
|
+
};
|
|
14
|
+
trackedEntityAttribute?: {
|
|
15
|
+
displayName?: string;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
type RuleDetailsModalProps = {
|
|
19
|
+
open: boolean;
|
|
20
|
+
onClose: () => void;
|
|
21
|
+
ruleId: string | null;
|
|
22
|
+
/** Already known from the catalog list — shown immediately, before the detail fetch resolves. */
|
|
23
|
+
ruleName: string;
|
|
24
|
+
status: RuleDetailsStatus;
|
|
25
|
+
programStageName?: string | null;
|
|
26
|
+
programRuleVariables: readonly ProgramRuleVariableLike[];
|
|
27
|
+
};
|
|
28
|
+
declare function RuleDetailsModal({ open, onClose, ruleId, ruleName, status, programStageName, programRuleVariables, }: RuleDetailsModalProps): react_jsx_runtime.JSX.Element | null;
|
|
29
|
+
|
|
30
|
+
export { type ProgramRuleVariableLike, RuleDetailsModal, type RuleDetailsModalProps, type RuleDetailsStatus };
|
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { Modal, ModalContent, CircularLoader, ButtonStrip, Button } from '@dhis2/ui';
|
|
3
|
+
import { getEffectVisual, EFFECT_ICONS } from './effectStyles.js';
|
|
4
|
+
import { translate } from './i18n.js';
|
|
5
|
+
import { useProgramRuleDetail } from './useProgramRuleDetail.js';
|
|
6
|
+
|
|
7
|
+
const EM_DASH = "\u2014";
|
|
8
|
+
function formatTimestamp(value) {
|
|
9
|
+
if (!value) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
const date = new Date(value);
|
|
13
|
+
if (Number.isNaN(date.getTime())) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const day = String(date.getDate());
|
|
17
|
+
const month = date.toLocaleString("en-GB", { month: "short" });
|
|
18
|
+
const year = String(date.getFullYear());
|
|
19
|
+
const hours = String(date.getHours()).padStart(2, "0");
|
|
20
|
+
const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
21
|
+
return `${day} ${month} ${year} ${hours}:${minutes}`;
|
|
22
|
+
}
|
|
23
|
+
function resolveStatusChip(status) {
|
|
24
|
+
switch (status) {
|
|
25
|
+
case "firing":
|
|
26
|
+
return {
|
|
27
|
+
label: translate("Firing"),
|
|
28
|
+
className: "bg-dhis2-teal-100 text-dhis2-teal-900"
|
|
29
|
+
};
|
|
30
|
+
case "idle":
|
|
31
|
+
return { label: translate("Idle"), className: "bg-dhis2-grey-200 text-dhis2-grey-700" };
|
|
32
|
+
case "out-of-scope":
|
|
33
|
+
return {
|
|
34
|
+
label: translate("Out of scope"),
|
|
35
|
+
className: "bg-dhis2-grey-200 text-dhis2-grey-600"
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const VARIABLE_PATTERNS = [
|
|
40
|
+
{
|
|
41
|
+
pattern: /#\{[^}]*\}/g,
|
|
42
|
+
kind: "Data element",
|
|
43
|
+
className: "bg-dhis2-blue-100 text-dhis2-blue-900"
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
pattern: /A\{[^}]*\}/g,
|
|
47
|
+
kind: "Tracked entity attribute",
|
|
48
|
+
className: "bg-dhis2-teal-100 text-dhis2-teal-900"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
pattern: /V\{[^}]*\}/g,
|
|
52
|
+
kind: "Environment variable",
|
|
53
|
+
className: "bg-dhis2-grey-200 text-dhis2-grey-900"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
pattern: /d2:\w+(?=\()/g,
|
|
57
|
+
kind: "Function",
|
|
58
|
+
className: "bg-dhis2-yellow-100 text-dhis2-yellow-900"
|
|
59
|
+
}
|
|
60
|
+
];
|
|
61
|
+
const RESOLVABLE_VARIABLE_KINDS = /* @__PURE__ */ new Set([
|
|
62
|
+
"Data element",
|
|
63
|
+
"Tracked entity attribute"
|
|
64
|
+
]);
|
|
65
|
+
function resolveVariableDisplayName(name, programRuleVariables) {
|
|
66
|
+
const variable = programRuleVariables.find((candidate) => candidate.name === name);
|
|
67
|
+
return variable?.dataElement?.displayName ?? variable?.trackedEntityAttribute?.displayName;
|
|
68
|
+
}
|
|
69
|
+
function resolveVariableToken(token, kind, programRuleVariables) {
|
|
70
|
+
if (kind === "Function") {
|
|
71
|
+
return `${token}()`;
|
|
72
|
+
}
|
|
73
|
+
if (!RESOLVABLE_VARIABLE_KINDS.has(kind)) {
|
|
74
|
+
return token;
|
|
75
|
+
}
|
|
76
|
+
return resolveVariableDisplayName(token.slice(2, -1), programRuleVariables) ?? token;
|
|
77
|
+
}
|
|
78
|
+
function matchDistinctTokens(condition, pattern, seen) {
|
|
79
|
+
const matches = condition.match(pattern) ?? [];
|
|
80
|
+
const distinct = matches.filter((token) => !seen.has(token));
|
|
81
|
+
for (const token of distinct) {
|
|
82
|
+
seen.add(token);
|
|
83
|
+
}
|
|
84
|
+
return distinct;
|
|
85
|
+
}
|
|
86
|
+
function parseConditionVariables(condition, programRuleVariables) {
|
|
87
|
+
if (!condition) {
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
const seen = /* @__PURE__ */ new Set();
|
|
91
|
+
return VARIABLE_PATTERNS.flatMap(
|
|
92
|
+
({ pattern, kind, className }) => matchDistinctTokens(condition, pattern, seen).map((token) => ({
|
|
93
|
+
token,
|
|
94
|
+
kind,
|
|
95
|
+
label: resolveVariableToken(token, kind, programRuleVariables),
|
|
96
|
+
className
|
|
97
|
+
}))
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
const ACTION_TARGET_RESOLVERS = [
|
|
101
|
+
{ label: "Data element", getRef: (action) => action.dataElement },
|
|
102
|
+
{ label: "Tracked entity attribute", getRef: (action) => action.trackedEntityAttribute },
|
|
103
|
+
{ label: "Program stage section", getRef: (action) => action.programStageSection },
|
|
104
|
+
{ label: "Program stage", getRef: (action) => action.programStage },
|
|
105
|
+
{ label: "Option", getRef: (action) => action.option },
|
|
106
|
+
{ label: "Option group", getRef: (action) => action.optionGroup }
|
|
107
|
+
];
|
|
108
|
+
function formatActionTargetValue(ref) {
|
|
109
|
+
return `${ref.displayName ?? ref.id} \xB7 ${ref.id}`;
|
|
110
|
+
}
|
|
111
|
+
function resolveActionTarget(action) {
|
|
112
|
+
for (const { label, getRef } of ACTION_TARGET_RESOLVERS) {
|
|
113
|
+
const ref = getRef(action);
|
|
114
|
+
if (ref?.id) {
|
|
115
|
+
return { label: translate(label), value: formatActionTargetValue(ref) };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
function BasicDetailCell({ label, value, mono }) {
|
|
121
|
+
return /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
122
|
+
/* @__PURE__ */ jsx("p", { className: "m-0 text-xs text-dhis2-grey-600", children: label }),
|
|
123
|
+
/* @__PURE__ */ jsx("p", { className: `m-0 mt-[2px] text-sm text-dhis2-grey-900 ${mono ? "font-mono" : ""}`, children: value })
|
|
124
|
+
] });
|
|
125
|
+
}
|
|
126
|
+
const FEEDBACK_ACTION_TYPES = /* @__PURE__ */ new Set(["DISPLAYTEXT", "DISPLAYKEYVALUEPAIR"]);
|
|
127
|
+
function resolveDataRow(action) {
|
|
128
|
+
return action.data ? { label: translate("Data (expression)"), value: action.data, mono: true } : null;
|
|
129
|
+
}
|
|
130
|
+
function resolveContentRow(action) {
|
|
131
|
+
const showContent = Boolean(action.content) && FEEDBACK_ACTION_TYPES.has(action.programRuleActionType);
|
|
132
|
+
return showContent ? { label: translate("Content (static text)"), value: action.content ?? "" } : null;
|
|
133
|
+
}
|
|
134
|
+
function resolveLocationRow(action) {
|
|
135
|
+
return action.location ? { label: translate("Location"), value: action.location, mono: true } : null;
|
|
136
|
+
}
|
|
137
|
+
function resolveActionRows(action) {
|
|
138
|
+
const rows = [
|
|
139
|
+
resolveActionTarget(action),
|
|
140
|
+
resolveDataRow(action),
|
|
141
|
+
resolveContentRow(action),
|
|
142
|
+
resolveLocationRow(action)
|
|
143
|
+
];
|
|
144
|
+
return rows.filter((row) => row !== null);
|
|
145
|
+
}
|
|
146
|
+
function ActionCard({ action, index }) {
|
|
147
|
+
const type = action.programRuleActionType;
|
|
148
|
+
const visual = getEffectVisual(type);
|
|
149
|
+
const Icon = EFFECT_ICONS[visual.variant];
|
|
150
|
+
const rows = resolveActionRows(action);
|
|
151
|
+
return /* @__PURE__ */ jsxs(
|
|
152
|
+
"div",
|
|
153
|
+
{
|
|
154
|
+
className: "relative rounded-[3px] border border-dhis2-grey-300 bg-white py-dp12 pe-dp16 ps-dp16 shadow-[0_1px_2px_rgb(0_0_0/4%)]",
|
|
155
|
+
style: { borderInlineStartWidth: 3, borderInlineStartColor: visual.edgeStroke },
|
|
156
|
+
children: [
|
|
157
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-dp12 flex items-center justify-between gap-dp8", children: [
|
|
158
|
+
/* @__PURE__ */ jsxs(
|
|
159
|
+
"span",
|
|
160
|
+
{
|
|
161
|
+
className: `inline-flex items-center gap-[4px] rounded-[4px] px-dp8 py-[2px] text-xs font-semibold ${visual.tagClassName}`,
|
|
162
|
+
children: [
|
|
163
|
+
/* @__PURE__ */ jsx(Icon, {}),
|
|
164
|
+
type
|
|
165
|
+
]
|
|
166
|
+
}
|
|
167
|
+
),
|
|
168
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] uppercase tracking-wide text-dhis2-grey-600", children: translate("Action {{n}}", { n: index + 1 }) })
|
|
169
|
+
] }),
|
|
170
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-dp10", children: rows.map((row) => /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-[172px_minmax(0,1fr)] gap-dp10", children: [
|
|
171
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-dhis2-grey-600", children: row.label }),
|
|
172
|
+
/* @__PURE__ */ jsx(
|
|
173
|
+
"span",
|
|
174
|
+
{
|
|
175
|
+
className: `min-w-0 break-words text-sm ${row.mono ? "font-mono text-[12px]" : ""}`,
|
|
176
|
+
children: row.value
|
|
177
|
+
}
|
|
178
|
+
)
|
|
179
|
+
] }, row.label)) })
|
|
180
|
+
]
|
|
181
|
+
}
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
function orDash(value) {
|
|
185
|
+
return value ?? EM_DASH;
|
|
186
|
+
}
|
|
187
|
+
function resolveDetailDisplayName(rule) {
|
|
188
|
+
return rule?.displayName;
|
|
189
|
+
}
|
|
190
|
+
function resolveDetailName(rule) {
|
|
191
|
+
return rule?.name;
|
|
192
|
+
}
|
|
193
|
+
function resolveRuleDisplayName(rule, fallback) {
|
|
194
|
+
const displayName = resolveDetailDisplayName(rule) ?? resolveDetailName(rule);
|
|
195
|
+
return displayName ?? fallback;
|
|
196
|
+
}
|
|
197
|
+
function resolveRuleStageName(rule) {
|
|
198
|
+
return rule?.programStage?.displayName;
|
|
199
|
+
}
|
|
200
|
+
function resolveStageName(rule, programStageName) {
|
|
201
|
+
if (programStageName === null) {
|
|
202
|
+
return translate("All stages (registration)");
|
|
203
|
+
}
|
|
204
|
+
return orDash(resolveRuleStageName(rule) ?? programStageName);
|
|
205
|
+
}
|
|
206
|
+
function resolveLastUpdatedByName(rule) {
|
|
207
|
+
return rule?.lastUpdatedBy?.displayName;
|
|
208
|
+
}
|
|
209
|
+
function resolveLastUpdatedValue(rule) {
|
|
210
|
+
const label = formatTimestamp(rule?.lastUpdated);
|
|
211
|
+
if (!label) {
|
|
212
|
+
return EM_DASH;
|
|
213
|
+
}
|
|
214
|
+
const by = resolveLastUpdatedByName(rule);
|
|
215
|
+
return by ? `${label} \xB7 ${by}` : label;
|
|
216
|
+
}
|
|
217
|
+
function resolvePriorityCellValue(rule) {
|
|
218
|
+
return rule?.priority != null ? String(rule.priority) : EM_DASH;
|
|
219
|
+
}
|
|
220
|
+
function resolveActionsCellValue(rule) {
|
|
221
|
+
return translate("{{n}} action(s)", { n: rule?.programRuleActions?.length ?? 0 });
|
|
222
|
+
}
|
|
223
|
+
function resolveBasicDetailCells(rule, ruleName, programStageName) {
|
|
224
|
+
return [
|
|
225
|
+
{ label: translate("Name"), value: resolveRuleDisplayName(rule, ruleName) },
|
|
226
|
+
{ label: translate("Code"), value: orDash(rule?.code), mono: true },
|
|
227
|
+
{ label: translate("Identifier"), value: orDash(rule?.id), mono: true },
|
|
228
|
+
{ label: translate("Program"), value: orDash(rule?.program?.displayName) },
|
|
229
|
+
{ label: translate("Program stage"), value: resolveStageName(rule, programStageName) },
|
|
230
|
+
{ label: translate("Priority"), value: resolvePriorityCellValue(rule) },
|
|
231
|
+
{ label: translate("Actions"), value: resolveActionsCellValue(rule) },
|
|
232
|
+
{ label: translate("Last updated"), value: resolveLastUpdatedValue(rule) }
|
|
233
|
+
];
|
|
234
|
+
}
|
|
235
|
+
function BasicDetails({
|
|
236
|
+
rule,
|
|
237
|
+
ruleName,
|
|
238
|
+
programStageName
|
|
239
|
+
}) {
|
|
240
|
+
const cells = resolveBasicDetailCells(rule, ruleName, programStageName);
|
|
241
|
+
return /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-x-dp24 gap-y-dp12 rounded-[3px] border border-dhis2-grey-300 bg-dhis2-grey-050 p-dp16", children: cells.map((cell) => /* @__PURE__ */ jsx(BasicDetailCell, { ...cell }, cell.label)) });
|
|
242
|
+
}
|
|
243
|
+
const SECTION_HEADING_CLASS = "m-0 mb-dp8 text-[13px] font-bold uppercase tracking-wide text-dhis2-grey-700";
|
|
244
|
+
function RuleDetailsHeader({
|
|
245
|
+
title,
|
|
246
|
+
chip,
|
|
247
|
+
description
|
|
248
|
+
}) {
|
|
249
|
+
return /* @__PURE__ */ jsxs("div", { className: "-mx-dp24 -mt-dp24 mb-0 border-b border-dhis2-grey-300 px-dp24 pb-dp16 pe-[44px] pt-[20px]", children: [
|
|
250
|
+
/* @__PURE__ */ jsx("p", { className: "m-0 text-[11px] font-bold uppercase tracking-[.09em] text-dhis2-grey-600", children: translate("Program rule") }),
|
|
251
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-[6px] flex flex-wrap items-center gap-dp8", children: [
|
|
252
|
+
/* @__PURE__ */ jsx("h2", { className: "m-0 text-xl font-medium leading-[1.3] text-dhis2-grey-900", children: title }),
|
|
253
|
+
/* @__PURE__ */ jsx(
|
|
254
|
+
"span",
|
|
255
|
+
{
|
|
256
|
+
className: `rounded-[4px] px-dp8 py-[2px] text-xs font-semibold ${chip.className}`,
|
|
257
|
+
children: chip.label
|
|
258
|
+
}
|
|
259
|
+
)
|
|
260
|
+
] }),
|
|
261
|
+
description ? /* @__PURE__ */ jsx(
|
|
262
|
+
"p",
|
|
263
|
+
{
|
|
264
|
+
className: "m-0 mt-[6px] text-sm text-dhis2-grey-700",
|
|
265
|
+
style: { textWrap: "pretty" },
|
|
266
|
+
children: description
|
|
267
|
+
}
|
|
268
|
+
) : null
|
|
269
|
+
] });
|
|
270
|
+
}
|
|
271
|
+
function ConditionSection({
|
|
272
|
+
condition,
|
|
273
|
+
variables
|
|
274
|
+
}) {
|
|
275
|
+
return /* @__PURE__ */ jsxs("section", { children: [
|
|
276
|
+
/* @__PURE__ */ jsx("h3", { className: SECTION_HEADING_CLASS, children: translate("Condition") }),
|
|
277
|
+
/* @__PURE__ */ jsx("pre", { className: "m-0 whitespace-pre-wrap break-words rounded-[3px] border border-dhis2-grey-300 bg-dhis2-grey-200 px-dp16 py-[14px] font-mono text-[13px] leading-[1.6] text-dhis2-grey-900", children: condition ?? EM_DASH }),
|
|
278
|
+
variables.length ? /* @__PURE__ */ jsxs("div", { className: "mt-dp12", children: [
|
|
279
|
+
/* @__PURE__ */ jsx("p", { className: "m-0 mb-dp8 text-xs text-dhis2-grey-600", children: translate("Variables referenced") }),
|
|
280
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-dp8", children: variables.map((variable) => /* @__PURE__ */ jsxs(
|
|
281
|
+
"span",
|
|
282
|
+
{
|
|
283
|
+
className: `inline-flex items-center gap-[4px] rounded-full px-dp8 py-[2px] text-xs ${variable.className}`,
|
|
284
|
+
children: [
|
|
285
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono font-medium", children: variable.label }),
|
|
286
|
+
/* @__PURE__ */ jsx("span", { className: "opacity-70", children: translate(variable.kind) })
|
|
287
|
+
]
|
|
288
|
+
},
|
|
289
|
+
variable.token
|
|
290
|
+
)) })
|
|
291
|
+
] }) : null
|
|
292
|
+
] });
|
|
293
|
+
}
|
|
294
|
+
function ActionsSection({ actions }) {
|
|
295
|
+
return /* @__PURE__ */ jsxs("section", { children: [
|
|
296
|
+
/* @__PURE__ */ jsx("h3", { className: SECTION_HEADING_CLASS, children: translate("Actions") }),
|
|
297
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-dp12", children: actions.map((action, index) => /* @__PURE__ */ jsx(ActionCard, { action, index }, action.id)) })
|
|
298
|
+
] });
|
|
299
|
+
}
|
|
300
|
+
function RuleDetailsContent({
|
|
301
|
+
detail,
|
|
302
|
+
ruleName,
|
|
303
|
+
programStageName,
|
|
304
|
+
variables
|
|
305
|
+
}) {
|
|
306
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-dp24 pt-dp16", children: [
|
|
307
|
+
/* @__PURE__ */ jsxs("section", { children: [
|
|
308
|
+
/* @__PURE__ */ jsx("h3", { className: SECTION_HEADING_CLASS, children: translate("Basic details") }),
|
|
309
|
+
/* @__PURE__ */ jsx(
|
|
310
|
+
BasicDetails,
|
|
311
|
+
{
|
|
312
|
+
rule: detail,
|
|
313
|
+
ruleName,
|
|
314
|
+
programStageName
|
|
315
|
+
}
|
|
316
|
+
)
|
|
317
|
+
] }),
|
|
318
|
+
/* @__PURE__ */ jsx(ConditionSection, { condition: detail.condition, variables }),
|
|
319
|
+
/* @__PURE__ */ jsx(ActionsSection, { actions: detail.programRuleActions ?? [] })
|
|
320
|
+
] });
|
|
321
|
+
}
|
|
322
|
+
function RuleDetailsBody({
|
|
323
|
+
detail,
|
|
324
|
+
loading,
|
|
325
|
+
error,
|
|
326
|
+
ruleName,
|
|
327
|
+
programStageName,
|
|
328
|
+
variables
|
|
329
|
+
}) {
|
|
330
|
+
if (loading) {
|
|
331
|
+
return /* @__PURE__ */ jsx("div", { className: "flex min-h-[280px] items-center justify-center", children: /* @__PURE__ */ jsx(CircularLoader, { small: true }) });
|
|
332
|
+
}
|
|
333
|
+
if (error) {
|
|
334
|
+
return /* @__PURE__ */ jsx("p", { className: "m-0 text-sm text-dhis2-red-700", children: translate("Could not load this rule: {{message}}", { message: error.message }) });
|
|
335
|
+
}
|
|
336
|
+
if (!detail) {
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
return /* @__PURE__ */ jsx(
|
|
340
|
+
RuleDetailsContent,
|
|
341
|
+
{
|
|
342
|
+
detail,
|
|
343
|
+
ruleName,
|
|
344
|
+
programStageName,
|
|
345
|
+
variables
|
|
346
|
+
}
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
function RuleDetailsFooter({ onClose }) {
|
|
350
|
+
return /* @__PURE__ */ jsxs(
|
|
351
|
+
"div",
|
|
352
|
+
{
|
|
353
|
+
style: { order: 3 },
|
|
354
|
+
className: "-mx-dp24 -mb-dp24 mt-dp16 flex items-center justify-between gap-dp12 border-t border-dhis2-grey-300 bg-dhis2-grey-050 px-dp24 py-[14px]",
|
|
355
|
+
children: [
|
|
356
|
+
/* @__PURE__ */ jsx("p", { className: "m-0 text-sm text-dhis2-grey-600", children: translate("Read-only view. Edit rules in the Maintenance app.") }),
|
|
357
|
+
/* @__PURE__ */ jsx(ButtonStrip, { children: /* @__PURE__ */ jsx(Button, { secondary: true, onClick: onClose, children: translate("Close") }) })
|
|
358
|
+
]
|
|
359
|
+
}
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
function resolveActiveRuleId(open, ruleId) {
|
|
363
|
+
return open ? ruleId : null;
|
|
364
|
+
}
|
|
365
|
+
function shouldRenderModal(open, ruleId) {
|
|
366
|
+
return open && ruleId != null;
|
|
367
|
+
}
|
|
368
|
+
function RuleDetailsModal({
|
|
369
|
+
open,
|
|
370
|
+
onClose,
|
|
371
|
+
ruleId,
|
|
372
|
+
ruleName,
|
|
373
|
+
status,
|
|
374
|
+
programStageName,
|
|
375
|
+
programRuleVariables
|
|
376
|
+
}) {
|
|
377
|
+
const { detail, loading, error } = useProgramRuleDetail(resolveActiveRuleId(open, ruleId));
|
|
378
|
+
if (!shouldRenderModal(open, ruleId)) {
|
|
379
|
+
return null;
|
|
380
|
+
}
|
|
381
|
+
const chip = resolveStatusChip(status);
|
|
382
|
+
const variables = parseConditionVariables(detail?.condition, programRuleVariables);
|
|
383
|
+
const title = resolveRuleDisplayName(detail, ruleName);
|
|
384
|
+
return /* @__PURE__ */ jsxs(Modal, { position: "middle", onClose, children: [
|
|
385
|
+
/* @__PURE__ */ jsx(RuleDetailsHeader, { title, chip, description: detail?.description }),
|
|
386
|
+
/* @__PURE__ */ jsx(ModalContent, { children: /* @__PURE__ */ jsx(
|
|
387
|
+
RuleDetailsBody,
|
|
388
|
+
{
|
|
389
|
+
detail,
|
|
390
|
+
loading,
|
|
391
|
+
error,
|
|
392
|
+
ruleName,
|
|
393
|
+
programStageName,
|
|
394
|
+
variables
|
|
395
|
+
}
|
|
396
|
+
) }),
|
|
397
|
+
/* @__PURE__ */ jsx(RuleDetailsFooter, { onClose })
|
|
398
|
+
] });
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
export { RuleDetailsModal };
|
|
402
|
+
//# sourceMappingURL=RuleDetailsModal.js.map
|
|
403
|
+
//# sourceMappingURL=RuleDetailsModal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/RuleDetailsModal.tsx"],"names":[],"mappings":"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","file":"RuleDetailsModal.js","sourcesContent":["import { Button, ButtonStrip, CircularLoader, Modal, ModalContent } from '@dhis2/ui';\nimport { EFFECT_ICONS, getEffectVisual } from './effectStyles.js';\nimport { translate } from './i18n.js';\nimport type { ProgramRuleActionDetail, ProgramRuleDetail } from './programRuleDetailQuery.js';\nimport { useProgramRuleDetail } from './useProgramRuleDetail.js';\n\nexport type RuleDetailsStatus = 'firing' | 'idle' | 'out-of-scope';\n\n/**\n * Structural subset of `ProgramRuleVariable` (event) / the tracker `programRuleVariables` entry\n * shape — those two are distinct generated types (tracker variables never carry `dataElement`),\n * so this only asks for what condition-token resolution actually needs.\n */\nexport type ProgramRuleVariableLike = {\n name?: string;\n dataElement?: { displayName?: string };\n trackedEntityAttribute?: { displayName?: string };\n};\n\nexport type RuleDetailsModalProps = {\n open: boolean;\n onClose: () => void;\n ruleId: string | null;\n /** Already known from the catalog list — shown immediately, before the detail fetch resolves. */\n ruleName: string;\n status: RuleDetailsStatus;\n programStageName?: string | null;\n programRuleVariables: readonly ProgramRuleVariableLike[];\n};\n\nconst EM_DASH = '—';\n\nfunction formatTimestamp(value: string | undefined): string | null {\n if (!value) {\n return null;\n }\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) {\n return null;\n }\n const day = String(date.getDate());\n const month = date.toLocaleString('en-GB', { month: 'short' });\n const year = String(date.getFullYear());\n const hours = String(date.getHours()).padStart(2, '0');\n const minutes = String(date.getMinutes()).padStart(2, '0');\n return `${day} ${month} ${year} ${hours}:${minutes}`;\n}\n\nfunction resolveStatusChip(status: RuleDetailsStatus): { label: string; className: string } {\n switch (status) {\n case 'firing':\n return {\n label: translate('Firing'),\n className: 'bg-dhis2-teal-100 text-dhis2-teal-900',\n };\n case 'idle':\n return { label: translate('Idle'), className: 'bg-dhis2-grey-200 text-dhis2-grey-700' };\n case 'out-of-scope':\n return {\n label: translate('Out of scope'),\n className: 'bg-dhis2-grey-200 text-dhis2-grey-600',\n };\n }\n}\n\ntype VariableKind =\n | 'Data element'\n | 'Tracked entity attribute'\n | 'Environment variable'\n | 'Function';\n\ntype VariableChip = {\n token: string;\n kind: VariableKind;\n label: string;\n className: string;\n};\n\nconst VARIABLE_PATTERNS: Array<{ pattern: RegExp; kind: VariableKind; className: string }> = [\n {\n pattern: /#\\{[^}]*\\}/g,\n kind: 'Data element',\n className: 'bg-dhis2-blue-100 text-dhis2-blue-900',\n },\n {\n pattern: /A\\{[^}]*\\}/g,\n kind: 'Tracked entity attribute',\n className: 'bg-dhis2-teal-100 text-dhis2-teal-900',\n },\n {\n pattern: /V\\{[^}]*\\}/g,\n kind: 'Environment variable',\n className: 'bg-dhis2-grey-200 text-dhis2-grey-900',\n },\n {\n pattern: /d2:\\w+(?=\\()/g,\n kind: 'Function',\n className: 'bg-dhis2-yellow-100 text-dhis2-yellow-900',\n },\n];\n\nconst RESOLVABLE_VARIABLE_KINDS: ReadonlySet<VariableKind> = new Set([\n 'Data element',\n 'Tracked entity attribute',\n]);\n\nfunction resolveVariableDisplayName(\n name: string,\n programRuleVariables: readonly ProgramRuleVariableLike[]\n): string | undefined {\n const variable = programRuleVariables.find((candidate) => candidate.name === name);\n return variable?.dataElement?.displayName ?? variable?.trackedEntityAttribute?.displayName;\n}\n\n/** `#{name}`/`A{name}` reference a program rule *variable* name, not a metadata uid directly — resolve via `programRuleVariables`. */\nfunction resolveVariableToken(\n token: string,\n kind: VariableKind,\n programRuleVariables: readonly ProgramRuleVariableLike[]\n): string {\n if (kind === 'Function') {\n return `${token}()`;\n }\n if (!RESOLVABLE_VARIABLE_KINDS.has(kind)) {\n return token;\n }\n return resolveVariableDisplayName(token.slice(2, -1), programRuleVariables) ?? token;\n}\n\nfunction matchDistinctTokens(condition: string, pattern: RegExp, seen: Set<string>): string[] {\n const matches = condition.match(pattern) ?? [];\n const distinct = matches.filter((token) => !seen.has(token));\n for (const token of distinct) {\n seen.add(token);\n }\n return distinct;\n}\n\nfunction parseConditionVariables(\n condition: string | undefined,\n programRuleVariables: readonly ProgramRuleVariableLike[]\n): VariableChip[] {\n if (!condition) {\n return [];\n }\n const seen = new Set<string>();\n return VARIABLE_PATTERNS.flatMap(({ pattern, kind, className }) =>\n matchDistinctTokens(condition, pattern, seen).map((token) => ({\n token,\n kind,\n label: resolveVariableToken(token, kind, programRuleVariables),\n className,\n }))\n );\n}\n\ntype ActionTarget = { label: string; value: string };\ntype ActionTargetRef = { id: string; displayName?: string } | undefined;\n\n/** Checked in this order — an action only ever populates one of these six target kinds. */\nconst ACTION_TARGET_RESOLVERS: Array<{\n label: string;\n getRef: (action: ProgramRuleActionDetail) => ActionTargetRef;\n}> = [\n { label: 'Data element', getRef: (action) => action.dataElement },\n { label: 'Tracked entity attribute', getRef: (action) => action.trackedEntityAttribute },\n { label: 'Program stage section', getRef: (action) => action.programStageSection },\n { label: 'Program stage', getRef: (action) => action.programStage },\n { label: 'Option', getRef: (action) => action.option },\n { label: 'Option group', getRef: (action) => action.optionGroup },\n];\n\nfunction formatActionTargetValue(ref: NonNullable<ActionTargetRef>): string {\n return `${ref.displayName ?? ref.id} · ${ref.id}`;\n}\n\nfunction resolveActionTarget(action: ProgramRuleActionDetail): ActionTarget | null {\n for (const { label, getRef } of ACTION_TARGET_RESOLVERS) {\n const ref = getRef(action);\n if (ref?.id) {\n return { label: translate(label), value: formatActionTargetValue(ref) };\n }\n }\n return null;\n}\n\nfunction BasicDetailCell({ label, value, mono }: { label: string; value: string; mono?: boolean }) {\n return (\n <div className=\"min-w-0\">\n <p className=\"m-0 text-xs text-dhis2-grey-600\">{label}</p>\n <p className={`m-0 mt-[2px] text-sm text-dhis2-grey-900 ${mono ? 'font-mono' : ''}`}>\n {value}\n </p>\n </div>\n );\n}\n\ntype DetailRow = { label: string; value: string; mono?: boolean };\n\nconst FEEDBACK_ACTION_TYPES: ReadonlySet<string> = new Set(['DISPLAYTEXT', 'DISPLAYKEYVALUEPAIR']);\n\nfunction resolveDataRow(action: ProgramRuleActionDetail): DetailRow | null {\n return action.data\n ? { label: translate('Data (expression)'), value: action.data, mono: true }\n : null;\n}\n\nfunction resolveContentRow(action: ProgramRuleActionDetail): DetailRow | null {\n const showContent =\n Boolean(action.content) && FEEDBACK_ACTION_TYPES.has(action.programRuleActionType);\n return showContent\n ? { label: translate('Content (static text)'), value: action.content ?? '' }\n : null;\n}\n\nfunction resolveLocationRow(action: ProgramRuleActionDetail): DetailRow | null {\n return action.location\n ? { label: translate('Location'), value: action.location, mono: true }\n : null;\n}\n\nfunction resolveActionRows(action: ProgramRuleActionDetail): DetailRow[] {\n const rows = [\n resolveActionTarget(action),\n resolveDataRow(action),\n resolveContentRow(action),\n resolveLocationRow(action),\n ];\n return rows.filter((row): row is DetailRow => row !== null);\n}\n\nfunction ActionCard({ action, index }: { action: ProgramRuleActionDetail; index: number }) {\n const type = action.programRuleActionType;\n const visual = getEffectVisual(type);\n const Icon = EFFECT_ICONS[visual.variant];\n const rows = resolveActionRows(action);\n\n return (\n <div\n className=\"relative rounded-[3px] border border-dhis2-grey-300 bg-white py-dp12 pe-dp16 ps-dp16 shadow-[0_1px_2px_rgb(0_0_0/4%)]\"\n style={{ borderInlineStartWidth: 3, borderInlineStartColor: visual.edgeStroke }}\n >\n <div className=\"mb-dp12 flex items-center justify-between gap-dp8\">\n <span\n className={`inline-flex items-center gap-[4px] rounded-[4px] px-dp8 py-[2px] text-xs font-semibold ${visual.tagClassName}`}\n >\n <Icon />\n {type}\n </span>\n <span className=\"text-[11px] uppercase tracking-wide text-dhis2-grey-600\">\n {translate('Action {{n}}', { n: index + 1 })}\n </span>\n </div>\n <div className=\"flex flex-col gap-dp10\">\n {rows.map((row) => (\n <div key={row.label} className=\"grid grid-cols-[172px_minmax(0,1fr)] gap-dp10\">\n <span className=\"text-xs text-dhis2-grey-600\">{row.label}</span>\n <span\n className={`min-w-0 break-words text-sm ${row.mono ? 'font-mono text-[12px]' : ''}`}\n >\n {row.value}\n </span>\n </div>\n ))}\n </div>\n </div>\n );\n}\n\nfunction orDash(value: string | undefined): string {\n return value ?? EM_DASH;\n}\n\nfunction resolveDetailDisplayName(rule: ProgramRuleDetail | undefined): string | undefined {\n return rule?.displayName;\n}\n\nfunction resolveDetailName(rule: ProgramRuleDetail | undefined): string | undefined {\n return rule?.name;\n}\n\n/** Shared by the modal title and the \"Name\" basic-detail cell — both fall back the same way. */\nfunction resolveRuleDisplayName(rule: ProgramRuleDetail | undefined, fallback: string): string {\n const displayName = resolveDetailDisplayName(rule) ?? resolveDetailName(rule);\n return displayName ?? fallback;\n}\n\nfunction resolveRuleStageName(rule: ProgramRuleDetail | undefined): string | undefined {\n return rule?.programStage?.displayName;\n}\n\nfunction resolveStageName(\n rule: ProgramRuleDetail | undefined,\n programStageName: string | null | undefined\n): string {\n if (programStageName === null) {\n return translate('All stages (registration)');\n }\n return orDash(resolveRuleStageName(rule) ?? programStageName);\n}\n\nfunction resolveLastUpdatedByName(rule: ProgramRuleDetail | undefined): string | undefined {\n return rule?.lastUpdatedBy?.displayName;\n}\n\nfunction resolveLastUpdatedValue(rule: ProgramRuleDetail | undefined): string {\n const label = formatTimestamp(rule?.lastUpdated);\n if (!label) {\n return EM_DASH;\n }\n const by = resolveLastUpdatedByName(rule);\n return by ? `${label} · ${by}` : label;\n}\n\nfunction resolvePriorityCellValue(rule: ProgramRuleDetail | undefined): string {\n return rule?.priority != null ? String(rule.priority) : EM_DASH;\n}\n\nfunction resolveActionsCellValue(rule: ProgramRuleDetail | undefined): string {\n return translate('{{n}} action(s)', { n: rule?.programRuleActions?.length ?? 0 });\n}\n\nfunction resolveBasicDetailCells(\n rule: ProgramRuleDetail | undefined,\n ruleName: string,\n programStageName: string | null | undefined\n): Array<{ label: string; value: string; mono?: boolean }> {\n return [\n { label: translate('Name'), value: resolveRuleDisplayName(rule, ruleName) },\n { label: translate('Code'), value: orDash(rule?.code), mono: true },\n { label: translate('Identifier'), value: orDash(rule?.id), mono: true },\n { label: translate('Program'), value: orDash(rule?.program?.displayName) },\n { label: translate('Program stage'), value: resolveStageName(rule, programStageName) },\n { label: translate('Priority'), value: resolvePriorityCellValue(rule) },\n { label: translate('Actions'), value: resolveActionsCellValue(rule) },\n { label: translate('Last updated'), value: resolveLastUpdatedValue(rule) },\n ];\n}\n\nfunction BasicDetails({\n rule,\n ruleName,\n programStageName,\n}: {\n rule: ProgramRuleDetail | undefined;\n ruleName: string;\n programStageName?: string | null;\n}) {\n const cells = resolveBasicDetailCells(rule, ruleName, programStageName);\n return (\n <div className=\"grid grid-cols-2 gap-x-dp24 gap-y-dp12 rounded-[3px] border border-dhis2-grey-300 bg-dhis2-grey-050 p-dp16\">\n {cells.map((cell) => (\n <BasicDetailCell key={cell.label} {...cell} />\n ))}\n </div>\n );\n}\n\nconst SECTION_HEADING_CLASS =\n 'm-0 mb-dp8 text-[13px] font-bold uppercase tracking-wide text-dhis2-grey-700';\n\n/**\n * `Modal` already renders its own absolutely-positioned close button and wraps every child in\n * a uniform 24px padding box — this bleeds that padding away on its own edges (negative margin)\n * and re-applies the design's own padding, instead of stacking a second layer of padding (and\n * a duplicate close icon) inside it. A plain div defaults to flex `order: 0`, which already\n * sorts before `ModalContent` (order 2) and the footer below (explicit `order: 3`).\n */\nfunction RuleDetailsHeader({\n title,\n chip,\n description,\n}: {\n title: string;\n chip: { label: string; className: string };\n description?: string;\n}) {\n return (\n <div className=\"-mx-dp24 -mt-dp24 mb-0 border-b border-dhis2-grey-300 px-dp24 pb-dp16 pe-[44px] pt-[20px]\">\n <p className=\"m-0 text-[11px] font-bold uppercase tracking-[.09em] text-dhis2-grey-600\">\n {translate('Program rule')}\n </p>\n <div className=\"mt-[6px] flex flex-wrap items-center gap-dp8\">\n <h2 className=\"m-0 text-xl font-medium leading-[1.3] text-dhis2-grey-900\">\n {title}\n </h2>\n <span\n className={`rounded-[4px] px-dp8 py-[2px] text-xs font-semibold ${chip.className}`}\n >\n {chip.label}\n </span>\n </div>\n {description ? (\n <p\n className=\"m-0 mt-[6px] text-sm text-dhis2-grey-700\"\n style={{ textWrap: 'pretty' }}\n >\n {description}\n </p>\n ) : null}\n </div>\n );\n}\n\nfunction ConditionSection({\n condition,\n variables,\n}: {\n condition: string | undefined;\n variables: VariableChip[];\n}) {\n return (\n <section>\n <h3 className={SECTION_HEADING_CLASS}>{translate('Condition')}</h3>\n <pre className=\"m-0 whitespace-pre-wrap break-words rounded-[3px] border border-dhis2-grey-300 bg-dhis2-grey-200 px-dp16 py-[14px] font-mono text-[13px] leading-[1.6] text-dhis2-grey-900\">\n {condition ?? EM_DASH}\n </pre>\n {variables.length ? (\n <div className=\"mt-dp12\">\n <p className=\"m-0 mb-dp8 text-xs text-dhis2-grey-600\">\n {translate('Variables referenced')}\n </p>\n <div className=\"flex flex-wrap gap-dp8\">\n {variables.map((variable) => (\n <span\n key={variable.token}\n className={`inline-flex items-center gap-[4px] rounded-full px-dp8 py-[2px] text-xs ${variable.className}`}\n >\n <span className=\"font-mono font-medium\">{variable.label}</span>\n <span className=\"opacity-70\">{translate(variable.kind)}</span>\n </span>\n ))}\n </div>\n </div>\n ) : null}\n </section>\n );\n}\n\nfunction ActionsSection({ actions }: { actions: ProgramRuleActionDetail[] }) {\n return (\n <section>\n <h3 className={SECTION_HEADING_CLASS}>{translate('Actions')}</h3>\n <div className=\"flex flex-col gap-dp12\">\n {actions.map((action, index) => (\n <ActionCard key={action.id} action={action} index={index} />\n ))}\n </div>\n </section>\n );\n}\n\nfunction RuleDetailsContent({\n detail,\n ruleName,\n programStageName,\n variables,\n}: {\n detail: ProgramRuleDetail;\n ruleName: string;\n programStageName?: string | null;\n variables: VariableChip[];\n}) {\n return (\n <div className=\"flex flex-col gap-dp24 pt-dp16\">\n <section>\n <h3 className={SECTION_HEADING_CLASS}>{translate('Basic details')}</h3>\n <BasicDetails\n rule={detail}\n ruleName={ruleName}\n programStageName={programStageName}\n />\n </section>\n <ConditionSection condition={detail.condition} variables={variables} />\n <ActionsSection actions={detail.programRuleActions ?? []} />\n </div>\n );\n}\n\nfunction RuleDetailsBody({\n detail,\n loading,\n error,\n ruleName,\n programStageName,\n variables,\n}: {\n detail: ProgramRuleDetail | undefined;\n loading: boolean;\n error: Error | undefined;\n ruleName: string;\n programStageName?: string | null;\n variables: VariableChip[];\n}) {\n if (loading) {\n return (\n <div className=\"flex min-h-[280px] items-center justify-center\">\n <CircularLoader small />\n </div>\n );\n }\n if (error) {\n return (\n <p className=\"m-0 text-sm text-dhis2-red-700\">\n {translate('Could not load this rule: {{message}}', { message: error.message })}\n </p>\n );\n }\n if (!detail) {\n return null;\n }\n return (\n <RuleDetailsContent\n detail={detail}\n ruleName={ruleName}\n programStageName={programStageName}\n variables={variables}\n />\n );\n}\n\n/**\n * A plain div (not `ModalActions`) — `ModalActions` sets `align-self: flex-end`, which\n * shrink-wraps it to its content width instead of stretching full-width, so the bleed-to-edge\n * trick here would compute against that shrunk box. `order: 3` reproduces `ModalActions`'\n * position in the flex column without that side effect.\n */\nfunction RuleDetailsFooter({ onClose }: { onClose: () => void }) {\n return (\n <div\n style={{ order: 3 }}\n className=\"-mx-dp24 -mb-dp24 mt-dp16 flex items-center justify-between gap-dp12 border-t border-dhis2-grey-300 bg-dhis2-grey-050 px-dp24 py-[14px]\"\n >\n <p className=\"m-0 text-sm text-dhis2-grey-600\">\n {translate('Read-only view. Edit rules in the Maintenance app.')}\n </p>\n <ButtonStrip>\n <Button secondary onClick={onClose}>\n {translate('Close')}\n </Button>\n </ButtonStrip>\n </div>\n );\n}\n\nfunction resolveActiveRuleId(open: boolean, ruleId: string | null): string | null {\n return open ? ruleId : null;\n}\n\nfunction shouldRenderModal(open: boolean, ruleId: string | null): boolean {\n return open && ruleId != null;\n}\n\nexport function RuleDetailsModal({\n open,\n onClose,\n ruleId,\n ruleName,\n status,\n programStageName,\n programRuleVariables,\n}: RuleDetailsModalProps) {\n const { detail, loading, error } = useProgramRuleDetail(resolveActiveRuleId(open, ruleId));\n\n if (!shouldRenderModal(open, ruleId)) {\n return null;\n }\n\n const chip = resolveStatusChip(status);\n const variables = parseConditionVariables(detail?.condition, programRuleVariables);\n const title = resolveRuleDisplayName(detail, ruleName);\n\n return (\n <Modal position=\"middle\" onClose={onClose}>\n <RuleDetailsHeader title={title} chip={chip} description={detail?.description} />\n <ModalContent>\n <RuleDetailsBody\n detail={detail}\n loading={loading}\n error={error}\n ruleName={ruleName}\n programStageName={programStageName}\n variables={variables}\n />\n </ModalContent>\n <RuleDetailsFooter onClose={onClose} />\n </Modal>\n );\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { TraceAttachableFormStore } from './attach.js';
|
|
4
|
+
import { RuleTraceStore } from './traceStore.js';
|
|
5
|
+
import '@nnkogift/dhis2-form-utils-hooks';
|
|
6
|
+
|
|
7
|
+
type RuleDevtoolsScopeProps = {
|
|
8
|
+
formStore: TraceAttachableFormStore;
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
};
|
|
11
|
+
declare function RuleDevtoolsScope({ formStore, children }: RuleDevtoolsScopeProps): react_jsx_runtime.JSX.Element;
|
|
12
|
+
declare function useRuleTraceStore(): RuleTraceStore;
|
|
13
|
+
|
|
14
|
+
export { RuleDevtoolsScope, type RuleDevtoolsScopeProps, useRuleTraceStore };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import { createContext, useMemo, useEffect, useContext } from 'react';
|
|
3
|
+
import { attachRuleDevtools } from './attach.js';
|
|
4
|
+
|
|
5
|
+
const RuleTraceContext = createContext(null);
|
|
6
|
+
function RuleDevtoolsScope({ formStore, children }) {
|
|
7
|
+
const traceStore = useMemo(() => attachRuleDevtools(formStore), [formStore]);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
return () => {
|
|
10
|
+
traceStore.dispose();
|
|
11
|
+
};
|
|
12
|
+
}, [traceStore]);
|
|
13
|
+
return /* @__PURE__ */ jsx(RuleTraceContext.Provider, { value: traceStore, children });
|
|
14
|
+
}
|
|
15
|
+
function useRuleTraceStore() {
|
|
16
|
+
const store = useContext(RuleTraceContext);
|
|
17
|
+
if (!store) {
|
|
18
|
+
throw new Error("useRuleTraceStore must be used within RuleDevtoolsScope");
|
|
19
|
+
}
|
|
20
|
+
return store;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { RuleDevtoolsScope, useRuleTraceStore };
|
|
24
|
+
//# sourceMappingURL=RuleDevtoolsScope.js.map
|
|
25
|
+
//# sourceMappingURL=RuleDevtoolsScope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/RuleDevtoolsScope.tsx"],"names":[],"mappings":";;;;AAIA,MAAM,gBAAA,GAAmB,cAAqC,IAAI,CAAA;AAO3D,SAAS,iBAAA,CAAkB,EAAE,SAAA,EAAW,QAAA,EAAS,EAA2B;AAC/E,EAAA,MAAM,UAAA,GAAa,QAAQ,MAAM,kBAAA,CAAmB,SAAS,CAAA,EAAG,CAAC,SAAS,CAAC,CAAA;AAE3E,EAAA,SAAA,CAAU,MAAM;AACZ,IAAA,OAAO,MAAM;AACT,MAAA,UAAA,CAAW,OAAA,EAAQ;AAAA,IACvB,CAAA;AAAA,EACJ,CAAA,EAAG,CAAC,UAAU,CAAC,CAAA;AAEf,EAAA,2BAAQ,gBAAA,CAAiB,QAAA,EAAjB,EAA0B,KAAA,EAAO,YAAa,QAAA,EAAS,CAAA;AACnE;AAEO,SAAS,iBAAA,GAAoC;AAChD,EAAA,MAAM,KAAA,GAAQ,WAAW,gBAAgB,CAAA;AACzC,EAAA,IAAI,CAAC,KAAA,EAAO;AACR,IAAA,MAAM,IAAI,MAAM,yDAAyD,CAAA;AAAA,EAC7E;AACA,EAAA,OAAO,KAAA;AACX","file":"RuleDevtoolsScope.js","sourcesContent":["import { createContext, useContext, useEffect, useMemo, type ReactNode } from 'react';\nimport { attachRuleDevtools, type TraceAttachableFormStore } from './attach.js';\nimport type { RuleTraceStore } from './traceStore.js';\n\nconst RuleTraceContext = createContext<RuleTraceStore | null>(null);\n\nexport type RuleDevtoolsScopeProps = {\n formStore: TraceAttachableFormStore;\n children: ReactNode;\n};\n\nexport function RuleDevtoolsScope({ formStore, children }: RuleDevtoolsScopeProps) {\n const traceStore = useMemo(() => attachRuleDevtools(formStore), [formStore]);\n\n useEffect(() => {\n return () => {\n traceStore.dispose();\n };\n }, [traceStore]);\n\n return <RuleTraceContext.Provider value={traceStore}>{children}</RuleTraceContext.Provider>;\n}\n\nexport function useRuleTraceStore(): RuleTraceStore {\n const store = useContext(RuleTraceContext);\n if (!store) {\n throw new Error('useRuleTraceStore must be used within RuleDevtoolsScope');\n }\n return store;\n}\n"]}
|