Skip to content

Commit 4978f33

Browse files
committed
Added sections to CollectorRequests
1 parent 0880ab3 commit 4978f33

6 files changed

Lines changed: 260 additions & 12 deletions

File tree

src/HDSModel/HDSModel.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
const { HDSLibError } = require('../errors');
12
const { deepFreeze } = require('../utils');
23

34
const LAZILY_LOADED = {
@@ -63,7 +64,7 @@ class HDSModel {
6364

6465
/** RAW model data */
6566
get modelData () {
66-
if (!this.isLoaded) throw new Error('Model not loaded call `HDSLib.initHDSModel()` or `await model.load()` first.');
67+
if (!this.isLoaded) throwNotLoadedError();
6768
return this.#modelData;
6869
}
6970
}
@@ -72,11 +73,15 @@ class HDSModel {
7273
for (const [prop, Obj] of Object.entries(LAZILY_LOADED)) {
7374
Object.defineProperty(HDSModel.prototype, prop, {
7475
get: function () {
75-
if (!this.isLoaded) throw new Error('Model not loaded call `HDSLib.initHDSModel()` or `await model.load()` first.');
76+
if (!this.isLoaded) throwNotLoadedError();
7677
if (!this.laziliyLoadedMap[prop]) this.laziliyLoadedMap[prop] = new Obj(this);
7778
return this.laziliyLoadedMap[prop];
7879
}
7980
});
8081
}
8182

8283
module.exports = HDSModel;
84+
85+
function throwNotLoadedError () {
86+
throw new HDSLibError('Model not loaded call `HDSLib.initHDSModel()` or `await model.load()` first.');
87+
}

src/HDSModel/HDSModelInitAndSingleton.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ const HDService = require('../HDSService');
44

55
module.exports = {
66
getModel,
7-
initHDSModel
7+
initHDSModel,
8+
resetModel
89
};
910

1011
function getModel () {
@@ -13,6 +14,12 @@ function getModel () {
1314
}
1415
return model;
1516
}
17+
/**
18+
* Mostly used during test to unlod model
19+
*/
20+
function resetModel () {
21+
model = null;
22+
}
1623

1724
/**
1825
* Initialized model singleton

src/appTemplates/CollectorRequest.ts

Lines changed: 116 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import { HDSLibError } from '../errors.js';
2+
import { getModel } from '../HDSModel/HDSModelInitAndSingleton.js';
23
import { validateLocalizableText } from '../localizeText.js';
3-
import type { localizableText } from '../../types/localizeText.d.ts';
4+
import type { localizableText, localizableTextLanguages } from '../../types/localizeText.d.ts';
5+
46

57
declare type PermissionItem = {streamId: string, defaultName: string, level: string};
68

9+
const CURRENT_VERSION = 1;
10+
711
/**
812
* Each Collector has one Request
913
* Which contains
@@ -22,13 +26,15 @@ export class CollectorRequest {
2226
#requester: {name: string};
2327
#app: {id: string, url: string | null, data: any};
2428
#permissions: Array<PermissionItem>;
29+
#sections: Array<CollectorRequestSection>;
2530

2631
#extraContent: any;
2732
constructor (content: any) {
28-
this.#version = 0;
33+
this.#version = CURRENT_VERSION;
2934
this.#requester = { name: null };
3035
this.#app = { id: null, url: null, data: {} };
3136
this.#permissions = [];
37+
this.#sections = [];
3238
this.setContent(content);
3339
}
3440

@@ -51,32 +57,53 @@ export class CollectorRequest {
5157
*/
5258
setContent(content: any) {
5359
const futureContent = structuredClone(content);
60+
5461
// validate content
55-
if (futureContent.version) {
62+
if (futureContent.version != null) {
5663
const numV = Number.parseInt(futureContent.version);
57-
if (numV !== this.#version) throw new HDSLibError(`Invalid CollectorRequest content version: ${futureContent.version}`);
64+
if (numV === 0) {
65+
vo0ToV1(futureContent); // convert to v1 if needed
66+
} else {
67+
if (numV !== this.#version) throw new HDSLibError(`Invalid CollectorRequest content version: ${futureContent.version}`);
68+
}
5869
delete futureContent.version;
5970
}
6071

72+
// -- title, consent, description
6173
for (const key of ['title', 'consent', 'description']) {
6274
if (futureContent[key] != null) {
6375
this[key] = futureContent[key];
6476
}
6577
delete futureContent[key];
6678
}
79+
80+
// -- requester
6781
if (futureContent.requester) {
6882
if (futureContent.requester.name != null) {
6983
this.requesterName = futureContent.requester.name;
7084
}
7185
delete futureContent.requester;
7286
}
87+
88+
// -- app
7389
if (futureContent.app) {
7490
if (futureContent.app.id != null) { this.appId = futureContent.app.id; }
7591
if (futureContent.app.url != null) { this.appUrl = futureContent.app.url; }
7692
if (futureContent.app.data != null) { this.appCustomData = futureContent.app.data; }
7793
delete futureContent.app;
7894
}
7995

96+
// -- sections
97+
if (futureContent.sections != null) {
98+
for (const sectionData of futureContent.sections) {
99+
const section = new CollectorRequestSection(sectionData.key, sectionData.type);
100+
section.setName(sectionData.name);
101+
section.addItemKeys(sectionData.itemKeys);
102+
this.#sections.push(section);
103+
}
104+
}
105+
106+
// -- permissions
80107
if (futureContent.permissions) {
81108
this.#permissions = []; // reset permissions
82109
futureContent.permissions.forEach((p: PermissionItem)=> {
@@ -116,6 +143,14 @@ export class CollectorRequest {
116143

117144
get permissions() { return this.#permissions; }
118145

146+
get sectionsData() {
147+
const result = [];
148+
for (const section of this.#sections) {
149+
result.push(section.getData());
150+
}
151+
return result;
152+
}
153+
119154
// ---------- permissions ---------- //
120155
addPermissions (streamId: string, defaultName: string, level: string) {
121156
this.#permissions.push({streamId, defaultName, level});
@@ -126,6 +161,7 @@ export class CollectorRequest {
126161
*/
127162
get content () {
128163
const content = {
164+
version: this.version,
129165
title: this.title,
130166
consent: this.consent,
131167
description: this.description,
@@ -137,7 +173,8 @@ export class CollectorRequest {
137173
id: this.appId,
138174
url: this.appUrl,
139175
data: this.appCustomData
140-
}
176+
},
177+
sections: this.sectionsData
141178
};
142179
Object.assign(content, this.#extraContent);
143180
return content;
@@ -149,4 +186,78 @@ function validateString (key, totest) {
149186
return totest;
150187
}
151188

189+
const RequestSectionType = {
190+
recurring: 'recurring',
191+
permanent: 'permanent'
192+
}
193+
type RequestSectionType = (typeof RequestSectionType )[keyof typeof RequestSectionType ];
194+
195+
class CollectorRequestSection {
196+
#type: RequestSectionType;
197+
#name: localizableText;
198+
#key: string;
199+
#itemKeys: Array<string>;
200+
201+
constructor (key: string, type: RequestSectionType) {
202+
this.#key = key;
203+
this.#type = type;
204+
this.#itemKeys = [];
205+
this.#name = {
206+
en: ''
207+
}
208+
}
209+
210+
addItemKeys(keys: Array<string>) {
211+
keys.forEach((k) => this.addItemKey(k));
212+
}
213+
214+
addItemKey(key: string) {
215+
getModel().itemsDefs.forKey(key); // will throw error if not found
216+
if (this.#itemKeys.includes(key)) return; // avoid double entries
217+
this.#itemKeys.push(key);
218+
}
219+
220+
setName(localizedName: localizableText) {
221+
for (const [languageCode, name] of Object.entries(localizedName)) {
222+
this.setNameLocal(languageCode as localizableTextLanguages, name);
223+
}
224+
}
225+
226+
setNameLocal(languageCode: localizableTextLanguages, name: string) {
227+
this.#name[languageCode] = name;
228+
}
152229

230+
get type() { return this.#type }
231+
get key() { return this.#key }
232+
get itemKeys() { return this.#itemKeys }
233+
234+
getData() {
235+
return {
236+
key: this.key,
237+
type: this.#type,
238+
name: this.#name,
239+
itemKeys: this.#itemKeys
240+
}
241+
}
242+
243+
}
244+
245+
/**
246+
* Transform data to match v1
247+
* @param v0Data
248+
*/
249+
function vo0ToV1(v0Data: any) {
250+
if (v0Data.app?.data?.forms) {
251+
if (v0Data.sections) throw new HDSLibError('Cannot mix data.forms & sections', v0Data);
252+
v0Data.sections = [];
253+
for (const [key, value] of Object.entries(v0Data.app.data.forms) as [key: string, value: any]) {
254+
value.key = key;
255+
value.name = {
256+
en: value.name
257+
}
258+
v0Data.sections.push(value)
259+
}
260+
delete v0Data.app.data.forms;
261+
}
262+
v0Data.version = 1;
263+
}

0 commit comments

Comments
 (0)