@truedat/dd 8.7.3 → 8.7.4
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/package.json +3 -3
- package/src/components/StructureGrantCartCheckout.js +19 -25
- package/src/components/StructureGrantCartInformation.js +4 -1
- package/src/components/__tests__/StructureGrantCartCheckout.spec.js +40 -0
- package/src/hooks/useTemplatesByIds.js +55 -20
- package/src/reducers/__tests__/grantRequestsCart.spec.js +16 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/dd",
|
|
3
|
-
"version": "8.7.
|
|
3
|
+
"version": "8.7.4",
|
|
4
4
|
"description": "Truedat Web Data Dictionary",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"module": "src/index.js",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"@testing-library/jest-dom": "^6.6.3",
|
|
52
52
|
"@testing-library/react": "^16.3.0",
|
|
53
53
|
"@testing-library/user-event": "^14.6.1",
|
|
54
|
-
"@truedat/test": "8.7.
|
|
54
|
+
"@truedat/test": "8.7.4",
|
|
55
55
|
"identity-obj-proxy": "^3.0.0",
|
|
56
56
|
"jest": "^29.7.0",
|
|
57
57
|
"redux-saga-test-plan": "^4.0.6"
|
|
@@ -86,5 +86,5 @@
|
|
|
86
86
|
"svg-pan-zoom": "^3.6.2",
|
|
87
87
|
"swr": "^2.3.3"
|
|
88
88
|
},
|
|
89
|
-
"gitHead": "
|
|
89
|
+
"gitHead": "74bf59ddf29e05b518dc206271c4f1215d66a942"
|
|
90
90
|
}
|
|
@@ -75,11 +75,11 @@ const getGroupedStructuresByDomainAndTemplate = (
|
|
|
75
75
|
|
|
76
76
|
const templateId = isExplicitSystem
|
|
77
77
|
? (systemToTemplateId[normalizedSystemIdStr] ?? defaultTemplateId)
|
|
78
|
-
:
|
|
78
|
+
: null;
|
|
79
79
|
|
|
80
80
|
const shouldGroupByDomain = isExplicitSystem
|
|
81
81
|
? systemGroupByDomain[normalizedSystemIdStr] === true
|
|
82
|
-
: defaultGroupByDomain === true
|
|
82
|
+
: defaultGroupByDomain === true;
|
|
83
83
|
|
|
84
84
|
const systemKey = isExplicitSystem ? normalizedSystemIdStr : "others";
|
|
85
85
|
|
|
@@ -161,16 +161,16 @@ export const StructureGrantCartCheckout = ({
|
|
|
161
161
|
|
|
162
162
|
const getTemplateIdFromKey = (key) => {
|
|
163
163
|
const parts = key.split("_");
|
|
164
|
-
const templatePart = parts[
|
|
164
|
+
const templatePart = parts[parts.length - 1];
|
|
165
165
|
if (templatePart === "notype" || !templatePart) {
|
|
166
|
-
return
|
|
166
|
+
return null;
|
|
167
167
|
}
|
|
168
168
|
return Number(templatePart) || templatePart;
|
|
169
169
|
};
|
|
170
170
|
|
|
171
171
|
const getDomainIdsFromKey = (key) => {
|
|
172
172
|
const parts = key.split("_");
|
|
173
|
-
const domainPart = parts
|
|
173
|
+
const domainPart = parts.slice(0, -2).join("_");
|
|
174
174
|
if (domainPart === "nodomain" || !domainPart) {
|
|
175
175
|
return null;
|
|
176
176
|
}
|
|
@@ -240,7 +240,7 @@ export const StructureGrantCartCheckout = ({
|
|
|
240
240
|
k,
|
|
241
241
|
{
|
|
242
242
|
template: undefined,
|
|
243
|
-
templateContent:
|
|
243
|
+
templateContent: undefined,
|
|
244
244
|
valid: false,
|
|
245
245
|
},
|
|
246
246
|
]),
|
|
@@ -256,20 +256,13 @@ export const StructureGrantCartCheckout = ({
|
|
|
256
256
|
if (!allLoaded) return;
|
|
257
257
|
const getTemplateById = (tid) =>
|
|
258
258
|
tid != null ? (templatesById[String(tid)] ?? templatesById[tid]) : null;
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
templateContent: {},
|
|
267
|
-
valid: false,
|
|
268
|
-
},
|
|
269
|
-
];
|
|
270
|
-
}),
|
|
271
|
-
);
|
|
272
|
-
initGroupTemplates(initial);
|
|
259
|
+
groupKeys.forEach((k) => {
|
|
260
|
+
const templateObj = getTemplateById(effectiveTemplateIdByKey[k]);
|
|
261
|
+
const t = templateObj?.name;
|
|
262
|
+
if (t) {
|
|
263
|
+
selectGrantRequestTemplateForGroup({ key: k, template: t });
|
|
264
|
+
}
|
|
265
|
+
});
|
|
273
266
|
}, [
|
|
274
267
|
isMultiGroup,
|
|
275
268
|
groupKeys.join(","),
|
|
@@ -277,7 +270,7 @@ export const StructureGrantCartCheckout = ({
|
|
|
277
270
|
defaultTemplateId,
|
|
278
271
|
templatesById,
|
|
279
272
|
effectiveTemplateIdByKey,
|
|
280
|
-
|
|
273
|
+
selectGrantRequestTemplateForGroup,
|
|
281
274
|
]);
|
|
282
275
|
|
|
283
276
|
useEffect(() => {
|
|
@@ -430,6 +423,7 @@ export const StructureGrantCartCheckout = ({
|
|
|
430
423
|
const groupDomainIds = getUniqueDomainIds(groupStructures);
|
|
431
424
|
const groupData = groupTemplates[key] ?? {};
|
|
432
425
|
const selectedTemplate = systemTemplates[key];
|
|
426
|
+
const autoTemplateName = selectedTemplate?.name;
|
|
433
427
|
const domainName = domainNamesByKey[key];
|
|
434
428
|
const systemNames = getUniqueSystemName(groupStructures);
|
|
435
429
|
|
|
@@ -462,7 +456,7 @@ export const StructureGrantCartCheckout = ({
|
|
|
462
456
|
>
|
|
463
457
|
{formatMessage({ id: systemMessageId })}:{" "}
|
|
464
458
|
<span style={{ fontWeight: "normal" }}>
|
|
465
|
-
{key.split("_")
|
|
459
|
+
{key.split("_").at(-2) === "others"
|
|
466
460
|
? formatMessage({
|
|
467
461
|
id: "grantRequest.cart.group.others",
|
|
468
462
|
})
|
|
@@ -494,11 +488,11 @@ export const StructureGrantCartCheckout = ({
|
|
|
494
488
|
<Suspense fallback={null}>
|
|
495
489
|
<SelectableDynamicForm
|
|
496
490
|
scope="gr"
|
|
497
|
-
content={groupData.templateContent ??
|
|
491
|
+
content={groupData.templateContent ?? null}
|
|
498
492
|
domainIds={groupDomainIds}
|
|
499
493
|
hideLabel
|
|
500
494
|
isModification={!!modificationGrant}
|
|
501
|
-
|
|
495
|
+
name={autoTemplateName}
|
|
502
496
|
disableSelector={!!selectedTemplate}
|
|
503
497
|
onChange={({ content, valid }) =>
|
|
504
498
|
updateGrantRequestTemplateContentForGroup({
|
|
@@ -536,7 +530,7 @@ export const StructureGrantCartCheckout = ({
|
|
|
536
530
|
<Grid.Column width={5}>
|
|
537
531
|
<StructureGrantCartInformation
|
|
538
532
|
isModification={!!modificationGrant}
|
|
539
|
-
|
|
533
|
+
name={singleSystemTemplate?.name}
|
|
540
534
|
disableSelector={!!singleSystemTemplate}
|
|
541
535
|
/>
|
|
542
536
|
</Grid.Column>
|
|
@@ -26,6 +26,7 @@ export const StructureGrantCartInformation = ({
|
|
|
26
26
|
updateGrantRequestTemplateContent,
|
|
27
27
|
selectedTemplate,
|
|
28
28
|
disableSelector,
|
|
29
|
+
name: autoTemplateName,
|
|
29
30
|
}) => {
|
|
30
31
|
const { formatMessage } = useIntl();
|
|
31
32
|
const templateContent = _.pathOr({}, "templateContent")(grantRequestsCart);
|
|
@@ -36,6 +37,7 @@ export const StructureGrantCartInformation = ({
|
|
|
36
37
|
fetchPolicy: "cache-and-network",
|
|
37
38
|
variables: { action: "createForeignGrantRequest" },
|
|
38
39
|
});
|
|
40
|
+
|
|
39
41
|
return (
|
|
40
42
|
<Segment loading={loading}>
|
|
41
43
|
<Form>
|
|
@@ -68,7 +70,7 @@ export const StructureGrantCartInformation = ({
|
|
|
68
70
|
id: `structure.grant.cart.template.placeholder`,
|
|
69
71
|
})}
|
|
70
72
|
required
|
|
71
|
-
|
|
73
|
+
name={autoTemplateName}
|
|
72
74
|
disableSelector={disableSelector}
|
|
73
75
|
/>
|
|
74
76
|
</Form>
|
|
@@ -83,6 +85,7 @@ StructureGrantCartInformation.propTypes = {
|
|
|
83
85
|
isModification: PropTypes.bool,
|
|
84
86
|
selectedTemplate: PropTypes.object,
|
|
85
87
|
disableSelector: PropTypes.bool,
|
|
88
|
+
name: PropTypes.string,
|
|
86
89
|
};
|
|
87
90
|
|
|
88
91
|
const mapStateToProps = ({ grantRequestsCart }) => ({ grantRequestsCart });
|
|
@@ -357,4 +357,44 @@ describe("StructureGrantCartCheckout", () => {
|
|
|
357
357
|
await waitForLoad(rendered);
|
|
358
358
|
expect(rendered.container).toMatchSnapshot();
|
|
359
359
|
});
|
|
360
|
+
|
|
361
|
+
it("calls selectGrantRequestTemplateForGroup (not initGroupTemplates) when templates loaded", async () => {
|
|
362
|
+
useWebContext.mockReturnValue({ scopesWithRelations: ["gr"] });
|
|
363
|
+
useTemplateRelations.mockReturnValue({
|
|
364
|
+
resource: [
|
|
365
|
+
{ resource_id: 10, template_id: 1 },
|
|
366
|
+
{ resource_id: 20, template_id: 2 },
|
|
367
|
+
],
|
|
368
|
+
});
|
|
369
|
+
useTemplatesByIds.mockReturnValue({
|
|
370
|
+
1: { name: "Template A", content: [] },
|
|
371
|
+
2: { name: "Template B", content: [] },
|
|
372
|
+
});
|
|
373
|
+
const props = {
|
|
374
|
+
...defaultProps,
|
|
375
|
+
grantRequestsCart: grantRequestsCartMultiGroup,
|
|
376
|
+
};
|
|
377
|
+
const renderOpts = {
|
|
378
|
+
state: { grantRequestsCart: grantRequestsCartMultiGroup },
|
|
379
|
+
mocks: [
|
|
380
|
+
singleTemplateMock({ scope: "gr" }),
|
|
381
|
+
domainsMock({ action: "createForeignGrantRequest" }),
|
|
382
|
+
],
|
|
383
|
+
};
|
|
384
|
+
const rendered = render(
|
|
385
|
+
<StructureGrantCartCheckout {...props} />,
|
|
386
|
+
renderOpts,
|
|
387
|
+
);
|
|
388
|
+
await waitForLoad(rendered);
|
|
389
|
+
expect(mockSelectGrantRequestTemplateForGroup).toHaveBeenCalledTimes(2);
|
|
390
|
+
expect(mockSelectGrantRequestTemplateForGroup).toHaveBeenCalledWith({
|
|
391
|
+
key: "nodomain_10_1",
|
|
392
|
+
template: "Template A",
|
|
393
|
+
});
|
|
394
|
+
expect(mockSelectGrantRequestTemplateForGroup).toHaveBeenCalledWith({
|
|
395
|
+
key: "nodomain_20_2",
|
|
396
|
+
template: "Template B",
|
|
397
|
+
});
|
|
398
|
+
expect(mockInitGroupTemplates).not.toHaveBeenCalled();
|
|
399
|
+
});
|
|
360
400
|
});
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
|
-
import { useState, useEffect } from "react";
|
|
2
|
+
import { useState, useEffect, useMemo } from "react";
|
|
3
|
+
import { useQuery } from "@apollo/client";
|
|
4
|
+
import { TEMPLATES_QUERY } from "@truedat/core/api/queries";
|
|
3
5
|
import { apiJson } from "@truedat/core/services/api";
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
const normalizeTemplate = (raw) => {
|
|
6
8
|
if (!raw || typeof raw !== "object") return null;
|
|
7
9
|
const inner = raw?.data && typeof raw.data === "object" ? raw.data : raw;
|
|
8
10
|
const content = _.isArray(inner?.content)
|
|
@@ -23,25 +25,56 @@ const ensureTemplateShape = (t) => {
|
|
|
23
25
|
};
|
|
24
26
|
};
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
const TEMPLATES_SCOPE = "gr";
|
|
29
|
+
|
|
30
|
+
const parseIdList = _.flow(
|
|
31
|
+
_.split(","),
|
|
32
|
+
_.map((s) => parseInt(s.trim(), 10)),
|
|
33
|
+
_.reject(Number.isNaN),
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
export const useTemplatesByIds = (ids, domainIds) => {
|
|
37
|
+
const [restTemplates, setRestTemplates] = useState({});
|
|
28
38
|
const idsKey = Array.isArray(ids) && ids.length > 0 ? ids.join(",") : "";
|
|
39
|
+
const domainIdsKey =
|
|
40
|
+
Array.isArray(domainIds) && domainIds.length > 0 ? domainIds.join(",") : "";
|
|
41
|
+
const hasIds = !!idsKey;
|
|
42
|
+
const hasDomainIds = !!domainIdsKey;
|
|
43
|
+
|
|
44
|
+
const { data } = useQuery(TEMPLATES_QUERY, {
|
|
45
|
+
variables: { scope: TEMPLATES_SCOPE, domainIds },
|
|
46
|
+
skip: !hasIds || !hasDomainIds,
|
|
47
|
+
fetchPolicy: "cache-and-network",
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const preprocessedTemplates = useMemo(() => {
|
|
51
|
+
if (!data?.templates || !hasIds) return null;
|
|
52
|
+
const idList = parseIdList(idsKey);
|
|
53
|
+
if (idList.length === 0) return null;
|
|
54
|
+
const map = _.reduce(
|
|
55
|
+
(acc, id) => {
|
|
56
|
+
const t = data.templates.find((tpl) => String(tpl.id) === String(id));
|
|
57
|
+
return t ? _.set(id, t, acc) : acc;
|
|
58
|
+
},
|
|
59
|
+
{},
|
|
60
|
+
idList,
|
|
61
|
+
);
|
|
62
|
+
return map;
|
|
63
|
+
}, [data, idsKey, hasIds]);
|
|
29
64
|
|
|
30
65
|
useEffect(() => {
|
|
31
|
-
if (!
|
|
32
|
-
|
|
66
|
+
if (!hasIds || hasDomainIds) {
|
|
67
|
+
setRestTemplates({});
|
|
33
68
|
return;
|
|
34
69
|
}
|
|
35
|
-
const idList = idsKey
|
|
36
|
-
.split(",")
|
|
37
|
-
.map((s) => parseInt(s.trim(), 10))
|
|
38
|
-
.filter((n) => !Number.isNaN(n));
|
|
70
|
+
const idList = parseIdList(idsKey);
|
|
39
71
|
if (idList.length === 0) {
|
|
40
|
-
|
|
72
|
+
setRestTemplates({});
|
|
41
73
|
return;
|
|
42
74
|
}
|
|
43
75
|
// eslint-disable-next-line fp/no-let
|
|
44
76
|
let cancelled = false;
|
|
77
|
+
|
|
45
78
|
Promise.all(
|
|
46
79
|
idList.map((id) =>
|
|
47
80
|
apiJson(`/api/templates/${id}`).then((res) => ({
|
|
@@ -52,20 +85,22 @@ export const useTemplatesByIds = (ids) => {
|
|
|
52
85
|
)
|
|
53
86
|
.then((results) => {
|
|
54
87
|
if (cancelled) return;
|
|
55
|
-
const map =
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
88
|
+
const map = _.reduce(
|
|
89
|
+
(acc, { id, raw }) => {
|
|
90
|
+
const t = ensureTemplateShape(normalizeTemplate(raw) ?? raw);
|
|
91
|
+
return t ? _.set(id, t, acc) : acc;
|
|
92
|
+
},
|
|
93
|
+
{},
|
|
94
|
+
results,
|
|
95
|
+
);
|
|
96
|
+
setRestTemplates(map);
|
|
62
97
|
})
|
|
63
98
|
.catch(() => {});
|
|
64
99
|
return () => {
|
|
65
100
|
// eslint-disable-next-line fp/no-mutation
|
|
66
101
|
cancelled = true;
|
|
67
102
|
};
|
|
68
|
-
}, [idsKey]);
|
|
103
|
+
}, [idsKey, domainIdsKey, hasIds, hasDomainIds]);
|
|
69
104
|
|
|
70
|
-
return
|
|
105
|
+
return preprocessedTemplates !== null ? preprocessedTemplates : restTemplates;
|
|
71
106
|
};
|
|
@@ -140,6 +140,22 @@ describe("reducers: grantRequestsCart", () => {
|
|
|
140
140
|
).toEqual(expectedState);
|
|
141
141
|
});
|
|
142
142
|
|
|
143
|
+
it("should reset templateContent on selectGrantRequestTemplate.TRIGGER", () => {
|
|
144
|
+
const stateWithContent = {
|
|
145
|
+
...initialState,
|
|
146
|
+
templateContent: { field1: { value: "x", origin: "default" } },
|
|
147
|
+
};
|
|
148
|
+
expect(
|
|
149
|
+
grantRequestsCart(stateWithContent, {
|
|
150
|
+
type: selectGrantRequestTemplate.TRIGGER,
|
|
151
|
+
payload: "another_template",
|
|
152
|
+
}),
|
|
153
|
+
).toEqual({
|
|
154
|
+
...initialState,
|
|
155
|
+
template: "another_template",
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
143
159
|
it("should handle the updateGrantRequestTemplateContent.TRIGGER with valid content", () => {
|
|
144
160
|
const stateWithTemplate = {
|
|
145
161
|
...initialState,
|