Skip to content

Commit c2d9e51

Browse files
GrantDLSjekabs-karklinsjekabskarklins
authored
feat: use template config for dynamic multiple choice (#1582)
Co-authored-by: Jekabs Karklins <58165815+jekabs-karklins@users.noreply.github.com> Co-authored-by: jekabskarklins <jekabs.karklins@ess.eu>
1 parent 3d60321 commit c2d9e51

17 files changed

Lines changed: 123 additions & 13 deletions

File tree

apps/backend/src/datasources/mockups/QuestionaryDataSource.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { DeepPartial } from './ProposalDataSource';
12
import {
23
DependenciesLogicOperator,
34
EvaluatorOperator,
@@ -29,7 +30,6 @@ import {
2930
TextInputConfig,
3031
} from '../../resolvers/types/FieldConfig';
3132
import { QuestionaryDataSource } from '../QuestionaryDataSource';
32-
import { DeepPartial } from './ProposalDataSource';
3333

3434
export let dummyQuestionarySteps: QuestionaryStep[];
3535
export let dummyQuestionary: Questionary;
@@ -74,6 +74,7 @@ export const dummyQuestionTemplateRelationFactory = (
7474
dummyQuestionFactory(values?.question),
7575
values?.sortOrder || Math.round(Math.random() * 100),
7676
values?.topicId || Math.round(Math.random() * 10),
77+
values?.templateId || Math.round(Math.random() * 100),
7778
values?.config || { ...new BooleanConfig(), readPermissions: [] },
7879
values?.dependencies as FieldDependency[],
7980
values?.dependenciesOperator as DependenciesLogicOperator

apps/backend/src/datasources/postgres/records.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,7 @@ export const createQuestionTemplateRelationObject = async <T extends DataType>(
931931
),
932932
record.topic_id,
933933
record.sort_order,
934+
record.template_id,
934935
createConfig<any>(record.data_type as DataType, transformedConfig),
935936
dependencies,
936937
record.dependencies_operator

apps/backend/src/models/Questionary.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export class Answer extends QuestionTemplateRelation {
2020
questionTemplateRelation.question,
2121
questionTemplateRelation.topicId,
2222
questionTemplateRelation.sortOrder,
23+
questionTemplateRelation.templateId,
2324
questionTemplateRelation.config,
2425
questionTemplateRelation.dependencies,
2526
questionTemplateRelation.dependenciesOperator

apps/backend/src/models/Template.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export class QuestionTemplateRelation {
8080
public question: Question,
8181
public topicId: number,
8282
public sortOrder: number,
83+
public templateId: number,
8384
public config: typeof FieldConfigType,
8485
public dependencies: FieldDependency[],
8586
public dependenciesOperator?: DependenciesLogicOperator

apps/backend/src/queries/TemplateQueries.spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,37 @@ describe('getDynamicMultipleChoiceOptions', () => {
152152

153153
expect(options).toEqual(['option1', 'option2']);
154154
});
155+
156+
it('should use the question template relation if a template ID is supplied', async () => {
157+
const templateDataSource = container.resolve<TemplateDataSourceMock>(
158+
Tokens.TemplateDataSource
159+
);
160+
const getQuestionSpy = jest.spyOn(templateDataSource, 'getQuestion');
161+
const getQuestionTemplateRelationSpy = jest.spyOn(
162+
templateDataSource,
163+
'getQuestionTemplateRelation'
164+
);
165+
jest.spyOn(global, 'fetch').mockImplementation(() =>
166+
Promise.resolve({
167+
json: () => Promise.resolve(['option1', 'option2']),
168+
ok: true,
169+
} as Response)
170+
);
171+
172+
const options = await templateQueries.getDynamicMultipleChoiceOptions(
173+
dummyUserWithRole,
174+
'dmcQuestionEmptyJsonPath',
175+
1
176+
);
177+
178+
expect(options).toEqual(['option1', 'option2']);
179+
expect(getQuestionTemplateRelationSpy).toHaveBeenCalledWith(
180+
'dmcQuestionEmptyJsonPath',
181+
1
182+
);
183+
expect(getQuestionSpy).not.toHaveBeenCalled();
184+
185+
getQuestionSpy.mockRestore();
186+
getQuestionTemplateRelationSpy.mockRestore();
187+
});
155188
});

apps/backend/src/queries/TemplateQueries.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,13 @@ export default class TemplateQueries {
9494
@Authorized()
9595
async getDynamicMultipleChoiceOptions(
9696
user: UserWithRole | null,
97-
questionId: string
97+
questionId: string,
98+
templateId?: number | null
9899
) {
99-
const question = await this.dataSource.getQuestion(questionId);
100+
const question = await this.getDynamicMultipleChoiceQuestion(
101+
questionId,
102+
templateId
103+
);
100104
if (!question) return [];
101105

102106
const config = question.config as DynamicMultipleChoiceConfig;
@@ -139,4 +143,26 @@ export default class TemplateQueries {
139143

140144
return [];
141145
}
146+
147+
private async getDynamicMultipleChoiceQuestion(
148+
questionId: string,
149+
templateId?: number | null
150+
): Promise<Question | null> {
151+
if (templateId !== null && templateId !== undefined) {
152+
const questionTemplateRelation =
153+
await this.dataSource.getQuestionTemplateRelation(
154+
questionId,
155+
templateId
156+
);
157+
158+
if (!questionTemplateRelation) return null;
159+
160+
return {
161+
...questionTemplateRelation.question,
162+
config: questionTemplateRelation.config,
163+
};
164+
}
165+
166+
return this.dataSource.getQuestion(questionId);
167+
}
142168
}
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Query, Ctx, Resolver, Arg } from 'type-graphql';
1+
import { Query, Ctx, Resolver, Arg, Int } from 'type-graphql';
22

33
import { ResolverContext } from '../../context';
44

@@ -7,11 +7,14 @@ export class DynamicMultipleChoiceQuery {
77
@Query(() => [String], { nullable: true })
88
getDynamicMultipleChoiceOptions(
99
@Arg('questionId', () => String) questionId: string,
10+
@Arg('templateId', () => Int, { nullable: true })
11+
templateId: number | null,
1012
@Ctx() context: ResolverContext
1113
) {
1214
return context.queries.template.getDynamicMultipleChoiceOptions(
1315
context.user,
14-
questionId
16+
questionId,
17+
templateId
1518
);
1619
}
1720
}

apps/backend/src/resolvers/types/QuestionTemplateRelation.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ export class QuestionTemplateRelation
1616
@Field(() => Int)
1717
public sortOrder: number;
1818

19+
@Field(() => Int)
20+
public templateId: number;
21+
1922
@Field(() => Int)
2023
public topicId: number;
2124

apps/e2e/cypress/fixtures/template_export.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
},
3838
"topicId": 1,
3939
"sortOrder": 0,
40+
"templateId": 1,
4041
"config": {
4142
"tooltip": "",
4243
"required": false,
@@ -78,6 +79,7 @@
7879
},
7980
"topicId": 8,
8081
"sortOrder": 0,
82+
"templateId": 1,
8183
"config": {
8284
"addEntryButtonLabel": "Add",
8385
"templateCategory": "SAMPLE_DECLARATION",
@@ -129,6 +131,7 @@
129131
},
130132
"topicId": 8,
131133
"sortOrder": 2,
134+
"templateId": 1,
132135
"config": {
133136
"small_label": "",
134137
"required": false,
@@ -175,6 +178,7 @@
175178
},
176179
"topicId": 8,
177180
"sortOrder": 3,
181+
"templateId": 1,
178182
"config": {
179183
"small_label": "",
180184
"required": false,
@@ -209,6 +213,7 @@
209213
},
210214
"topicId": 8,
211215
"sortOrder": 4,
216+
"templateId": 1,
212217
"config": {
213218
"small_label": "",
214219
"required": false,
@@ -244,6 +249,7 @@
244249
},
245250
"topicId": 8,
246251
"sortOrder": 5,
252+
"templateId": 1,
247253
"config": {
248254
"small_label": "",
249255
"required": false,
@@ -277,6 +283,7 @@
277283
},
278284
"topicId": 8,
279285
"sortOrder": 6,
286+
"templateId": 1,
280287
"config": {
281288
"small_label": "",
282289
"required": false,
@@ -316,6 +323,7 @@
316323
},
317324
"topicId": 8,
318325
"sortOrder": 7,
326+
"templateId": 1,
319327
"config": {
320328
"required": false,
321329
"small_label": "",
@@ -350,6 +358,7 @@
350358
},
351359
"topicId": 8,
352360
"sortOrder": 8,
361+
"templateId": 1,
353362
"config": {
354363
"required": false,
355364
"small_label": "",
@@ -385,6 +394,7 @@
385394
},
386395
"topicId": 8,
387396
"sortOrder": 8,
397+
"templateId": 1,
388398
"config": {
389399
"small_label": "",
390400
"required": false,
@@ -421,6 +431,7 @@
421431
},
422432
"topicId": 8,
423433
"sortOrder": 9,
434+
"templateId": 1,
424435
"config": {
425436
"html": "",
426437
"plain": "",
@@ -454,6 +465,7 @@
454465
},
455466
"topicId": 8,
456467
"sortOrder": 10,
468+
"templateId": 1,
457469
"config": {
458470
"required": false,
459471
"small_label": "",
@@ -492,6 +504,7 @@
492504
},
493505
"topicId": 8,
494506
"sortOrder": 11,
507+
"templateId": 1,
495508
"config": {
496509
"small_label": "",
497510
"required": false,
@@ -532,6 +545,7 @@
532545
},
533546
"topicId": 8,
534547
"sortOrder": 12,
548+
"templateId": 1,
535549
"config": {
536550
"small_label": "",
537551
"required": false,
@@ -854,6 +868,7 @@
854868
},
855869
"topicId": 7,
856870
"sortOrder": 0,
871+
"templateId": 7,
857872
"config": {
858873
"titlePlaceholder": "Title",
859874
"tooltip": "",
@@ -880,6 +895,7 @@
880895
},
881896
"topicId": 7,
882897
"sortOrder": 3,
898+
"templateId": 7,
883899
"config": {
884900
"small_label": "",
885901
"required": false,
@@ -906,6 +922,7 @@
906922
},
907923
"topicId": 7,
908924
"sortOrder": 4,
925+
"templateId": 7,
909926
"config": {
910927
"small_label": "",
911928
"required": false,
@@ -940,6 +957,7 @@
940957
},
941958
"topicId": 7,
942959
"sortOrder": 5,
960+
"templateId": 7,
943961
"config": {
944962
"small_label": "",
945963
"required": false,
@@ -982,6 +1000,7 @@
9821000
},
9831001
"topicId": 7,
9841002
"sortOrder": 6,
1003+
"templateId": 7,
9851004
"config": {
9861005
"small_label": "",
9871006
"required": false,
@@ -1037,6 +1056,7 @@
10371056
},
10381057
"topicId": 7,
10391058
"sortOrder": 7,
1059+
"templateId": 7,
10401060
"config": {
10411061
"small_label": "",
10421062
"required": false,
@@ -1085,6 +1105,7 @@
10851105
},
10861106
"topicId": 7,
10871107
"sortOrder": 8,
1108+
"templateId": 7,
10881109
"config": {
10891110
"required": false,
10901111
"small_label": "",
@@ -1119,6 +1140,7 @@
11191140
},
11201141
"topicId": 7,
11211142
"sortOrder": 9,
1143+
"templateId": 7,
11221144
"config": {
11231145
"small_label": "",
11241146
"required": false,
@@ -1156,6 +1178,7 @@
11561178
},
11571179
"topicId": 7,
11581180
"sortOrder": 10,
1181+
"templateId": 7,
11591182
"config": {
11601183
"required": false,
11611184
"small_label": "",
@@ -1193,6 +1216,7 @@
11931216
},
11941217
"topicId": 7,
11951218
"sortOrder": 11,
1219+
"templateId": 7,
11961220
"config": {
11971221
"required": false,
11981222
"small_label": "",

apps/frontend/src/components/common/proposalFilters/QuestionaryFilter.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ function QuestionaryFilter({ onSubmit, callId }: QuestionaryFilterProps) {
159159
}}
160160
questionTemplateRelation={selectedQuestion}
161161
callId={callId}
162+
templateId={selectedQuestion.templateId}
162163
/>
163164
)}
164165
</Collapse>

0 commit comments

Comments
 (0)