@legalplace/lplogic 2.0.0

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.
@@ -0,0 +1,543 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ var ModelV1Schema = {
4
+ definitions: {
5
+ section: {
6
+ type: "object",
7
+ required: ["id", "label", "options"],
8
+ properties: {
9
+ id: {
10
+ description: "Section's id",
11
+ type: ["string", "integer"],
12
+ minimum: 1
13
+ },
14
+ label: {
15
+ description: "Section's title",
16
+ type: "string",
17
+ examples: ["Le Bailleur", "Le Locataire"]
18
+ },
19
+ options: {
20
+ description: "Section's options",
21
+ type: "array",
22
+ items: {
23
+ $ref: "#/definitions/option"
24
+ }
25
+ }
26
+ }
27
+ },
28
+ option: {
29
+ type: "object",
30
+ properties: {
31
+ meta: {
32
+ type: "object",
33
+ properties: {
34
+ id: {
35
+ type: ["string", "integer"],
36
+ description: "Option's id"
37
+ },
38
+ type: {
39
+ type: "string",
40
+ description: "Option's type \n - `static`: A static question \n - `radio`: A radio input \n - `checkbox`: A checkbox input \n - `hidden`: An option that only displays an output \n - `brut-text`: An option without output that displays HTML in the wizard \n - `repeated`: A loop linked to a multiple (can only have `hidden` options as children)",
41
+ enum: [
42
+ "static",
43
+ "radio",
44
+ "checkbox",
45
+ "hidden",
46
+ "brut-text",
47
+ "repeated"
48
+ ]
49
+ },
50
+ multiple: {
51
+ type: "boolean",
52
+ description: "Can be used on root options only, if set to true, the option must allow to have duplicates with different answers for all its children"
53
+ },
54
+ output: {
55
+ type: "string",
56
+ description: "The raw option's output. Example:\n``` \nDomicilié à [var:1], [var:2]\n[var:3]```"
57
+ },
58
+ outputRender: {
59
+ type: "string",
60
+ description: 'The html option\'s output (This property is depreceated it was used by the mvp wizard (angular)). Example:\n```html \nDomicilié à <span ng-repeat="cI in [1] track by $index"><span ng-init="vars[1] = contractCtrl.variables_wrapper[1]; " ng-include="\\\'preview/var.html\\\'"></span>, <span ng-repeat="cI in [2] track by $index"><span ng-init="vars[2] = contractCtrl.variables_wrapper[2]; " ng-include="\\\'preview/var.html\\\'"></span>\n <span ng-repeat="cI in [3] track by $index"><span ng-init="vars[3] = contractCtrl.variables_wrapper[3]; " ng-include="\\\'preview/var.html\\\'"></span>```'
61
+ },
62
+ default: {
63
+ type: ["string", "integer"],
64
+ description: "In case of a radio/checkbox/static options, this holds the default child id that should be selected in case the user advances to the next section without selecting any of the child"
65
+ },
66
+ parentMultiple: {
67
+ type: "boolean",
68
+ description: "Set to true if the root parent is a multiple option"
69
+ },
70
+ step_two_only: {
71
+ type: "boolean",
72
+ description: "Set to true if the option should be displayed in the second step only"
73
+ },
74
+ conditions: {
75
+ description: "Raw conditions array",
76
+ type: ["array", "boolean"],
77
+ items: {
78
+ $ref: "#/definitions/condition"
79
+ }
80
+ },
81
+ compiledConditions: {
82
+ description: "Compiled conditions array",
83
+ type: ["array", "boolean"],
84
+ items: {
85
+ $ref: "#/definitions/compiledCondition"
86
+ }
87
+ },
88
+ warning: {
89
+ description: "The html content of the warning block",
90
+ type: "string"
91
+ },
92
+ helper: {
93
+ description: "The html content of the helper block",
94
+ type: "string"
95
+ },
96
+ multipletext: {
97
+ description: "The label of the multiple's incrementing cta",
98
+ type: "string"
99
+ },
100
+ parent_section: {
101
+ description: "Id of the parent section",
102
+ type: ["integer", "string"]
103
+ },
104
+ multipleIncrtText: {
105
+ description: "The text that preceeds the reccurency number of the multiple",
106
+ type: "string"
107
+ },
108
+ content: {
109
+ description: "The html content of the brut-text option",
110
+ type: "string"
111
+ },
112
+ repeatOption: {
113
+ description: "In case of a `repeated` option, this defines the multiple's id that the loop should be linked to",
114
+ type: ["integer", "string"]
115
+ },
116
+ multipleIncrt: {
117
+ description: "The start of the multiples incrementation counter",
118
+ type: ["integer", "string"]
119
+ },
120
+ zonetendue: {
121
+ description: 'True to enabled the "zonetendue" extension',
122
+ type: "boolean"
123
+ },
124
+ mandatory: {
125
+ description: "Set to true to make the option mandatory",
126
+ type: "boolean"
127
+ }
128
+ }
129
+ },
130
+ children: {
131
+ description: "Child options",
132
+ type: "array",
133
+ items: {
134
+ $ref: "#/definitions/option"
135
+ }
136
+ },
137
+ variables: {
138
+ description: "Child variables",
139
+ type: "array",
140
+ items: {
141
+ $ref: "#/definitions/variable"
142
+ }
143
+ }
144
+ }
145
+ },
146
+ variable: {
147
+ type: "object",
148
+ description: "Variable definition object",
149
+ properties: {
150
+ id: {
151
+ description: "Variable's id (must be unique)",
152
+ type: ["integer", "string"]
153
+ },
154
+ label: {
155
+ description: "Variable's label",
156
+ type: "string",
157
+ examples: ["Nom complet", "Adresse", "Date de naissance"]
158
+ },
159
+ type: {
160
+ description: "Variable's type",
161
+ type: "string",
162
+ enum: [
163
+ "text",
164
+ "date",
165
+ "list",
166
+ "textarea",
167
+ "number",
168
+ "eval",
169
+ "advancedmask",
170
+ "hour",
171
+ "email",
172
+ "mask"
173
+ ]
174
+ },
175
+ value: {
176
+ description: "Variable's value, or values list in case of a multiple",
177
+ type: ["string", "array"]
178
+ },
179
+ parentMultiple: {
180
+ description: "Set to true if the root option is a multiple",
181
+ type: "boolean"
182
+ },
183
+ phsize: {
184
+ type: ["string", "integer", "null"],
185
+ description: "Variable's place holder length"
186
+ },
187
+ warning: {
188
+ description: "The html content of the warning block",
189
+ type: "string"
190
+ },
191
+ helper: {
192
+ description: "The html content of the helper block",
193
+ type: "string"
194
+ },
195
+ list: {
196
+ description: "The list of options for the select (list type) variable",
197
+ type: "array"
198
+ },
199
+ autocomplete: {
200
+ description: "The input's autocomplete attribute",
201
+ type: "string"
202
+ },
203
+ textarea_height: {
204
+ description: "The textarea's high (lines number) (Only if textarea_size is set to `p`)",
205
+ type: ["integer", "string"]
206
+ },
207
+ advancedmask: {
208
+ description: "The advanced mask's formula (ex: 20 ???-???-???) (?: Char & Number, !: Number Only, @: Char Only)",
209
+ type: "string"
210
+ },
211
+ maskph: {
212
+ description: "Mask's placeholder",
213
+ type: "string"
214
+ },
215
+ mask: {
216
+ description: "Mask's formula (ex: 999-999-999)",
217
+ type: "string"
218
+ },
219
+ prefillings: {
220
+ description: "Preffiling's object",
221
+ type: "array",
222
+ items: {
223
+ $ref: "#/definitions/prefilling"
224
+ }
225
+ },
226
+ placeholder: {
227
+ description: "Input's placeholder",
228
+ type: "string"
229
+ },
230
+ eval_decimal: {
231
+ description: "The number of decimals for the result of an evaluation (eval type)",
232
+ type: ["integer", "string"]
233
+ },
234
+ evaluation: {
235
+ description: "The evaluation formula (eval type), Example: \n ``` \n[var:1]*[var:2]/[var:3]```",
236
+ type: "string"
237
+ },
238
+ round: {
239
+ description: "Round evalulation result (eval type). \n - `0`: Default \n - `1`: Round Up \n - `2`: Round down",
240
+ type: ["string", "integer"],
241
+ enum: [0, 1, 2, "0", "1", "2"]
242
+ },
243
+ longInput: {
244
+ description: "Set to true to enlarge the textarea (textarea type)",
245
+ type: "boolean"
246
+ },
247
+ textarea_size: {
248
+ description: "Textarea's size (textarea type)\n - l: Large (240px) \n - m: Medium (120px) \n - p: Custom size in pixels",
249
+ type: "string",
250
+ enum: ["l", "m", "p"]
251
+ },
252
+ mandatory: {
253
+ description: "True if the variable is mandatory",
254
+ type: "boolean"
255
+ },
256
+ step_two_only: {
257
+ type: "boolean",
258
+ description: "Set to true if the variable should be displayed in the second step only"
259
+ }
260
+ }
261
+ },
262
+ condition: {
263
+ type: "object",
264
+ properties: {
265
+ c: {
266
+ type: "string",
267
+ enum: [
268
+ "selected",
269
+ "not-selected",
270
+ "has-one",
271
+ "at-least-one",
272
+ "has-many",
273
+ "contains",
274
+ "does-not-contain"
275
+ ],
276
+ description: "Condition"
277
+ },
278
+ o: {
279
+ type: ["string", "boolean", "integer"],
280
+ description: "Option's id, set to false if the condition is related to a variable"
281
+ },
282
+ p: {
283
+ type: ["string", "integer"],
284
+ description: "`Depreceated` Option's parent id"
285
+ },
286
+ v: {
287
+ type: ["string", "boolean", "integer"],
288
+ description: "Variable's id, set to false if the condition is related to an option"
289
+ },
290
+ value: {
291
+ type: ["string", "integer"],
292
+ description: "Expected value (in case the condition is on a variable)"
293
+ },
294
+ l: {
295
+ type: ["array", "boolean"],
296
+ description: "`Depreceated` Variable's possible values list, set to false if condition is related to an option"
297
+ },
298
+ m: {
299
+ type: "boolean",
300
+ description: "`Depreaceated` True if the variable/option is a multiple"
301
+ },
302
+ t: {
303
+ type: "string",
304
+ enum: ["and", "or"],
305
+ description: "Relation's op to the previous condition"
306
+ }
307
+ },
308
+ anyOf: [
309
+ {
310
+ required: ["o", "c"]
311
+ },
312
+ {
313
+ required: ["v", "c", "value"]
314
+ }
315
+ ]
316
+ },
317
+ compiledCondition: {
318
+ type: ["object", "array"],
319
+ description: 'The compiledCondition is whether an object or an array, it\'s a rewriting of the conditions object where the conditions with the "and" relation are separated into arrays from the "or" relations'
320
+ },
321
+ prefilling: {
322
+ type: "object",
323
+ additionalProperties: false,
324
+ description: "A Prefilling, is a conditionned text placeholder/example used to fill a textarea according to different conditions",
325
+ properties: {
326
+ text: {
327
+ type: "string",
328
+ description: "Text used to fill the textarea if the condition is realized"
329
+ },
330
+ conditions: {
331
+ type: ["array", "boolean"],
332
+ description: "Conditions object",
333
+ items: {
334
+ $ref: "#/definitions/condition"
335
+ }
336
+ },
337
+ compiledConditions: {
338
+ type: ["array", "boolean"],
339
+ description: "Compiled conditions object",
340
+ items: {
341
+ $ref: "#/definitions/compiledCondition"
342
+ }
343
+ }
344
+ }
345
+ },
346
+ varExtraction: {
347
+ type: "object",
348
+ additionalProperties: false,
349
+ properties: {
350
+ type: {
351
+ type: "string",
352
+ enum: ["variable", "option"],
353
+ description: "Extraction's type"
354
+ },
355
+ index: {
356
+ type: ["integer", "string"],
357
+ description: "Used by the editor, the variables index in the variable's array list"
358
+ },
359
+ id: {
360
+ type: ["integer", "string"],
361
+ description: "Variable's id"
362
+ },
363
+ parent_id: {
364
+ type: ["integer", "string", "boolean"],
365
+ description: "Variable's parent id"
366
+ },
367
+ extractions: {
368
+ type: "object",
369
+ additionalProperties: false,
370
+ properties: {
371
+ sendinblue: {
372
+ ext_name: {
373
+ type: "string",
374
+ description: "`Static` Used by the editor to display the extraction's label"
375
+ },
376
+ enabled: {
377
+ type: "boolean",
378
+ description: "Set to true to enable Sendinblue's extraction"
379
+ },
380
+ name: {
381
+ type: "string",
382
+ description: "Sendinblue's variable name"
383
+ }
384
+ },
385
+ mixpanel: {
386
+ ext_name: {
387
+ type: "string",
388
+ description: "`Static` Used by the editor to display the extraction's label"
389
+ },
390
+ enabled: {
391
+ type: "boolean",
392
+ description: "Set to true to enable Mixpanel's extraction"
393
+ },
394
+ name: {
395
+ type: "string",
396
+ description: "Mixpanel's variable name"
397
+ }
398
+ },
399
+ slack: {
400
+ ext_name: {
401
+ type: "string",
402
+ description: "`Static` Used by the editor to display the extraction's label"
403
+ },
404
+ enabled: {
405
+ type: "boolean",
406
+ description: "Set to true to enable Slack's extraction"
407
+ },
408
+ name: {
409
+ type: "string",
410
+ description: "Slack's variable name"
411
+ },
412
+ channel: {
413
+ type: "string",
414
+ description: "Slack's channel name"
415
+ }
416
+ }
417
+ }
418
+ }
419
+ }
420
+ }
421
+ },
422
+ $schema: "http://json-schema.org/draft-07/schema#",
423
+ $id: "editor.json",
424
+ type: "object",
425
+ title: "Model V1",
426
+ required: ["contract_name", "sections"],
427
+ properties: {
428
+ contract_name: {
429
+ type: "string",
430
+ description: "The current document's main title that will be displayed on top of the wizard.",
431
+ examples: ["Bail de location non meublée", "Statuts SAS"]
432
+ },
433
+ sections: {
434
+ type: "array",
435
+ description: "Document's sections list",
436
+ items: {
437
+ $ref: "#/definitions/section"
438
+ }
439
+ },
440
+ params: {
441
+ type: "object",
442
+ additionalProperties: false,
443
+ description: "Model's parameters",
444
+ properties: {
445
+ sivAttributes: {
446
+ type: "object",
447
+ description: "`Depreceated`"
448
+ },
449
+ hasSivAttributes: {
450
+ type: "boolean",
451
+ description: "`Depreceated`"
452
+ },
453
+ is_two_steps: {
454
+ type: "boolean",
455
+ description: "Set to true to enable support of 2 steps"
456
+ },
457
+ proIdnType: {
458
+ type: "string",
459
+ enum: ["PRO", "IND", "COND"]
460
+ },
461
+ disableAutoDefault: {
462
+ type: "boolean",
463
+ description: "Set to true to disable the auto selection of default options"
464
+ },
465
+ varsExtraction: {
466
+ type: "array",
467
+ description: "Variables extraction logic",
468
+ items: {
469
+ $ref: "#/definitions/varExtraction"
470
+ }
471
+ },
472
+ disableCompagnon: {
473
+ type: "boolean",
474
+ description: "`Depreceated` Set to true to disable the compagnon block (the gray block on the top right of the angular wizard)"
475
+ },
476
+ fullWidth: {
477
+ type: "boolean",
478
+ description: "Set to true to enable wizard in full width (disable preview)"
479
+ },
480
+ disableDownloadPopup: {
481
+ type: "boolean",
482
+ description: "`Depreceated` Set to true to disable the download CTA on to of the preview block"
483
+ },
484
+ disableDownload: {
485
+ type: "boolean",
486
+ description: "`Depreceated` Set to true to disable the download CTA on to of the preview block"
487
+ },
488
+ disablePreview: {
489
+ type: "boolean",
490
+ description: "`Depreceated` Set to true to disable the preview"
491
+ },
492
+ noAttachements: {
493
+ type: "boolean",
494
+ description: "`Depreceated` Set to true to disable the static Annexe files (For Bail Immobilier)"
495
+ },
496
+ isTwoSteps: {
497
+ type: "boolean",
498
+ description: "Set to true to enable 2 steps feature"
499
+ }
500
+ }
501
+ },
502
+ options_ids: {
503
+ type: "array",
504
+ description: "`Depreceated` Array to track options ids, this should be replaced with a simple integer counter",
505
+ items: {
506
+ type: ["integer", "string"]
507
+ }
508
+ },
509
+ variables_id: {
510
+ type: "array",
511
+ description: "`Depreceated` Array to track varaibles ids, this should be replaced with a simple integer counter",
512
+ items: {
513
+ type: "object"
514
+ }
515
+ },
516
+ pro: {
517
+ type: "object",
518
+ additionalProperties: false,
519
+ description: "If `prodIndType` is set to `COND`, this stores the conditions that defined whether the client is a pro or an individual",
520
+ properties: {
521
+ meta: {
522
+ type: "object",
523
+ additionalProperties: false,
524
+ properties: {
525
+ conditions: {
526
+ type: ["array", "boolean"],
527
+ items: {
528
+ $ref: "#/definitions/condition"
529
+ }
530
+ },
531
+ compiledConditions: {
532
+ type: ["array", "boolean"],
533
+ items: {
534
+ $ref: "#/definitions/compiledCondition"
535
+ }
536
+ }
537
+ }
538
+ }
539
+ }
540
+ }
541
+ }
542
+ };
543
+ exports.default = ModelV1Schema;
package/jest.config.js ADDED
@@ -0,0 +1,13 @@
1
+ module.exports = {
2
+ "roots": [
3
+ "./tests"
4
+ ],
5
+ "transform": {
6
+ "^.+\\.tsx?$": "ts-jest"
7
+ },
8
+ "globals": {
9
+ "ts-jest": {
10
+ tsConfig: "tsconfig.json"
11
+ }
12
+ }
13
+ }
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@legalplace/lplogic",
3
+ "version": "2.0.0",
4
+ "description": "LegalPlace LpLogic",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "test": "npx jest",
9
+ "build": "npx tsc"
10
+ },
11
+ "outDir": "./dist",
12
+ "author": "Moncef Hammou <moncef@legalplace.fr>",
13
+ "license": "ISC",
14
+ "devDependencies": {
15
+ "@babel/core": "^7.7.2",
16
+ "@babel/preset-typescript": "^7.7.2",
17
+ "@legalplace/models-v3-types": "^3.1.0",
18
+ "@types/jest": "^24.0.15",
19
+ "@types/node": "^12.6.1",
20
+ "@typescript-eslint/eslint-plugin": "^2.6.1",
21
+ "@typescript-eslint/parser": "^2.6.1",
22
+ "airbnb-standard": "^1.0.0",
23
+ "eslint": "^6.6.0",
24
+ "eslint-config-airbnb-base": "^14.0.0",
25
+ "eslint-config-prettier": "^6.5.0",
26
+ "eslint-plugin-import": "^2.18.2",
27
+ "eslint-plugin-prettier": "^3.1.1",
28
+ "jest": "^24.8.0",
29
+ "prettier": "1.19.1",
30
+ "ts-jest": "^24.0.2",
31
+ "typescript": "^3.7.2"
32
+ },
33
+ "dependencies": {
34
+ "@legalplace/json-logic-js": "^1.2.3",
35
+ "jsonschema": "^1.2.4"
36
+ }
37
+ }
@@ -0,0 +1,90 @@
1
+ import LpLogic from "../lib/index"
2
+
3
+ test('Testing "selected" operator on a boolean `true`', async () => {
4
+ expect(LpLogic({"selected":[{"var":"o.1"}]}, {"o":{"1":true}})).toBe(true)
5
+ })
6
+
7
+ test('Testing "selected" operator on an array of boolean `true`', async () => {
8
+ expect(LpLogic({"selected":[{"var":"o.1"}]}, {"o":{"1":[true, true]}})).toBe(true)
9
+ })
10
+
11
+
12
+ test('Testing "selected" operator on an array of boolean `false`', async () => {
13
+ expect(LpLogic({"selected":[{"var":"o.1"}]}, {"o":{"1":false}})).toBe(false)
14
+ })
15
+
16
+ test('Testing "selected" operator on an array containing a boolean `false`', async () => {
17
+ expect(LpLogic({"selected":[{"var":"o.1"}]}, {"o":{"1":[true, false]}})).toBe(false)
18
+ })
19
+
20
+ test('Testing "not-selected" operator on a boolean `false`', async () => {
21
+ expect(LpLogic({"not-selected":[{"var":"o.1"}]}, {"o":{"1":false}})).toBe(true)
22
+ })
23
+
24
+ test('Testing "not-selected" operator on an array of boolean `false`', async () => {
25
+ expect(LpLogic({"not-selected":[{"var":"o.1"}]}, {"o":{"1":[false, false]}})).toBe(true)
26
+ })
27
+
28
+ // Returns false
29
+
30
+ test('Testing "not-selected" operator on a boolean `true`', async () => {
31
+ expect( LpLogic({"not-selected":[{"var":"o.1"}]}, {"o":{"1":true}}) ).toBe(false)
32
+ })
33
+
34
+ test('Testing "not-selected" operator on an array containing a boolean `true`', async () => {
35
+ expect( LpLogic({"not-selected":[{"var":"o.1"}]}, {"o":{"1":[true, false]}}) ).toBe(false)
36
+ })
37
+
38
+ // Returns true
39
+ test('Testing "has-one" on an array of one element', async () => {
40
+ expect(LpLogic({"has-one":[{"var":"o.1"}]}, {"o":{"1":[true]}})).toBe(true)
41
+ })
42
+
43
+ // Returns false
44
+ test('Testing "has-one" on an array of two elements', async () => {
45
+ expect( LpLogic({"has-one":[{"var":"o.1"}]}, {"o":{"1":[true, true]}}) ).toBe(false)
46
+ })
47
+
48
+
49
+ // Returns true
50
+ test('Testing "has-many" on an array of two elements', async () => {
51
+ expect( LpLogic({"has-many":[{"var":"o.1"}]}, {"o":{"1":[true, true]}}) ).toBe(true)
52
+ });
53
+
54
+
55
+ // Returns false
56
+ test('Testing "has-many" on an array of one element', async () => {
57
+ expect( LpLogic({"has-many":[{"var":"o.1"}]}, {"o":{"1":[true]}}) ).toBe(false)
58
+ })
59
+
60
+ // Returns true
61
+ test('Testing "at-least-one" on a array of three elements with one as true', async () => {
62
+ expect( LpLogic({"at-least-one":[{"var":"o.1"}]}, {"o":{"1":[false, false, true]}}) ).toBe(true)
63
+ })
64
+
65
+ // Returns false
66
+ test('Testing "at-least-one" on an array of three elements with all elements as false', async () => {
67
+ expect( LpLogic({"at-least-one":[{"var":"o.1"}]}, {"o":{"1":[false, false, false]}}) ).toBe(false)
68
+ });
69
+
70
+
71
+ // Returns true
72
+ test('Testing "contains" Hello on a value `Hello`', async () => {
73
+ expect( LpLogic({"contains":[{"var":"v.1"}, "Hello"]}, {"v":{"1":"Hello"}}) ).toBe(true)
74
+ })
75
+
76
+
77
+ // Returns false
78
+ test('Testing "contains" Hello on a value `Bye`', async () => {
79
+ expect( LpLogic({"contains":[{"var":"v.1"}, "Hello"]}, {"v":{"1":"Bye"}}) ).toBe(false)
80
+ })
81
+
82
+ // Returns true
83
+ test('Testing "does-not-contain" Hello on a value `Bye`', async () => {
84
+ expect( LpLogic({"does-not-contain":[{"var":"v.1"}, "Hello"]}, {"v":{"1":"Bye"}}) ).toBe(true)
85
+ })
86
+
87
+ // Returns false
88
+ test('Testing "does-not-contain" Hello on a value `Hello`', async () => {
89
+ expect( LpLogic({"does-not-contain":[{"var":"v.1"}, "Hello"]}, {"v":{"1":"Hello"}}) ).toBe(false)
90
+ })