@truedat/dd 8.2.4 → 8.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/src/api.js +2 -0
- package/src/components/GrantRequestCartResult.js +132 -0
- package/src/components/GrantRoutes.js +5 -16
- package/src/components/StructureGrantCart.js +11 -6
- package/src/components/StructureGrantCartCheckout.js +357 -40
- package/src/components/StructureGrantCartInformation.js +6 -0
- package/src/components/StructureGrantCartUserSelector.js +23 -8
- package/src/components/__tests__/GrantRequestCartResult.spec.js +79 -0
- package/src/components/__tests__/StructureGrantCartCheckout.spec.js +110 -8
- package/src/components/__tests__/__snapshots__/GrantRequestCartResult.spec.js.snap +179 -0
- package/src/components/__tests__/__snapshots__/StructureGrantCartCheckout.spec.js.snap +294 -1
- package/src/hooks/useCheckoutGrantRequest.js +16 -0
- package/src/hooks/useGrantRequestGroupsByIds.js +22 -0
- package/src/hooks/useSystems.js +27 -0
- package/src/hooks/useTemplatesByIds.js +66 -0
- package/src/messages/en.js +14 -0
- package/src/messages/es.js +14 -0
- package/src/reducers/__tests__/grantRequestsCart.spec.js +70 -3
- package/src/reducers/ddMessage.js +31 -23
- package/src/reducers/grantRequestsCart.js +35 -1
- package/src/reducers/structureRedirect.js +11 -1
- package/src/routines.js +7 -0
- package/src/sagas/index.js +0 -3
- package/src/selectors/__tests__/messages.spec.js +56 -0
- package/src/selectors/getParsedEvents.js +3 -1
- package/src/selectors/messages.js +49 -49
- package/src/styles/grantCartUserSelector.less +3 -0
- package/src/sagas/operateGrantRequestCart.js +0 -26
|
@@ -1,46 +1,284 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
2
|
import PropTypes from "prop-types";
|
|
3
|
+
import { useEffect, useMemo, Suspense } from "react";
|
|
3
4
|
import { Header, Segment, Grid, Button, GridColumn } from "semantic-ui-react";
|
|
4
5
|
import { bindActionCreators } from "redux";
|
|
5
|
-
import { connect } from "react-redux";
|
|
6
|
+
import { connect, useDispatch } from "react-redux";
|
|
6
7
|
import { HistoryBackButton } from "@truedat/core/components";
|
|
7
8
|
import { useIntl, FormattedMessage } from "react-intl";
|
|
8
|
-
import {
|
|
9
|
+
import { lazy } from "react";
|
|
10
|
+
import {
|
|
11
|
+
checkoutGrantRequest,
|
|
12
|
+
initGroupTemplates,
|
|
13
|
+
selectGrantRequestTemplate,
|
|
14
|
+
selectGrantRequestTemplateForGroup,
|
|
15
|
+
updateGrantRequestTemplateContentForGroup,
|
|
16
|
+
} from "../routines";
|
|
9
17
|
import StructureGrantCart from "./StructureGrantCart";
|
|
10
18
|
import StructureGrantCartInformation from "./StructureGrantCartInformation";
|
|
11
|
-
import
|
|
19
|
+
import StructureGrantCartUserSelector from "./StructureGrantCartUserSelector";
|
|
20
|
+
import { useWebContext } from "@truedat/core/webContext";
|
|
21
|
+
import { useTemplateRelations } from "@truedat/df/hooks/useTemplateRelations";
|
|
22
|
+
import { useCheckoutGrantRequest } from "../hooks/useCheckoutGrantRequest";
|
|
23
|
+
import { useTemplatesByIds } from "../hooks/useTemplatesByIds";
|
|
24
|
+
|
|
25
|
+
const SelectableDynamicForm = lazy(
|
|
26
|
+
() => import("@truedat/df/components/SelectableDynamicForm")
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const getGroupedStructuresByTemplate = (
|
|
30
|
+
structures,
|
|
31
|
+
templateResourceRelations,
|
|
32
|
+
defaultTemplateId
|
|
33
|
+
) => {
|
|
34
|
+
const systemToTemplateId = _.fromPairs(
|
|
35
|
+
(templateResourceRelations ?? []).map((r) => [
|
|
36
|
+
r.resource_id != null ? Number(r.resource_id) || r.resource_id : null,
|
|
37
|
+
r.template_id != null ? Number(r.template_id) || r.template_id : null,
|
|
38
|
+
]).filter(([sid]) => sid != null)
|
|
39
|
+
);
|
|
40
|
+
return _.reduce(
|
|
41
|
+
(acc, structure) => {
|
|
42
|
+
const systemId = structure.system_id ?? structure.system?.id ?? null;
|
|
43
|
+
const normalizedSystemId =
|
|
44
|
+
systemId != null ? Number(systemId) || systemId : null;
|
|
45
|
+
const templateId =
|
|
46
|
+
normalizedSystemId != null
|
|
47
|
+
? systemToTemplateId[normalizedSystemId] ?? defaultTemplateId
|
|
48
|
+
: defaultTemplateId;
|
|
49
|
+
const key =
|
|
50
|
+
templateId != null ? String(templateId) : "others";
|
|
51
|
+
const list = acc[key] ?? [];
|
|
52
|
+
return { ...acc, [key]: [...list, structure] };
|
|
53
|
+
},
|
|
54
|
+
{},
|
|
55
|
+
structures ?? []
|
|
56
|
+
);
|
|
57
|
+
};
|
|
12
58
|
|
|
13
59
|
export const StructureGrantCartCheckout = ({
|
|
14
60
|
grantRequestsCart,
|
|
15
|
-
|
|
61
|
+
initGroupTemplates,
|
|
62
|
+
selectGrantRequestTemplate,
|
|
63
|
+
selectGrantRequestTemplateForGroup,
|
|
64
|
+
updateGrantRequestTemplateContentForGroup,
|
|
16
65
|
}) => {
|
|
66
|
+
const dispatch = useDispatch();
|
|
67
|
+
const { trigger, isMutating } = useCheckoutGrantRequest();
|
|
68
|
+
const { resource: templateResourceRelations, default: defaultRelation } =
|
|
69
|
+
useTemplateRelations({
|
|
70
|
+
resourceType: "system",
|
|
71
|
+
listAll: true,
|
|
72
|
+
});
|
|
73
|
+
const defaultTemplateId =
|
|
74
|
+
defaultRelation?.template_id != null
|
|
75
|
+
? Number(defaultRelation.template_id) || defaultRelation.template_id
|
|
76
|
+
: null;
|
|
17
77
|
const { formatMessage } = useIntl();
|
|
18
|
-
const [
|
|
78
|
+
const { scopesWithRelations = [] } = useWebContext();
|
|
79
|
+
const {
|
|
80
|
+
template,
|
|
81
|
+
templateContent,
|
|
82
|
+
modificationGrant,
|
|
83
|
+
validCart,
|
|
84
|
+
user,
|
|
85
|
+
structures = [],
|
|
86
|
+
groupTemplates = {},
|
|
87
|
+
} = grantRequestsCart;
|
|
88
|
+
|
|
89
|
+
const groupedStructures = getGroupedStructuresByTemplate(
|
|
90
|
+
structures,
|
|
91
|
+
templateResourceRelations,
|
|
92
|
+
defaultTemplateId
|
|
93
|
+
);
|
|
94
|
+
const groupKeys = _.keys(groupedStructures);
|
|
95
|
+
const isMultiGroup =
|
|
96
|
+
!modificationGrant &&
|
|
97
|
+
scopesWithRelations.includes("gr") &&
|
|
98
|
+
groupKeys.length > 1;
|
|
99
|
+
|
|
100
|
+
const singleGroupKey =
|
|
101
|
+
!modificationGrant &&
|
|
102
|
+
scopesWithRelations.includes("gr") &&
|
|
103
|
+
groupKeys.length === 1
|
|
104
|
+
? groupKeys[0]
|
|
105
|
+
: null;
|
|
106
|
+
|
|
107
|
+
const effectiveTemplateIdByKey = useMemo(
|
|
108
|
+
() =>
|
|
109
|
+
_.fromPairs(
|
|
110
|
+
groupKeys.map((k) => [
|
|
111
|
+
k,
|
|
112
|
+
k === "others" ? defaultTemplateId : Number(k) || k,
|
|
113
|
+
])
|
|
114
|
+
),
|
|
115
|
+
[groupKeys.join(","), defaultTemplateId]
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
const uniqueTemplateIds = useMemo(
|
|
119
|
+
() => _.uniq(_.compact(_.values(effectiveTemplateIdByKey))),
|
|
120
|
+
[effectiveTemplateIdByKey]
|
|
121
|
+
);
|
|
19
122
|
|
|
20
|
-
const
|
|
21
|
-
|
|
123
|
+
const singleTemplateId =
|
|
124
|
+
!isMultiGroup && singleGroupKey != null
|
|
125
|
+
? singleGroupKey === "others"
|
|
126
|
+
? defaultTemplateId
|
|
127
|
+
: Number(singleGroupKey) || singleGroupKey
|
|
128
|
+
: null;
|
|
129
|
+
|
|
130
|
+
const templateIdsToFetch = isMultiGroup
|
|
131
|
+
? uniqueTemplateIds
|
|
132
|
+
: singleTemplateId != null
|
|
133
|
+
? [singleTemplateId]
|
|
134
|
+
: [];
|
|
135
|
+
|
|
136
|
+
const templatesById = useTemplatesByIds(templateIdsToFetch);
|
|
137
|
+
|
|
138
|
+
const systemTemplates = useMemo(() => {
|
|
139
|
+
if (!isMultiGroup) return {};
|
|
140
|
+
const next = {};
|
|
141
|
+
groupKeys.forEach((k) => {
|
|
142
|
+
const tid = effectiveTemplateIdByKey[k];
|
|
143
|
+
const t =
|
|
144
|
+
tid != null
|
|
145
|
+
? templatesById[String(tid)] ?? templatesById[tid]
|
|
146
|
+
: null;
|
|
147
|
+
if (t) next[k] = t;
|
|
148
|
+
});
|
|
149
|
+
return next;
|
|
150
|
+
}, [isMultiGroup, groupKeys.join(","), effectiveTemplateIdByKey, templatesById]);
|
|
151
|
+
|
|
152
|
+
const singleSystemTemplate = useMemo(
|
|
153
|
+
() =>
|
|
154
|
+
singleTemplateId != null
|
|
155
|
+
? templatesById[String(singleTemplateId)] ??
|
|
156
|
+
templatesById[singleTemplateId] ??
|
|
157
|
+
null
|
|
158
|
+
: null,
|
|
159
|
+
[singleTemplateId, templatesById]
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
if (!isMultiGroup) return;
|
|
164
|
+
if (_.isEmpty(uniqueTemplateIds)) {
|
|
165
|
+
initGroupTemplates(
|
|
166
|
+
_.fromPairs(
|
|
167
|
+
groupKeys.map((k) => [
|
|
168
|
+
k,
|
|
169
|
+
{
|
|
170
|
+
template: k === "others" ? null : undefined,
|
|
171
|
+
templateContent: {},
|
|
172
|
+
valid: false,
|
|
173
|
+
},
|
|
174
|
+
])
|
|
175
|
+
)
|
|
176
|
+
);
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
const allLoaded = uniqueTemplateIds.every(
|
|
180
|
+
(id) =>
|
|
181
|
+
templatesById[String(id)] !== undefined ||
|
|
182
|
+
templatesById[id] !== undefined
|
|
183
|
+
);
|
|
184
|
+
if (!allLoaded) return;
|
|
185
|
+
const getTemplateById = (tid) =>
|
|
186
|
+
tid != null ? templatesById[String(tid)] ?? templatesById[tid] : null;
|
|
187
|
+
const initial = _.fromPairs(
|
|
188
|
+
groupKeys.map((k) => {
|
|
189
|
+
const t = getTemplateById(effectiveTemplateIdByKey[k])?.name;
|
|
190
|
+
return [
|
|
191
|
+
k,
|
|
192
|
+
{
|
|
193
|
+
template: t ?? (k === "others" ? null : undefined),
|
|
194
|
+
templateContent: {},
|
|
195
|
+
valid: false,
|
|
196
|
+
},
|
|
197
|
+
];
|
|
198
|
+
})
|
|
199
|
+
);
|
|
200
|
+
initGroupTemplates(initial);
|
|
201
|
+
}, [
|
|
202
|
+
isMultiGroup,
|
|
203
|
+
groupKeys.join(","),
|
|
204
|
+
uniqueTemplateIds.join(","),
|
|
205
|
+
defaultTemplateId,
|
|
206
|
+
templatesById,
|
|
207
|
+
effectiveTemplateIdByKey,
|
|
208
|
+
initGroupTemplates,
|
|
209
|
+
]);
|
|
210
|
+
|
|
211
|
+
useEffect(() => {
|
|
212
|
+
if (isMultiGroup || singleTemplateId == null || !singleSystemTemplate?.name)
|
|
213
|
+
return;
|
|
214
|
+
selectGrantRequestTemplate(singleSystemTemplate.name);
|
|
215
|
+
}, [
|
|
216
|
+
isMultiGroup,
|
|
217
|
+
singleTemplateId,
|
|
218
|
+
singleSystemTemplate?.name,
|
|
219
|
+
selectGrantRequestTemplate,
|
|
220
|
+
]);
|
|
221
|
+
|
|
222
|
+
const validCartMulti =
|
|
223
|
+
isMultiGroup &&
|
|
224
|
+
user?.valid &&
|
|
225
|
+
groupKeys.every(
|
|
226
|
+
(k) => groupTemplates[k]?.template && groupTemplates[k]?.valid
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
const canSubmit = isMultiGroup ? validCartMulti : validCart && user?.valid;
|
|
22
230
|
|
|
23
231
|
const checkout = () => {
|
|
24
|
-
|
|
25
|
-
|
|
232
|
+
let payload;
|
|
233
|
+
if (isMultiGroup) {
|
|
234
|
+
const grant_request_groups = groupKeys
|
|
235
|
+
.filter((k) => _.size(groupedStructures[k]) > 0)
|
|
236
|
+
.map((key) => {
|
|
237
|
+
const groupData = groupTemplates[key];
|
|
238
|
+
const templateName = groupData?.template;
|
|
239
|
+
const requests = _.map((structure) => ({
|
|
240
|
+
data_structure_id: structure.id,
|
|
241
|
+
filters: { rows: structure.filters },
|
|
242
|
+
metadata: groupData?.templateContent ?? {},
|
|
243
|
+
}))(groupedStructures[key]);
|
|
244
|
+
return _.omitBy(_.isNil)({
|
|
245
|
+
requests,
|
|
246
|
+
type: templateName,
|
|
247
|
+
modification_grant_id: modificationGrant?.id ?? null,
|
|
248
|
+
user_id: user?.id,
|
|
249
|
+
created_by_id: user?.id,
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
payload = { grant_request_groups };
|
|
253
|
+
} else {
|
|
254
|
+
const requests = _.map((structure) => ({
|
|
26
255
|
data_structure_id: structure.id,
|
|
27
|
-
filters: {
|
|
28
|
-
rows: structure.filters,
|
|
29
|
-
},
|
|
256
|
+
filters: { rows: structure.filters },
|
|
30
257
|
metadata: templateContent,
|
|
258
|
+
}))(structures);
|
|
259
|
+
payload = {
|
|
260
|
+
grant_request_group: _.omitBy(_.isNil)({
|
|
261
|
+
requests,
|
|
262
|
+
type: template,
|
|
263
|
+
modification_grant_id: modificationGrant?.id ?? null,
|
|
264
|
+
user_id: user?.id,
|
|
265
|
+
created_by_id: user?.id,
|
|
266
|
+
}),
|
|
31
267
|
};
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
268
|
+
}
|
|
269
|
+
dispatch(checkoutGrantRequest.request());
|
|
270
|
+
trigger(payload)
|
|
271
|
+
.then((data) => dispatch(checkoutGrantRequest.success(data)))
|
|
272
|
+
.catch((err) =>
|
|
273
|
+
dispatch(
|
|
274
|
+
checkoutGrantRequest.failure(
|
|
275
|
+
err?.response
|
|
276
|
+
? { status: err.response.status, data: err.response.data }
|
|
277
|
+
: err?.message
|
|
278
|
+
)
|
|
279
|
+
)
|
|
280
|
+
)
|
|
281
|
+
.finally(() => dispatch(checkoutGrantRequest.fulfill()));
|
|
44
282
|
};
|
|
45
283
|
|
|
46
284
|
return (
|
|
@@ -51,9 +289,7 @@ export const StructureGrantCartCheckout = ({
|
|
|
51
289
|
<Header as="h2">
|
|
52
290
|
<Header.Content>
|
|
53
291
|
<FormattedMessage
|
|
54
|
-
id={`grantRequest.header.${
|
|
55
|
-
modificationGrant ? "update" : "create"
|
|
56
|
-
}`}
|
|
292
|
+
id={`grantRequest.header.${modificationGrant ? "update" : "create"}`}
|
|
57
293
|
/>
|
|
58
294
|
</Header.Content>
|
|
59
295
|
</Header>
|
|
@@ -65,21 +301,91 @@ export const StructureGrantCartCheckout = ({
|
|
|
65
301
|
<Button
|
|
66
302
|
primary
|
|
67
303
|
onClick={checkout}
|
|
68
|
-
disabled={!
|
|
304
|
+
disabled={!canSubmit || isMutating}
|
|
69
305
|
content={formatMessage({ id: "actions.save" })}
|
|
70
306
|
/>
|
|
71
307
|
</GridColumn>
|
|
72
308
|
</Grid.Row>
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
<
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
309
|
+
{isMultiGroup ? (
|
|
310
|
+
<>
|
|
311
|
+
<Grid.Row>
|
|
312
|
+
<Grid.Column width={16}>
|
|
313
|
+
<Header as="h4">
|
|
314
|
+
<FormattedMessage id="grants.props.user_name" />
|
|
315
|
+
</Header>
|
|
316
|
+
<StructureGrantCartUserSelector spacedLabel />
|
|
317
|
+
</Grid.Column>
|
|
318
|
+
</Grid.Row>
|
|
319
|
+
{groupKeys.map((key) => {
|
|
320
|
+
const groupStructures = groupedStructures[key] ?? [];
|
|
321
|
+
if (_.isEmpty(groupStructures)) return null;
|
|
322
|
+
const isOthers = key === "others";
|
|
323
|
+
const groupData = groupTemplates[key] ?? {};
|
|
324
|
+
const selectedTemplate = systemTemplates[key];
|
|
325
|
+
return (
|
|
326
|
+
<Grid.Row key={key}>
|
|
327
|
+
<Grid.Column width={5}>
|
|
328
|
+
<Segment className="grant-cart-group-form">
|
|
329
|
+
<Header as="h4">
|
|
330
|
+
{isOthers ? (
|
|
331
|
+
<FormattedMessage id="grantRequest.cart.group.others" />
|
|
332
|
+
) : (
|
|
333
|
+
selectedTemplate?.name ?? key
|
|
334
|
+
)}
|
|
335
|
+
</Header>
|
|
336
|
+
<Suspense fallback={null}>
|
|
337
|
+
<SelectableDynamicForm
|
|
338
|
+
scope="gr"
|
|
339
|
+
content={groupData.templateContent ?? {}}
|
|
340
|
+
hideLabel
|
|
341
|
+
isModification={!!modificationGrant}
|
|
342
|
+
selectedTemplate={selectedTemplate}
|
|
343
|
+
disableSelector={!!selectedTemplate}
|
|
344
|
+
onChange={({ content, valid }) =>
|
|
345
|
+
updateGrantRequestTemplateContentForGroup({
|
|
346
|
+
key,
|
|
347
|
+
content,
|
|
348
|
+
valid,
|
|
349
|
+
})
|
|
350
|
+
}
|
|
351
|
+
onNameChange={(name) =>
|
|
352
|
+
selectGrantRequestTemplateForGroup({
|
|
353
|
+
key,
|
|
354
|
+
template: name,
|
|
355
|
+
})
|
|
356
|
+
}
|
|
357
|
+
placeholder={formatMessage({
|
|
358
|
+
id: "structure.grant.cart.template.placeholder",
|
|
359
|
+
})}
|
|
360
|
+
required
|
|
361
|
+
/>
|
|
362
|
+
</Suspense>
|
|
363
|
+
</Segment>
|
|
364
|
+
</Grid.Column>
|
|
365
|
+
<Grid.Column width={11}>
|
|
366
|
+
<StructureGrantCart
|
|
367
|
+
structureRequestGroups={groupStructures}
|
|
368
|
+
allowEmptyCart
|
|
369
|
+
/>
|
|
370
|
+
</Grid.Column>
|
|
371
|
+
</Grid.Row>
|
|
372
|
+
);
|
|
373
|
+
})}
|
|
374
|
+
</>
|
|
375
|
+
) : (
|
|
376
|
+
<Grid.Row>
|
|
377
|
+
<Grid.Column width={5}>
|
|
378
|
+
<StructureGrantCartInformation
|
|
379
|
+
isModification={!!modificationGrant}
|
|
380
|
+
selectedTemplate={singleSystemTemplate}
|
|
381
|
+
disableSelector={!!singleSystemTemplate}
|
|
382
|
+
/>
|
|
383
|
+
</Grid.Column>
|
|
384
|
+
<Grid.Column width={11}>
|
|
385
|
+
<StructureGrantCart />
|
|
386
|
+
</Grid.Column>
|
|
387
|
+
</Grid.Row>
|
|
388
|
+
)}
|
|
83
389
|
</Grid>
|
|
84
390
|
</Segment>
|
|
85
391
|
);
|
|
@@ -87,7 +393,10 @@ export const StructureGrantCartCheckout = ({
|
|
|
87
393
|
|
|
88
394
|
StructureGrantCartCheckout.propTypes = {
|
|
89
395
|
grantRequestsCart: PropTypes.object,
|
|
90
|
-
|
|
396
|
+
initGroupTemplates: PropTypes.func,
|
|
397
|
+
selectGrantRequestTemplate: PropTypes.func,
|
|
398
|
+
selectGrantRequestTemplateForGroup: PropTypes.func,
|
|
399
|
+
updateGrantRequestTemplateContentForGroup: PropTypes.func,
|
|
91
400
|
};
|
|
92
401
|
|
|
93
402
|
const mapStateToProps = ({ grantRequestsCart }) => ({
|
|
@@ -95,7 +404,15 @@ const mapStateToProps = ({ grantRequestsCart }) => ({
|
|
|
95
404
|
});
|
|
96
405
|
|
|
97
406
|
const mapDispatchToProps = (dispatch) =>
|
|
98
|
-
bindActionCreators(
|
|
407
|
+
bindActionCreators(
|
|
408
|
+
{
|
|
409
|
+
initGroupTemplates,
|
|
410
|
+
selectGrantRequestTemplate,
|
|
411
|
+
selectGrantRequestTemplateForGroup,
|
|
412
|
+
updateGrantRequestTemplateContentForGroup,
|
|
413
|
+
},
|
|
414
|
+
dispatch
|
|
415
|
+
);
|
|
99
416
|
|
|
100
417
|
export default connect(
|
|
101
418
|
mapStateToProps,
|
|
@@ -21,6 +21,8 @@ export const StructureGrantCartInformation = ({
|
|
|
21
21
|
isModification,
|
|
22
22
|
selectGrantRequestTemplate,
|
|
23
23
|
updateGrantRequestTemplateContent,
|
|
24
|
+
selectedTemplate,
|
|
25
|
+
disableSelector,
|
|
24
26
|
}) => {
|
|
25
27
|
const { formatMessage } = useIntl();
|
|
26
28
|
const templateContent = _.pathOr({}, "templateContent")(grantRequestsCart);
|
|
@@ -60,6 +62,8 @@ export const StructureGrantCartInformation = ({
|
|
|
60
62
|
id: `structure.grant.cart.template.placeholder`,
|
|
61
63
|
})}
|
|
62
64
|
required
|
|
65
|
+
selectedTemplate={selectedTemplate}
|
|
66
|
+
disableSelector={disableSelector}
|
|
63
67
|
/>
|
|
64
68
|
</Form>
|
|
65
69
|
</Segment>
|
|
@@ -71,6 +75,8 @@ StructureGrantCartInformation.propTypes = {
|
|
|
71
75
|
selectGrantRequestTemplate: PropTypes.func,
|
|
72
76
|
updateGrantRequestTemplateContent: PropTypes.func,
|
|
73
77
|
isModification: PropTypes.bool,
|
|
78
|
+
selectedTemplate: PropTypes.object,
|
|
79
|
+
disableSelector: PropTypes.bool,
|
|
74
80
|
};
|
|
75
81
|
|
|
76
82
|
const mapStateToProps = ({ grantRequestsCart }) => ({ grantRequestsCart });
|
|
@@ -14,6 +14,7 @@ import { updateGrantRequestUser } from "../routines";
|
|
|
14
14
|
export const StructureGrantCartUserSelector = ({
|
|
15
15
|
grantRequestsCart,
|
|
16
16
|
updateGrantRequestUser,
|
|
17
|
+
spacedLabel,
|
|
17
18
|
}) => {
|
|
18
19
|
const { formatMessage } = useIntl();
|
|
19
20
|
const [usersGroupsQuery, setUsersGroupsQuery] = useState("");
|
|
@@ -166,14 +167,27 @@ export const StructureGrantCartUserSelector = ({
|
|
|
166
167
|
selection
|
|
167
168
|
required={thirdParty}
|
|
168
169
|
label={
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
170
|
+
spacedLabel ? (
|
|
171
|
+
<span className="grant-cart-user-selector-label-spaced">
|
|
172
|
+
<Checkbox
|
|
173
|
+
label={formatMessage({ id: "grantRequestCart.user.label" })}
|
|
174
|
+
onChange={(e, data) => {
|
|
175
|
+
setThirdParty(data.checked);
|
|
176
|
+
selectUser(null);
|
|
177
|
+
}}
|
|
178
|
+
checked={thirdParty}
|
|
179
|
+
/>
|
|
180
|
+
</span>
|
|
181
|
+
) : (
|
|
182
|
+
<Checkbox
|
|
183
|
+
label={formatMessage({ id: "grantRequestCart.user.label" })}
|
|
184
|
+
onChange={(e, data) => {
|
|
185
|
+
setThirdParty(data.checked);
|
|
186
|
+
selectUser(null);
|
|
187
|
+
}}
|
|
188
|
+
checked={thirdParty}
|
|
189
|
+
/>
|
|
190
|
+
)
|
|
177
191
|
}
|
|
178
192
|
options={options}
|
|
179
193
|
value={userId}
|
|
@@ -186,6 +200,7 @@ export const StructureGrantCartUserSelector = ({
|
|
|
186
200
|
StructureGrantCartUserSelector.propTypes = {
|
|
187
201
|
grantRequestsCart: PropTypes.object,
|
|
188
202
|
updateGrantRequestUser: PropTypes.func,
|
|
203
|
+
spacedLabel: PropTypes.bool,
|
|
189
204
|
};
|
|
190
205
|
|
|
191
206
|
const mapStateToProps = ({ grantRequestsCart }) => ({
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { render, waitForLoad } from "@truedat/test/render";
|
|
2
|
+
import { GrantRequestCartResult } from "../GrantRequestCartResult";
|
|
3
|
+
|
|
4
|
+
jest.mock("../../hooks/useGrantRequestGroupsByIds", () => ({
|
|
5
|
+
useGrantRequestGroupsByIds: jest.fn(),
|
|
6
|
+
}));
|
|
7
|
+
|
|
8
|
+
jest.mock("react-router", () => {
|
|
9
|
+
const actual = jest.requireActual("react-router");
|
|
10
|
+
return {
|
|
11
|
+
...actual,
|
|
12
|
+
useParams: jest.fn(),
|
|
13
|
+
};
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const { useGrantRequestGroupsByIds } = require("../../hooks/useGrantRequestGroupsByIds");
|
|
17
|
+
const { useParams } = require("react-router");
|
|
18
|
+
|
|
19
|
+
describe("GrantRequestCartResult", () => {
|
|
20
|
+
it("matches snapshot when no ids in URL (empty)", async () => {
|
|
21
|
+
useParams.mockReturnValue({});
|
|
22
|
+
useGrantRequestGroupsByIds.mockReturnValue({
|
|
23
|
+
groups: [],
|
|
24
|
+
isLoading: false,
|
|
25
|
+
error: null,
|
|
26
|
+
});
|
|
27
|
+
const rendered = render(<GrantRequestCartResult />);
|
|
28
|
+
await waitForLoad(rendered);
|
|
29
|
+
expect(rendered.container).toMatchSnapshot();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("matches snapshot when ids in URL and hook returns groups", async () => {
|
|
33
|
+
useParams.mockReturnValue({ ids: "1-2" });
|
|
34
|
+
const groups = [
|
|
35
|
+
{ id: 1, type: "Template A" },
|
|
36
|
+
{ id: 2, type: "Template B" },
|
|
37
|
+
];
|
|
38
|
+
useGrantRequestGroupsByIds.mockReturnValue({
|
|
39
|
+
groups,
|
|
40
|
+
isLoading: false,
|
|
41
|
+
error: null,
|
|
42
|
+
});
|
|
43
|
+
const rendered = render(<GrantRequestCartResult />);
|
|
44
|
+
await waitForLoad(rendered);
|
|
45
|
+
expect(rendered.container).toMatchSnapshot();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("matches snapshot when groups have embedded requests with data structures", async () => {
|
|
49
|
+
useParams.mockReturnValue({ ids: "1" });
|
|
50
|
+
const groups = [
|
|
51
|
+
{
|
|
52
|
+
id: 1,
|
|
53
|
+
type: "Template A",
|
|
54
|
+
_embedded: {
|
|
55
|
+
requests: [
|
|
56
|
+
{
|
|
57
|
+
_embedded: {
|
|
58
|
+
data_structure: { id: 10, name: "Structure One", external_id: "ext-1" },
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
_embedded: {
|
|
63
|
+
data_structure: { id: 20, name: "Structure Two", external_id: "ext-2" },
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
];
|
|
70
|
+
useGrantRequestGroupsByIds.mockReturnValue({
|
|
71
|
+
groups,
|
|
72
|
+
isLoading: false,
|
|
73
|
+
error: null,
|
|
74
|
+
});
|
|
75
|
+
const rendered = render(<GrantRequestCartResult />);
|
|
76
|
+
await waitForLoad(rendered);
|
|
77
|
+
expect(rendered.container).toMatchSnapshot();
|
|
78
|
+
});
|
|
79
|
+
});
|