@nnkogift/dhis2-form-utils-devtools 0.1.0-alpha.4 → 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 +1364 -651
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.cts +12 -63
- package/dist/index.d.ts +12 -63
- package/dist/index.js +5 -1669
- 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 +27 -4
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { NoticeBox, Card, IconChevronDown16, IconChevronRight16, Tag, Divider, Chip } from '@dhis2/ui';
|
|
3
|
+
import { useState, useEffect } from 'react';
|
|
4
|
+
import { EffectBadge } from './EffectBadge.js';
|
|
5
|
+
import { formatAgo } from './formatAgo.js';
|
|
6
|
+
import { translate } from './i18n.js';
|
|
7
|
+
|
|
8
|
+
function resolveLabel(id, resolver) {
|
|
9
|
+
const label = resolver?.(id) ?? id;
|
|
10
|
+
return { label, showId: label !== id };
|
|
11
|
+
}
|
|
12
|
+
function resolveEffectTargetLabel(effect, labelLookup) {
|
|
13
|
+
if (effect.type === "HIDESECTION") {
|
|
14
|
+
return resolveLabel(
|
|
15
|
+
effect.targetId,
|
|
16
|
+
labelLookup ? (id) => labelLookup.resolveSectionName(id) : void 0
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
if (effect.type === "DISPLAYTEXT" || effect.type === "DISPLAYKEYVALUEPAIR") {
|
|
20
|
+
return { label: effect.targetId, showId: false };
|
|
21
|
+
}
|
|
22
|
+
return resolveLabel(
|
|
23
|
+
effect.targetId,
|
|
24
|
+
labelLookup ? (id) => labelLookup.resolveFieldName(id) : void 0
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
function TraceTimeline({
|
|
28
|
+
entries,
|
|
29
|
+
selectedEntryId,
|
|
30
|
+
highlightRuleId,
|
|
31
|
+
onSelectEntry,
|
|
32
|
+
onHighlightRule,
|
|
33
|
+
labelLookup
|
|
34
|
+
}) {
|
|
35
|
+
const [expandedIds, setExpandedIds] = useState(() => /* @__PURE__ */ new Set());
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (!entries.length) {
|
|
38
|
+
setExpandedIds(/* @__PURE__ */ new Set());
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const newestId = entries[entries.length - 1]?.id;
|
|
42
|
+
if (!newestId) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
setExpandedIds((current) => {
|
|
46
|
+
if (current.size > 0) {
|
|
47
|
+
return current;
|
|
48
|
+
}
|
|
49
|
+
return /* @__PURE__ */ new Set([newestId]);
|
|
50
|
+
});
|
|
51
|
+
}, [entries]);
|
|
52
|
+
if (!entries.length) {
|
|
53
|
+
return /* @__PURE__ */ jsx("div", { className: "p-dp8", children: /* @__PURE__ */ jsx(NoticeBox, { title: translate("No rules observed yet"), children: translate(
|
|
54
|
+
"Interact with the form to record rule evaluations. Only rules that have fired at least once appear here."
|
|
55
|
+
) }) });
|
|
56
|
+
}
|
|
57
|
+
const reversed = [...entries].reverse();
|
|
58
|
+
const toggleExpanded = (entryId) => {
|
|
59
|
+
setExpandedIds((current) => {
|
|
60
|
+
const next = new Set(current);
|
|
61
|
+
if (next.has(entryId)) {
|
|
62
|
+
next.delete(entryId);
|
|
63
|
+
} else {
|
|
64
|
+
next.add(entryId);
|
|
65
|
+
}
|
|
66
|
+
return next;
|
|
67
|
+
});
|
|
68
|
+
};
|
|
69
|
+
return /* @__PURE__ */ jsx("ul", { className: "m-0 flex list-none flex-col gap-dp12 p-0", children: reversed.map((entry) => {
|
|
70
|
+
const isInitial = entry.changedFields.length === 0;
|
|
71
|
+
const ruleCount = entry.ruleResults.length;
|
|
72
|
+
const effectCount = entry.ruleResults.reduce(
|
|
73
|
+
(total, result) => total + result.effects.length,
|
|
74
|
+
0
|
|
75
|
+
);
|
|
76
|
+
const isExpanded = expandedIds.has(entry.id);
|
|
77
|
+
const isSelected = selectedEntryId === entry.id;
|
|
78
|
+
return /* @__PURE__ */ jsx("li", { className: "m-0", children: /* @__PURE__ */ jsxs(
|
|
79
|
+
Card,
|
|
80
|
+
{
|
|
81
|
+
className: `overflow-hidden rounded-md border border-dhis2-grey-300 bg-white shadow-[0_1px_2px_rgb(0_0_0/4%)] transition-[border-color,box-shadow] duration-150 ease-out ${isSelected ? "border-dhis2-teal-600 shadow-[0_0_0_1px_var(--color-dhis2-teal-600),0_2px_8px_rgb(0_137_123/12%)]" : ""}`,
|
|
82
|
+
children: [
|
|
83
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-stretch gap-dp4 bg-dhis2-grey-050 py-dp4 pe-dp8 ps-dp4", children: [
|
|
84
|
+
/* @__PURE__ */ jsx(
|
|
85
|
+
"button",
|
|
86
|
+
{
|
|
87
|
+
type: "button",
|
|
88
|
+
className: "inline-flex size-10 min-h-10 min-w-10 shrink-0 cursor-pointer items-center justify-center self-center rounded border-none bg-transparent text-dhis2-grey-700 hover:bg-dhis2-grey-200 focus-visible:outline-2 focus-visible:outline-dhis2-teal-600 focus-visible:outline-offset-1",
|
|
89
|
+
"aria-expanded": isExpanded,
|
|
90
|
+
"aria-label": isExpanded ? translate("Collapse evaluation details") : translate("Expand evaluation details"),
|
|
91
|
+
onClick: () => {
|
|
92
|
+
toggleExpanded(entry.id);
|
|
93
|
+
},
|
|
94
|
+
children: isExpanded ? /* @__PURE__ */ jsx(IconChevronDown16, {}) : /* @__PURE__ */ jsx(IconChevronRight16, {})
|
|
95
|
+
}
|
|
96
|
+
),
|
|
97
|
+
/* @__PURE__ */ jsxs(
|
|
98
|
+
"button",
|
|
99
|
+
{
|
|
100
|
+
type: "button",
|
|
101
|
+
className: "flex min-h-11 min-w-0 flex-1 cursor-pointer items-center justify-between gap-dp12 rounded border-none bg-transparent py-dp8 pe-dp8 ps-dp4 text-start font-[inherit] text-inherit hover:bg-white/80 focus-visible:outline-2 focus-visible:outline-dhis2-teal-600 focus-visible:outline-offset-1",
|
|
102
|
+
"aria-pressed": isSelected,
|
|
103
|
+
onClick: () => {
|
|
104
|
+
onSelectEntry(entry.id);
|
|
105
|
+
},
|
|
106
|
+
children: [
|
|
107
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col items-start gap-0.5", children: [
|
|
108
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold leading-[1.3] text-dhis2-grey-900 tabular-nums", children: formatAgo(entry.timestamp) }),
|
|
109
|
+
!isExpanded && effectCount > 0 ? /* @__PURE__ */ jsx("span", { className: "text-xs leading-[1.3] text-dhis2-grey-600", children: translate("{{count}} effects", {
|
|
110
|
+
count: effectCount
|
|
111
|
+
}) }) : null
|
|
112
|
+
] }),
|
|
113
|
+
/* @__PURE__ */ jsx(
|
|
114
|
+
Tag,
|
|
115
|
+
{
|
|
116
|
+
className: isInitial ? "shrink-0" : void 0,
|
|
117
|
+
neutral: !isInitial,
|
|
118
|
+
children: isInitial ? translate("Initial") : translate("{{count}} rules", { count: ruleCount })
|
|
119
|
+
}
|
|
120
|
+
)
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
)
|
|
124
|
+
] }),
|
|
125
|
+
isExpanded ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-dp16 border-t border-dhis2-grey-200 p-dp16", children: [
|
|
126
|
+
isInitial ? /* @__PURE__ */ jsx("p", { className: "m-0 text-sm leading-normal text-dhis2-grey-600", children: ruleCount ? translate("{{count}} effects on load", {
|
|
127
|
+
count: effectCount
|
|
128
|
+
}) : translate("No rules fired") }) : /* @__PURE__ */ jsxs("section", { className: "flex flex-col gap-dp8", children: [
|
|
129
|
+
/* @__PURE__ */ jsx("h3", { className: "m-0 text-[0.6875rem] font-bold uppercase leading-[1.3] tracking-wider text-dhis2-grey-600", children: translate("Changed fields") }),
|
|
130
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-dp8", children: entry.changedFields.map((fieldId) => {
|
|
131
|
+
const { label, showId } = resolveLabel(
|
|
132
|
+
fieldId,
|
|
133
|
+
labelLookup ? (id) => labelLookup.resolveFieldName(id) : void 0
|
|
134
|
+
);
|
|
135
|
+
return /* @__PURE__ */ jsx(
|
|
136
|
+
"div",
|
|
137
|
+
{
|
|
138
|
+
className: "flex max-w-full flex-col gap-0.5",
|
|
139
|
+
children: /* @__PURE__ */ jsx(
|
|
140
|
+
Tag,
|
|
141
|
+
{
|
|
142
|
+
neutral: true,
|
|
143
|
+
className: `max-w-full break-words text-xs ${showId ? "" : "font-mono break-all"}`,
|
|
144
|
+
children: label
|
|
145
|
+
}
|
|
146
|
+
)
|
|
147
|
+
},
|
|
148
|
+
fieldId
|
|
149
|
+
);
|
|
150
|
+
}) })
|
|
151
|
+
] }),
|
|
152
|
+
entry.ruleResults.length === 0 ? !isInitial ? /* @__PURE__ */ jsx("p", { className: "m-0 text-sm leading-normal text-dhis2-grey-600", children: translate("No rules fired") }) : null : /* @__PURE__ */ jsxs("section", { className: "flex flex-col gap-dp8", children: [
|
|
153
|
+
!isInitial ? /* @__PURE__ */ jsx("h3", { className: "m-0 text-[0.6875rem] font-bold uppercase leading-[1.3] tracking-wider text-dhis2-grey-600", children: translate("Rules fired") }) : null,
|
|
154
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-col gap-dp12", children: entry.ruleResults.map((result, index) => {
|
|
155
|
+
const { label: displayName } = resolveLabel(
|
|
156
|
+
result.ruleId,
|
|
157
|
+
labelLookup ? (id) => labelLookup.resolveRuleName(id) : void 0
|
|
158
|
+
);
|
|
159
|
+
return /* @__PURE__ */ jsxs(
|
|
160
|
+
"div",
|
|
161
|
+
{
|
|
162
|
+
className: "rounded border border-dhis2-grey-200 bg-dhis2-grey-050 p-dp12",
|
|
163
|
+
children: [
|
|
164
|
+
index > 0 ? /* @__PURE__ */ jsx(Divider, { margin: "12px 0" }) : null,
|
|
165
|
+
/* @__PURE__ */ jsx("div", { className: "mb-dp12 flex flex-col items-start gap-dp4", children: /* @__PURE__ */ jsx(
|
|
166
|
+
Chip,
|
|
167
|
+
{
|
|
168
|
+
selected: highlightRuleId === result.ruleId,
|
|
169
|
+
onClick: (_, event) => {
|
|
170
|
+
event.stopPropagation();
|
|
171
|
+
onHighlightRule(
|
|
172
|
+
highlightRuleId === result.ruleId ? null : result.ruleId
|
|
173
|
+
);
|
|
174
|
+
},
|
|
175
|
+
children: displayName
|
|
176
|
+
}
|
|
177
|
+
) }),
|
|
178
|
+
/* @__PURE__ */ jsx("ul", { className: "m-0 flex list-none flex-col gap-dp12 p-0", children: result.effects.map((effect) => {
|
|
179
|
+
const {
|
|
180
|
+
label: targetLabel,
|
|
181
|
+
showId: showTargetId
|
|
182
|
+
} = resolveEffectTargetLabel(
|
|
183
|
+
effect,
|
|
184
|
+
labelLookup
|
|
185
|
+
);
|
|
186
|
+
return /* @__PURE__ */ jsxs(
|
|
187
|
+
"li",
|
|
188
|
+
{
|
|
189
|
+
className: "flex flex-col gap-dp4",
|
|
190
|
+
children: [
|
|
191
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-baseline gap-dp8", children: [
|
|
192
|
+
/* @__PURE__ */ jsx(
|
|
193
|
+
EffectBadge,
|
|
194
|
+
{
|
|
195
|
+
type: effect.type
|
|
196
|
+
}
|
|
197
|
+
),
|
|
198
|
+
/* @__PURE__ */ jsx(
|
|
199
|
+
"span",
|
|
200
|
+
{
|
|
201
|
+
className: `break-words text-[0.8125rem] leading-[1.45] text-dhis2-grey-800 ${showTargetId ? "" : "break-all font-mono"}`,
|
|
202
|
+
children: targetLabel
|
|
203
|
+
}
|
|
204
|
+
)
|
|
205
|
+
] }),
|
|
206
|
+
effect.data ? /* @__PURE__ */ jsx("p", { className: "m-0 ps-dp4 text-[0.8125rem] leading-[1.45] break-words text-dhis2-grey-600", children: effect.data }) : null
|
|
207
|
+
]
|
|
208
|
+
},
|
|
209
|
+
`${effect.type}-${effect.targetId}-${effect.data ?? ""}`
|
|
210
|
+
);
|
|
211
|
+
}) })
|
|
212
|
+
]
|
|
213
|
+
},
|
|
214
|
+
result.ruleId
|
|
215
|
+
);
|
|
216
|
+
}) })
|
|
217
|
+
] })
|
|
218
|
+
] }) : null
|
|
219
|
+
]
|
|
220
|
+
}
|
|
221
|
+
) }, entry.id);
|
|
222
|
+
}) });
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export { TraceTimeline };
|
|
226
|
+
//# sourceMappingURL=TraceTimeline.js.map
|
|
227
|
+
//# sourceMappingURL=TraceTimeline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/TraceTimeline.tsx"],"names":[],"mappings":"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","file":"TraceTimeline.js","sourcesContent":["import {\n Card,\n Chip,\n Divider,\n IconChevronDown16,\n IconChevronRight16,\n NoticeBox,\n Tag,\n} from '@dhis2/ui';\nimport type { RuleTraceEntry, TraceEffect } from '@nnkogift/dhis2-form-utils-hooks';\nimport { useEffect, useState } from 'react';\nimport type { DevtoolsLabelLookup } from './createLabelLookup.js';\nimport { EffectBadge } from './EffectBadge.js';\nimport { formatAgo } from './formatAgo.js';\nimport { translate } from './i18n.js';\n\ntype TraceTimelineProps = {\n entries: readonly RuleTraceEntry[];\n selectedEntryId: string | null;\n highlightRuleId: string | null;\n onSelectEntry: (entryId: string) => void;\n onHighlightRule: (ruleId: string | null) => void;\n labelLookup?: DevtoolsLabelLookup;\n};\n\nfunction resolveLabel(\n id: string,\n resolver?: (value: string) => string\n): { label: string; showId: boolean } {\n const label = resolver?.(id) ?? id;\n return { label, showId: label !== id };\n}\n\nfunction resolveEffectTargetLabel(\n effect: TraceEffect,\n labelLookup?: DevtoolsLabelLookup\n): { label: string; showId: boolean } {\n if (effect.type === 'HIDESECTION') {\n return resolveLabel(\n effect.targetId,\n labelLookup ? (id) => labelLookup.resolveSectionName(id) : undefined\n );\n }\n\n if (effect.type === 'DISPLAYTEXT' || effect.type === 'DISPLAYKEYVALUEPAIR') {\n return { label: effect.targetId, showId: false };\n }\n\n return resolveLabel(\n effect.targetId,\n labelLookup ? (id) => labelLookup.resolveFieldName(id) : undefined\n );\n}\n\nexport function TraceTimeline({\n entries,\n selectedEntryId,\n highlightRuleId,\n onSelectEntry,\n onHighlightRule,\n labelLookup,\n}: TraceTimelineProps) {\n const [expandedIds, setExpandedIds] = useState<ReadonlySet<string>>(() => new Set());\n\n useEffect(() => {\n if (!entries.length) {\n setExpandedIds(new Set());\n return;\n }\n\n const newestId = entries[entries.length - 1]?.id;\n if (!newestId) {\n return;\n }\n\n setExpandedIds((current) => {\n if (current.size > 0) {\n return current;\n }\n return new Set([newestId]);\n });\n }, [entries]);\n\n if (!entries.length) {\n return (\n <div className=\"p-dp8\">\n <NoticeBox title={translate('No rules observed yet')}>\n {translate(\n 'Interact with the form to record rule evaluations. Only rules that have fired at least once appear here.'\n )}\n </NoticeBox>\n </div>\n );\n }\n\n const reversed = [...entries].reverse();\n\n const toggleExpanded = (entryId: string) => {\n setExpandedIds((current) => {\n const next = new Set(current);\n if (next.has(entryId)) {\n next.delete(entryId);\n } else {\n next.add(entryId);\n }\n return next;\n });\n };\n\n return (\n <ul className=\"m-0 flex list-none flex-col gap-dp12 p-0\">\n {reversed.map((entry) => {\n const isInitial = entry.changedFields.length === 0;\n const ruleCount = entry.ruleResults.length;\n const effectCount = entry.ruleResults.reduce(\n (total, result) => total + result.effects.length,\n 0\n );\n const isExpanded = expandedIds.has(entry.id);\n const isSelected = selectedEntryId === entry.id;\n\n return (\n <li key={entry.id} className=\"m-0\">\n <Card\n className={`overflow-hidden rounded-md border border-dhis2-grey-300 bg-white shadow-[0_1px_2px_rgb(0_0_0/4%)] transition-[border-color,box-shadow] duration-150 ease-out ${\n isSelected\n ? 'border-dhis2-teal-600 shadow-[0_0_0_1px_var(--color-dhis2-teal-600),0_2px_8px_rgb(0_137_123/12%)]'\n : ''\n }`}\n >\n <div className=\"flex items-stretch gap-dp4 bg-dhis2-grey-050 py-dp4 pe-dp8 ps-dp4\">\n <button\n type=\"button\"\n className=\"inline-flex size-10 min-h-10 min-w-10 shrink-0 cursor-pointer items-center justify-center self-center rounded border-none bg-transparent text-dhis2-grey-700 hover:bg-dhis2-grey-200 focus-visible:outline-2 focus-visible:outline-dhis2-teal-600 focus-visible:outline-offset-1\"\n aria-expanded={isExpanded}\n aria-label={\n isExpanded\n ? translate('Collapse evaluation details')\n : translate('Expand evaluation details')\n }\n onClick={() => {\n toggleExpanded(entry.id);\n }}\n >\n {isExpanded ? <IconChevronDown16 /> : <IconChevronRight16 />}\n </button>\n\n <button\n type=\"button\"\n className=\"flex min-h-11 min-w-0 flex-1 cursor-pointer items-center justify-between gap-dp12 rounded border-none bg-transparent py-dp8 pe-dp8 ps-dp4 text-start font-[inherit] text-inherit hover:bg-white/80 focus-visible:outline-2 focus-visible:outline-dhis2-teal-600 focus-visible:outline-offset-1\"\n aria-pressed={isSelected}\n onClick={() => {\n onSelectEntry(entry.id);\n }}\n >\n <span className=\"flex min-w-0 flex-col items-start gap-0.5\">\n <span className=\"text-sm font-semibold leading-[1.3] text-dhis2-grey-900 tabular-nums\">\n {formatAgo(entry.timestamp)}\n </span>\n {!isExpanded && effectCount > 0 ? (\n <span className=\"text-xs leading-[1.3] text-dhis2-grey-600\">\n {translate('{{count}} effects', {\n count: effectCount,\n })}\n </span>\n ) : null}\n </span>\n <Tag\n className={isInitial ? 'shrink-0' : undefined}\n neutral={!isInitial}\n >\n {isInitial\n ? translate('Initial')\n : translate('{{count}} rules', { count: ruleCount })}\n </Tag>\n </button>\n </div>\n\n {isExpanded ? (\n <div className=\"flex flex-col gap-dp16 border-t border-dhis2-grey-200 p-dp16\">\n {isInitial ? (\n <p className=\"m-0 text-sm leading-normal text-dhis2-grey-600\">\n {ruleCount\n ? translate('{{count}} effects on load', {\n count: effectCount,\n })\n : translate('No rules fired')}\n </p>\n ) : (\n <section className=\"flex flex-col gap-dp8\">\n <h3 className=\"m-0 text-[0.6875rem] font-bold uppercase leading-[1.3] tracking-wider text-dhis2-grey-600\">\n {translate('Changed fields')}\n </h3>\n <div className=\"flex flex-wrap gap-dp8\">\n {entry.changedFields.map((fieldId) => {\n const { label, showId } = resolveLabel(\n fieldId,\n labelLookup\n ? (id) =>\n labelLookup.resolveFieldName(id)\n : undefined\n );\n\n return (\n <div\n key={fieldId}\n className=\"flex max-w-full flex-col gap-0.5\"\n >\n <Tag\n neutral\n className={`max-w-full break-words text-xs ${showId ? '' : 'font-mono break-all'}`}\n >\n {label}\n </Tag>\n </div>\n );\n })}\n </div>\n </section>\n )}\n\n {entry.ruleResults.length === 0 ? (\n !isInitial ? (\n <p className=\"m-0 text-sm leading-normal text-dhis2-grey-600\">\n {translate('No rules fired')}\n </p>\n ) : null\n ) : (\n <section className=\"flex flex-col gap-dp8\">\n {!isInitial ? (\n <h3 className=\"m-0 text-[0.6875rem] font-bold uppercase leading-[1.3] tracking-wider text-dhis2-grey-600\">\n {translate('Rules fired')}\n </h3>\n ) : null}\n <div className=\"flex flex-col gap-dp12\">\n {entry.ruleResults.map((result, index) => {\n const { label: displayName } = resolveLabel(\n result.ruleId,\n labelLookup\n ? (id) =>\n labelLookup.resolveRuleName(id)\n : undefined\n );\n\n return (\n <div\n key={result.ruleId}\n className=\"rounded border border-dhis2-grey-200 bg-dhis2-grey-050 p-dp12\"\n >\n {index > 0 ? (\n <Divider margin=\"12px 0\" />\n ) : null}\n <div className=\"mb-dp12 flex flex-col items-start gap-dp4\">\n <Chip\n selected={\n highlightRuleId ===\n result.ruleId\n }\n onClick={(_, event) => {\n event.stopPropagation();\n onHighlightRule(\n highlightRuleId ===\n result.ruleId\n ? null\n : result.ruleId\n );\n }}\n >\n {displayName}\n </Chip>\n </div>\n <ul className=\"m-0 flex list-none flex-col gap-dp12 p-0\">\n {result.effects.map((effect) => {\n const {\n label: targetLabel,\n showId: showTargetId,\n } = resolveEffectTargetLabel(\n effect,\n labelLookup\n );\n\n return (\n <li\n key={`${effect.type}-${effect.targetId}-${effect.data ?? ''}`}\n className=\"flex flex-col gap-dp4\"\n >\n <div className=\"flex flex-wrap items-baseline gap-dp8\">\n <EffectBadge\n type={\n effect.type\n }\n />\n <span\n className={`break-words text-[0.8125rem] leading-[1.45] text-dhis2-grey-800 ${showTargetId ? '' : 'break-all font-mono'}`}\n >\n {targetLabel}\n </span>\n </div>\n {effect.data ? (\n <p className=\"m-0 ps-dp4 text-[0.8125rem] leading-[1.45] break-words text-dhis2-grey-600\">\n {effect.data}\n </p>\n ) : null}\n </li>\n );\n })}\n </ul>\n </div>\n );\n })}\n </div>\n </section>\n )}\n </div>\n ) : null}\n </Card>\n </li>\n );\n })}\n </ul>\n );\n}\n"]}
|
package/dist/attach.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { RuleTraceEntry } from '@nnkogift/dhis2-form-utils-hooks';
|
|
2
|
+
import { RuleTraceStore } from './traceStore.js';
|
|
3
|
+
|
|
4
|
+
/** Structural attach surface — avoids nominal `FormStore` clashes across package versions. */
|
|
5
|
+
type TraceAttachableFormStore = {
|
|
6
|
+
subscribeTrace: (listener: (entry: RuleTraceEntry) => void) => () => void;
|
|
7
|
+
};
|
|
8
|
+
declare function attachRuleDevtools(formStore: TraceAttachableFormStore, options?: {
|
|
9
|
+
maxEntries?: number;
|
|
10
|
+
}): RuleTraceStore;
|
|
11
|
+
|
|
12
|
+
export { type TraceAttachableFormStore, attachRuleDevtools };
|
package/dist/attach.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { DEFAULT_TRACE_MAX_ENTRIES } from './constants.js';
|
|
2
|
+
import { createRuleTraceStore } from './traceStore.js';
|
|
3
|
+
|
|
4
|
+
function attachRuleDevtools(formStore, options) {
|
|
5
|
+
const store = createRuleTraceStore(
|
|
6
|
+
options?.maxEntries ?? DEFAULT_TRACE_MAX_ENTRIES
|
|
7
|
+
);
|
|
8
|
+
store.bindTraceSubscription(formStore.subscribeTrace(store.record));
|
|
9
|
+
return store;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export { attachRuleDevtools };
|
|
13
|
+
//# sourceMappingURL=attach.js.map
|
|
14
|
+
//# sourceMappingURL=attach.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/attach.ts"],"names":[],"mappings":";;;AASO,SAAS,kBAAA,CACZ,WACA,OAAA,EACc;AACd,EAAA,MAAM,KAAA,GAAQ,oBAAA;AAAA,IACV,SAAS,UAAA,IAAc;AAAA,GAC3B;AAIA,EAAA,KAAA,CAAM,qBAAA,CAAsB,SAAA,CAAU,cAAA,CAAe,KAAA,CAAM,MAAM,CAAC,CAAA;AAElE,EAAA,OAAO,KAAA;AACX","file":"attach.js","sourcesContent":["import type { RuleTraceEntry } from '@nnkogift/dhis2-form-utils-hooks';\nimport { DEFAULT_TRACE_MAX_ENTRIES } from './constants.js';\nimport { createRuleTraceStore, type RuleTraceStore } from './traceStore.js';\n\n/** Structural attach surface — avoids nominal `FormStore` clashes across package versions. */\nexport type TraceAttachableFormStore = {\n subscribeTrace: (listener: (entry: RuleTraceEntry) => void) => () => void;\n};\n\nexport function attachRuleDevtools(\n formStore: TraceAttachableFormStore,\n options?: { maxEntries?: number }\n): RuleTraceStore {\n const store = createRuleTraceStore(\n options?.maxEntries ?? DEFAULT_TRACE_MAX_ENTRIES\n ) as RuleTraceStore & {\n bindTraceSubscription: (unsubscribe: () => void) => void;\n };\n\n store.bindTraceSubscription(formStore.subscribeTrace(store.record));\n\n return store;\n}\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { RuleTraceEntry } from '@nnkogift/dhis2-form-utils-hooks';
|
|
2
|
+
import { DevtoolsLabelLookup } from './createLabelLookup.js';
|
|
3
|
+
import '@nnkogift/dhis2-form-utils-metadata';
|
|
4
|
+
|
|
5
|
+
type GraphNodeKind = 'field' | 'section' | 'feedback' | 'rule';
|
|
6
|
+
type GraphNode = {
|
|
7
|
+
id: string;
|
|
8
|
+
kind: GraphNodeKind;
|
|
9
|
+
label: string;
|
|
10
|
+
};
|
|
11
|
+
type GraphEdge = {
|
|
12
|
+
id: string;
|
|
13
|
+
source: string;
|
|
14
|
+
target: string;
|
|
15
|
+
effectType?: string;
|
|
16
|
+
fireCount: number;
|
|
17
|
+
};
|
|
18
|
+
type RuleDependencyGraph = {
|
|
19
|
+
nodes: GraphNode[];
|
|
20
|
+
edges: GraphEdge[];
|
|
21
|
+
};
|
|
22
|
+
declare function accumulateGraph(previous: RuleDependencyGraph, entry: RuleTraceEntry, labelLookup?: DevtoolsLabelLookup): RuleDependencyGraph;
|
|
23
|
+
declare function buildGraphFromTrace(entries: readonly RuleTraceEntry[], labelLookup?: DevtoolsLabelLookup): RuleDependencyGraph;
|
|
24
|
+
|
|
25
|
+
export { type GraphEdge, type GraphNode, type GraphNodeKind, type RuleDependencyGraph, accumulateGraph, buildGraphFromTrace };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const nodeKey = (kind, id) => `${kind}:${id}`;
|
|
2
|
+
const edgeKey = (source, ruleId, target, effectType) => `${source}|${ruleId}|${target}|${effectType ?? ""}`;
|
|
3
|
+
function accumulateGraph(previous, entry, labelLookup) {
|
|
4
|
+
const nodes = new Map(previous.nodes.map((node) => [node.id, node]));
|
|
5
|
+
const edges = new Map(previous.edges.map((edge) => [edge.id, edge]));
|
|
6
|
+
const ensureNode = (kind, id, label) => {
|
|
7
|
+
const key = nodeKey(kind, id);
|
|
8
|
+
if (!nodes.has(key)) {
|
|
9
|
+
nodes.set(key, { id: key, kind, label });
|
|
10
|
+
}
|
|
11
|
+
return key;
|
|
12
|
+
};
|
|
13
|
+
for (const fieldId of entry.changedFields) {
|
|
14
|
+
ensureNode("field", fieldId, labelLookup?.resolveFieldName(fieldId) ?? fieldId);
|
|
15
|
+
}
|
|
16
|
+
for (const ruleResult of entry.ruleResults) {
|
|
17
|
+
const ruleLabel = labelLookup?.resolveRuleName(ruleResult.ruleId) ?? ruleResult.ruleId;
|
|
18
|
+
const ruleNodeId = ensureNode("rule", ruleResult.ruleId, ruleLabel);
|
|
19
|
+
for (const fieldId of entry.changedFields) {
|
|
20
|
+
const fieldNodeId = ensureNode(
|
|
21
|
+
"field",
|
|
22
|
+
fieldId,
|
|
23
|
+
labelLookup?.resolveFieldName(fieldId) ?? fieldId
|
|
24
|
+
);
|
|
25
|
+
const id = edgeKey(fieldNodeId, ruleResult.ruleId, ruleNodeId, "read");
|
|
26
|
+
const existing = edges.get(id);
|
|
27
|
+
edges.set(id, {
|
|
28
|
+
id,
|
|
29
|
+
source: fieldNodeId,
|
|
30
|
+
target: ruleNodeId,
|
|
31
|
+
effectType: "read",
|
|
32
|
+
fireCount: (existing?.fireCount ?? 0) + 1
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
for (const effect of ruleResult.effects) {
|
|
36
|
+
const targetKind = effect.type === "HIDESECTION" ? "section" : effect.type === "DISPLAYTEXT" || effect.type === "DISPLAYKEYVALUEPAIR" ? "feedback" : "field";
|
|
37
|
+
const targetNodeId = ensureNode(
|
|
38
|
+
targetKind,
|
|
39
|
+
effect.targetId,
|
|
40
|
+
targetKind === "section" ? labelLookup?.resolveSectionName(effect.targetId) ?? effect.targetId : targetKind === "field" ? labelLookup?.resolveFieldName(effect.targetId) ?? effect.targetId : effect.targetId
|
|
41
|
+
);
|
|
42
|
+
const id = edgeKey(ruleNodeId, ruleResult.ruleId, targetNodeId, effect.type);
|
|
43
|
+
const existing = edges.get(id);
|
|
44
|
+
edges.set(id, {
|
|
45
|
+
id,
|
|
46
|
+
source: ruleNodeId,
|
|
47
|
+
target: targetNodeId,
|
|
48
|
+
effectType: effect.type,
|
|
49
|
+
fireCount: (existing?.fireCount ?? 0) + 1
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
nodes: [...nodes.values()],
|
|
55
|
+
edges: [...edges.values()]
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function buildGraphFromTrace(entries, labelLookup) {
|
|
59
|
+
return entries.reduce(
|
|
60
|
+
(graph, entry) => accumulateGraph(graph, entry, labelLookup),
|
|
61
|
+
{ nodes: [], edges: [] }
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export { accumulateGraph, buildGraphFromTrace };
|
|
66
|
+
//# sourceMappingURL=buildGraph.js.map
|
|
67
|
+
//# sourceMappingURL=buildGraph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/buildGraph.ts"],"names":[],"mappings":"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","file":"buildGraph.js","sourcesContent":["import type { RuleTraceEntry } from '@nnkogift/dhis2-form-utils-hooks';\nimport type { DevtoolsLabelLookup } from './createLabelLookup.js';\n\nexport type GraphNodeKind = 'field' | 'section' | 'feedback' | 'rule';\n\nexport type GraphNode = {\n id: string;\n kind: GraphNodeKind;\n label: string;\n};\n\nexport type GraphEdge = {\n id: string;\n source: string;\n target: string;\n effectType?: string;\n fireCount: number;\n};\n\nexport type RuleDependencyGraph = {\n nodes: GraphNode[];\n edges: GraphEdge[];\n};\n\nconst nodeKey = (kind: GraphNodeKind, id: string) => `${kind}:${id}`;\n\nconst edgeKey = (source: string, ruleId: string, target: string, effectType?: string) =>\n `${source}|${ruleId}|${target}|${effectType ?? ''}`;\n\nexport function accumulateGraph(\n previous: RuleDependencyGraph,\n entry: RuleTraceEntry,\n labelLookup?: DevtoolsLabelLookup\n): RuleDependencyGraph {\n const nodes = new Map(previous.nodes.map((node) => [node.id, node]));\n const edges = new Map(previous.edges.map((edge) => [edge.id, edge]));\n\n const ensureNode = (kind: GraphNodeKind, id: string, label: string) => {\n const key = nodeKey(kind, id);\n if (!nodes.has(key)) {\n nodes.set(key, { id: key, kind, label });\n }\n return key;\n };\n\n for (const fieldId of entry.changedFields) {\n ensureNode('field', fieldId, labelLookup?.resolveFieldName(fieldId) ?? fieldId);\n }\n\n for (const ruleResult of entry.ruleResults) {\n const ruleLabel = labelLookup?.resolveRuleName(ruleResult.ruleId) ?? ruleResult.ruleId;\n const ruleNodeId = ensureNode('rule', ruleResult.ruleId, ruleLabel);\n\n for (const fieldId of entry.changedFields) {\n const fieldNodeId = ensureNode(\n 'field',\n fieldId,\n labelLookup?.resolveFieldName(fieldId) ?? fieldId\n );\n const id = edgeKey(fieldNodeId, ruleResult.ruleId, ruleNodeId, 'read');\n const existing = edges.get(id);\n edges.set(id, {\n id,\n source: fieldNodeId,\n target: ruleNodeId,\n effectType: 'read',\n fireCount: (existing?.fireCount ?? 0) + 1,\n });\n }\n\n for (const effect of ruleResult.effects) {\n const targetKind: GraphNodeKind =\n effect.type === 'HIDESECTION'\n ? 'section'\n : effect.type === 'DISPLAYTEXT' || effect.type === 'DISPLAYKEYVALUEPAIR'\n ? 'feedback'\n : 'field';\n\n const targetNodeId = ensureNode(\n targetKind,\n effect.targetId,\n targetKind === 'section'\n ? (labelLookup?.resolveSectionName(effect.targetId) ?? effect.targetId)\n : targetKind === 'field'\n ? (labelLookup?.resolveFieldName(effect.targetId) ?? effect.targetId)\n : effect.targetId\n );\n const id = edgeKey(ruleNodeId, ruleResult.ruleId, targetNodeId, effect.type);\n const existing = edges.get(id);\n edges.set(id, {\n id,\n source: ruleNodeId,\n target: targetNodeId,\n effectType: effect.type,\n fireCount: (existing?.fireCount ?? 0) + 1,\n });\n }\n }\n\n return {\n nodes: [...nodes.values()],\n edges: [...edges.values()],\n };\n}\n\nexport function buildGraphFromTrace(\n entries: readonly RuleTraceEntry[],\n labelLookup?: DevtoolsLabelLookup\n): RuleDependencyGraph {\n return entries.reduce<RuleDependencyGraph>(\n (graph, entry) => accumulateGraph(graph, entry, labelLookup),\n { nodes: [], edges: [] }\n );\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts"],"names":[],"mappings":"AAAO,MAAM,yBAAA,GAA4B","file":"constants.js","sourcesContent":["export const DEFAULT_TRACE_MAX_ENTRIES = 200;\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { EventProgramMetadata, TrackerProgramMetadata } from '@nnkogift/dhis2-form-utils-metadata';
|
|
2
|
+
|
|
3
|
+
type ProgramStageRef = {
|
|
4
|
+
id?: string;
|
|
5
|
+
displayName?: string;
|
|
6
|
+
};
|
|
7
|
+
type RuleDevtoolsMetadata = {
|
|
8
|
+
formKind: 'event';
|
|
9
|
+
metadata: EventProgramMetadata;
|
|
10
|
+
programStageId: string;
|
|
11
|
+
} | {
|
|
12
|
+
formKind: 'tracker';
|
|
13
|
+
metadata: TrackerProgramMetadata;
|
|
14
|
+
/** Stage names for rules that target a stage — the tracker metadata query itself has no stage list. */
|
|
15
|
+
programStages?: ProgramStageRef[];
|
|
16
|
+
};
|
|
17
|
+
type DevtoolsLabelLookup = {
|
|
18
|
+
resolveRuleName(id: string): string;
|
|
19
|
+
resolveFieldName(id: string): string;
|
|
20
|
+
resolveSectionName(id: string): string;
|
|
21
|
+
resolveStageName(id: string): string;
|
|
22
|
+
};
|
|
23
|
+
declare function createLabelLookup(source: RuleDevtoolsMetadata): DevtoolsLabelLookup;
|
|
24
|
+
|
|
25
|
+
export { type DevtoolsLabelLookup, type ProgramStageRef, type RuleDevtoolsMetadata, createLabelLookup };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { selectProgramStage } from '@nnkogift/dhis2-form-utils-metadata';
|
|
2
|
+
|
|
3
|
+
const createLookup = (rules, fields, sections, stages) => ({
|
|
4
|
+
resolveRuleName: (id) => rules.get(id) ?? id,
|
|
5
|
+
resolveFieldName: (id) => fields.get(id) ?? id,
|
|
6
|
+
resolveSectionName: (id) => sections.get(id) ?? id,
|
|
7
|
+
resolveStageName: (id) => stages.get(id) ?? id
|
|
8
|
+
});
|
|
9
|
+
function buildEventLookup(source) {
|
|
10
|
+
const rules = /* @__PURE__ */ new Map();
|
|
11
|
+
const fields = /* @__PURE__ */ new Map();
|
|
12
|
+
const sections = /* @__PURE__ */ new Map();
|
|
13
|
+
const stages = /* @__PURE__ */ new Map();
|
|
14
|
+
for (const rule of source.metadata.programRules) {
|
|
15
|
+
if (!rule.id) {
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
rules.set(rule.id, rule.displayName ?? rule.id);
|
|
19
|
+
}
|
|
20
|
+
const stage = selectProgramStage(
|
|
21
|
+
source.metadata,
|
|
22
|
+
source.programStageId
|
|
23
|
+
) ?? {
|
|
24
|
+
id: source.programStageId,
|
|
25
|
+
programStageDataElements: [],
|
|
26
|
+
programStageSections: []
|
|
27
|
+
};
|
|
28
|
+
for (const psde of stage.programStageDataElements ?? []) {
|
|
29
|
+
const de = psde.dataElement;
|
|
30
|
+
if (!de?.id) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
fields.set(de.id, de.displayFormName ?? de.displayName ?? de.id);
|
|
34
|
+
}
|
|
35
|
+
for (const section of stage.programStageSections ?? []) {
|
|
36
|
+
sections.set(section.id, section.displayName ?? section.id);
|
|
37
|
+
}
|
|
38
|
+
for (const programStage of source.metadata.programStages) {
|
|
39
|
+
if (!programStage.id) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
stages.set(programStage.id, programStage.displayName ?? programStage.id);
|
|
43
|
+
}
|
|
44
|
+
return createLookup(rules, fields, sections, stages);
|
|
45
|
+
}
|
|
46
|
+
function buildTrackerLookup(source) {
|
|
47
|
+
const rules = /* @__PURE__ */ new Map();
|
|
48
|
+
const fields = /* @__PURE__ */ new Map();
|
|
49
|
+
const sections = /* @__PURE__ */ new Map();
|
|
50
|
+
const stages = /* @__PURE__ */ new Map();
|
|
51
|
+
for (const rule of source.metadata.programRules) {
|
|
52
|
+
if (!rule.id) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
rules.set(rule.id, rule.name ?? rule.id);
|
|
56
|
+
}
|
|
57
|
+
for (const ptea of source.metadata.programTrackedEntityAttributes) {
|
|
58
|
+
const tea = ptea.trackedEntityAttribute;
|
|
59
|
+
if (!tea.id) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
fields.set(tea.id, tea.formName ?? tea.displayName ?? tea.id);
|
|
63
|
+
}
|
|
64
|
+
for (const section of source.metadata.programSections ?? []) {
|
|
65
|
+
sections.set(section.id, section.displayName ?? section.id);
|
|
66
|
+
}
|
|
67
|
+
for (const programStage of source.programStages ?? []) {
|
|
68
|
+
if (!programStage.id) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
stages.set(programStage.id, programStage.displayName ?? programStage.id);
|
|
72
|
+
}
|
|
73
|
+
return createLookup(rules, fields, sections, stages);
|
|
74
|
+
}
|
|
75
|
+
function createLabelLookup(source) {
|
|
76
|
+
return source.formKind === "event" ? buildEventLookup(source) : buildTrackerLookup(source);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { createLabelLookup };
|
|
80
|
+
//# sourceMappingURL=createLabelLookup.js.map
|
|
81
|
+
//# sourceMappingURL=createLabelLookup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/createLabelLookup.ts"],"names":[],"mappings":"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","file":"createLabelLookup.js","sourcesContent":["import type {\n EventProgramMetadata,\n ProgramStageMetadata,\n TrackerProgramMetadata,\n} from '@nnkogift/dhis2-form-utils-metadata';\nimport { selectProgramStage } from '@nnkogift/dhis2-form-utils-metadata';\n\nexport type ProgramStageRef = {\n id?: string;\n displayName?: string;\n};\n\nexport type RuleDevtoolsMetadata =\n | {\n formKind: 'event';\n metadata: EventProgramMetadata;\n programStageId: string;\n }\n | {\n formKind: 'tracker';\n metadata: TrackerProgramMetadata;\n /** Stage names for rules that target a stage — the tracker metadata query itself has no stage list. */\n programStages?: ProgramStageRef[];\n };\n\nexport type DevtoolsLabelLookup = {\n resolveRuleName(id: string): string;\n resolveFieldName(id: string): string;\n resolveSectionName(id: string): string;\n resolveStageName(id: string): string;\n};\n\nconst createLookup = (\n rules: Map<string, string>,\n fields: Map<string, string>,\n sections: Map<string, string>,\n stages: Map<string, string>\n): DevtoolsLabelLookup => ({\n resolveRuleName: (id) => rules.get(id) ?? id,\n resolveFieldName: (id) => fields.get(id) ?? id,\n resolveSectionName: (id) => sections.get(id) ?? id,\n resolveStageName: (id) => stages.get(id) ?? id,\n});\n\nfunction buildEventLookup(source: Extract<RuleDevtoolsMetadata, { formKind: 'event' }>) {\n const rules = new Map<string, string>();\n const fields = new Map<string, string>();\n const sections = new Map<string, string>();\n const stages = new Map<string, string>();\n\n for (const rule of source.metadata.programRules) {\n if (!rule.id) {\n continue;\n }\n rules.set(rule.id, rule.displayName ?? rule.id);\n }\n\n const stage: ProgramStageMetadata = selectProgramStage(\n source.metadata,\n source.programStageId\n ) ?? {\n id: source.programStageId,\n programStageDataElements: [],\n programStageSections: [],\n };\n\n for (const psde of stage.programStageDataElements ?? []) {\n const de = psde.dataElement;\n if (!de?.id) {\n continue;\n }\n fields.set(de.id, de.displayFormName ?? de.displayName ?? de.id);\n }\n\n for (const section of stage.programStageSections ?? []) {\n sections.set(section.id, section.displayName ?? section.id);\n }\n\n for (const programStage of source.metadata.programStages) {\n if (!programStage.id) {\n continue;\n }\n stages.set(programStage.id, programStage.displayName ?? programStage.id);\n }\n\n return createLookup(rules, fields, sections, stages);\n}\n\nfunction buildTrackerLookup(source: Extract<RuleDevtoolsMetadata, { formKind: 'tracker' }>) {\n const rules = new Map<string, string>();\n const fields = new Map<string, string>();\n const sections = new Map<string, string>();\n const stages = new Map<string, string>();\n\n for (const rule of source.metadata.programRules) {\n if (!rule.id) {\n continue;\n }\n rules.set(rule.id, rule.name ?? rule.id);\n }\n\n for (const ptea of source.metadata.programTrackedEntityAttributes) {\n const tea = ptea.trackedEntityAttribute;\n if (!tea.id) {\n continue;\n }\n fields.set(tea.id, tea.formName ?? tea.displayName ?? tea.id);\n }\n\n for (const section of source.metadata.programSections ?? []) {\n sections.set(section.id, section.displayName ?? section.id);\n }\n\n for (const programStage of source.programStages ?? []) {\n if (!programStage.id) {\n continue;\n }\n stages.set(programStage.id, programStage.displayName ?? programStage.id);\n }\n\n return createLookup(rules, fields, sections, stages);\n}\n\nexport function createLabelLookup(source: RuleDevtoolsMetadata): DevtoolsLabelLookup {\n return source.formKind === 'event' ? buildEventLookup(source) : buildTrackerLookup(source);\n}\n"]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { IconProps } from '@dhis2/ui';
|
|
3
|
+
|
|
4
|
+
type EffectVisualVariant = 'hide' | 'show' | 'assign' | 'mandatory' | 'warning' | 'error' | 'feedback' | 'message' | 'read' | 'default';
|
|
5
|
+
type EffectVisual = {
|
|
6
|
+
variant: EffectVisualVariant;
|
|
7
|
+
tagClassName: string;
|
|
8
|
+
edgeStroke: string;
|
|
9
|
+
shortLabel: string;
|
|
10
|
+
};
|
|
11
|
+
declare const EFFECT_ICONS: Record<EffectVisualVariant, FC<IconProps>>;
|
|
12
|
+
/** @deprecated Use getEffectVisual().variant */
|
|
13
|
+
type EffectTagVariant = EffectVisualVariant;
|
|
14
|
+
declare function getEffectVariant(type: string): EffectVisualVariant;
|
|
15
|
+
declare function getEffectVisual(type: string): EffectVisual;
|
|
16
|
+
declare function getEffectTagVariant(type: string): EffectVisualVariant;
|
|
17
|
+
type EffectTagRenderProps = {
|
|
18
|
+
neutral?: boolean;
|
|
19
|
+
positive?: boolean;
|
|
20
|
+
negative?: boolean;
|
|
21
|
+
className?: string;
|
|
22
|
+
};
|
|
23
|
+
declare function getEffectTagRenderProps(type: string): EffectTagRenderProps;
|
|
24
|
+
declare function getEffectTagRenderPropsForVariant(variant: EffectVisualVariant): EffectTagRenderProps;
|
|
25
|
+
declare function getEffectEdgeStroke(type: string, highlighted?: boolean): string;
|
|
26
|
+
declare function getEffectShortLabel(type: string): string;
|
|
27
|
+
|
|
28
|
+
export { EFFECT_ICONS, type EffectTagRenderProps, type EffectTagVariant, type EffectVisual, type EffectVisualVariant, getEffectEdgeStroke, getEffectShortLabel, getEffectTagRenderProps, getEffectTagRenderPropsForVariant, getEffectTagVariant, getEffectVariant, getEffectVisual };
|