@lblod/ember-rdfa-editor-lblod-plugins 8.4.0 → 9.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.
Files changed (100) hide show
  1. package/CHANGELOG.md +37 -1
  2. package/README.md +132 -0
  3. package/addon/components/address-plugin/insert.ts +2 -2
  4. package/addon/components/address-plugin/utils.ts +2 -2
  5. package/addon/components/article-structure-plugin/structure-card.ts +11 -11
  6. package/addon/components/besluit-type-plugin/besluit-type-select.ts +2 -2
  7. package/addon/components/besluit-type-plugin/toolbar-dropdown.ts +8 -8
  8. package/addon/components/citation-plugin/citation-card.ts +6 -6
  9. package/addon/components/citation-plugin/citation-insert.ts +7 -7
  10. package/addon/components/citation-plugin/citations/search-modal.ts +4 -4
  11. package/addon/components/document-title-plugin/insert-title-card.ts +4 -4
  12. package/addon/components/generic-rdfa-variable/insert-menu.ts +2 -2
  13. package/addon/components/hover-tooltip.ts +1 -1
  14. package/addon/components/import-snippet-plugin/card.ts +9 -9
  15. package/addon/components/rdfa-date-plugin/card.ts +6 -6
  16. package/addon/components/rdfa-date-plugin/date-time-picker.ts +2 -2
  17. package/addon/components/rdfa-date-plugin/date.ts +2 -2
  18. package/addon/components/rdfa-date-plugin/insert.ts +2 -2
  19. package/addon/components/roadsign-regulation-plugin/expanded-measure.ts +3 -3
  20. package/addon/components/roadsign-regulation-plugin/measure-template.ts +2 -2
  21. package/addon/components/roadsign-regulation-plugin/roadsign-regulation-card.ts +1 -1
  22. package/addon/components/roadsign-regulation-plugin/roadsigns-modal.ts +9 -9
  23. package/addon/components/snippet-plugin/search-modal.ts +1 -1
  24. package/addon/components/snippet-plugin/snippet-insert.ts +2 -2
  25. package/addon/components/standard-template-plugin/template-provider.ts +7 -7
  26. package/addon/components/table-of-contents-plugin/ember-nodes/table-of-contents.ts +3 -3
  27. package/addon/components/table-of-contents-plugin/toolbar-button.ts +5 -5
  28. package/addon/components/variable-number/number.ts +25 -26
  29. package/addon/components/variable-plugin/insert-variable-card.hbs +2 -0
  30. package/addon/components/variable-plugin/insert-variable-card.ts +53 -11
  31. package/addon/components/variable-plugin/number-settings.hbs +5 -0
  32. package/addon/components/variable-plugin/template-variable-card.ts +8 -8
  33. package/addon/helpers/pagination.ts +1 -1
  34. package/addon/models/instruction.ts +2 -2
  35. package/addon/models/measure.ts +2 -2
  36. package/addon/models/sign.ts +2 -2
  37. package/addon/plugins/article-structure-plugin/commands/insert-structure.ts +4 -4
  38. package/addon/plugins/article-structure-plugin/commands/move-selected-structure.ts +5 -5
  39. package/addon/plugins/article-structure-plugin/commands/recalculate-structure-numbers.ts +1 -1
  40. package/addon/plugins/article-structure-plugin/commands/remove-structure.ts +1 -1
  41. package/addon/plugins/article-structure-plugin/commands/unwrap-structure.ts +1 -1
  42. package/addon/plugins/article-structure-plugin/commands/wrap-structure-content.ts +5 -5
  43. package/addon/plugins/article-structure-plugin/structures/article-paragraph.ts +2 -2
  44. package/addon/plugins/article-structure-plugin/structures/article.ts +4 -4
  45. package/addon/plugins/article-structure-plugin/structures/chapter.ts +4 -4
  46. package/addon/plugins/article-structure-plugin/structures/section.ts +4 -4
  47. package/addon/plugins/article-structure-plugin/structures/subsection.ts +4 -4
  48. package/addon/plugins/article-structure-plugin/structures/title.ts +4 -4
  49. package/addon/plugins/article-structure-plugin/utils/structure.ts +1 -1
  50. package/addon/plugins/besluit-type-plugin/utils/fetchBesluitTypes.ts +1 -1
  51. package/addon/plugins/citation-plugin/index.ts +17 -17
  52. package/addon/plugins/citation-plugin/utils/cited-text.ts +2 -2
  53. package/addon/plugins/citation-plugin/utils/legislation-types.ts +1 -1
  54. package/addon/plugins/citation-plugin/utils/process-match.ts +3 -3
  55. package/addon/plugins/citation-plugin/utils/vlaamse-codex.ts +14 -14
  56. package/addon/plugins/decision-plugin/commands/insert-article-container.ts +2 -2
  57. package/addon/plugins/decision-plugin/commands/insert-description.ts +3 -3
  58. package/addon/plugins/decision-plugin/commands/insert-motivation.ts +9 -9
  59. package/addon/plugins/decision-plugin/commands/insert-title.ts +3 -3
  60. package/addon/plugins/decision-plugin/utils/get-title-for-decision.ts +1 -1
  61. package/addon/plugins/document-title-plugin/commands/insert-document-title.ts +3 -3
  62. package/addon/plugins/rdfa-date-plugin/nodes/date.ts +2 -2
  63. package/addon/plugins/rdfa-date-plugin/utils.ts +1 -1
  64. package/addon/plugins/roadsign-regulation-plugin/nodes.ts +4 -4
  65. package/addon/plugins/roadsign-regulation-plugin/utils/fetchData.ts +2 -2
  66. package/addon/plugins/roadsign-regulation-plugin/utils/includeInstructions.ts +2 -2
  67. package/addon/plugins/snippet-plugin/utils/fetch-data.ts +22 -14
  68. package/addon/plugins/standard-template-plugin/utils/instantiate-uuids.ts +2 -2
  69. package/addon/plugins/standard-template-plugin/utils/nodes.ts +5 -5
  70. package/addon/plugins/table-of-contents-plugin/nodes/table-of-contents.ts +1 -1
  71. package/addon/plugins/table-of-contents-plugin/utils/index.ts +1 -1
  72. package/addon/plugins/validation/index.ts +13 -13
  73. package/addon/plugins/validation/utils/transaction-complies-with-shapes.ts +2 -2
  74. package/addon/plugins/variable-plugin/nodes.ts +7 -6
  75. package/addon/plugins/variable-plugin/utils/constants.ts +5 -5
  76. package/addon/plugins/variable-plugin/utils/fetch-data.ts +2 -2
  77. package/addon/plugins/variable-plugin/utils/number-to-words.ts +15 -0
  78. package/addon/services/import-rdfa-snippet.ts +3 -3
  79. package/addon/services/roadsign-registry.ts +15 -15
  80. package/addon/services/standard-template-plugin.ts +1 -1
  81. package/addon/utils/_private/find-insertion-range.ts +1 -1
  82. package/addon/utils/changed-descendants.ts +1 -1
  83. package/addon/utils/constants.ts +3 -3
  84. package/addon/utils/find-insertion-pos-in-ancestor-of-type.ts +2 -2
  85. package/addon/utils/namespace.ts +3 -3
  86. package/addon/utils/option.ts +2 -2
  87. package/addon/utils/sparql-helpers.ts +2 -2
  88. package/addon/utils/strings.ts +11 -1
  89. package/app/styles/variable-plugin.scss +14 -0
  90. package/components/variable-number/number.d.ts +1 -1
  91. package/components/variable-plugin/insert-variable-card.d.ts +14 -1
  92. package/package.json +8 -8
  93. package/plugins/variable-plugin/utils/number-to-words.d.ts +8 -0
  94. package/translations/en-US.yaml +3 -2
  95. package/translations/nl-BE.yaml +3 -2
  96. package/types/global.d.ts +2 -2
  97. package/types/lblod/marawa/rdfa-attributes.d.ts +1 -1
  98. package/types/lblod/marawa/rdfa-context-scanner.d.ts +1 -1
  99. package/types/lblod/marawa/rdfa-helpers.d.ts +3 -3
  100. package/utils/strings.d.ts +1 -0
@@ -73,7 +73,7 @@ export default class RdfaDatePluginDateTimePicker extends Component<Args> {
73
73
 
74
74
  function getLocalizedMonths(
75
75
  intl: Intl,
76
- monthFormat: 'long' | 'numeric' | '2-digit' | 'short' | 'narrow' = 'long'
76
+ monthFormat: 'long' | 'numeric' | '2-digit' | 'short' | 'narrow' = 'long',
77
77
  ) {
78
78
  const someYear = 2021;
79
79
  return [...Array(12).keys()].map((monthIndex) => {
@@ -84,7 +84,7 @@ function getLocalizedMonths(
84
84
 
85
85
  function getLocalizedDays(
86
86
  intl: Intl,
87
- weekdayFormat: 'long' | 'short' | 'narrow' = 'long'
87
+ weekdayFormat: 'long' | 'short' | 'narrow' = 'long',
88
88
  ) {
89
89
  const someSunday = new Date('2021-01-03');
90
90
  return [...Array(7).keys()].map((index) => {
@@ -30,8 +30,8 @@ export default class VariableComponent extends Component<Args> {
30
30
  tr.setSelection(
31
31
  NodeSelection.create(
32
32
  this.args.controller.activeEditorState.doc,
33
- this.args.getPos() as number
34
- )
33
+ this.args.getPos() as number,
34
+ ),
35
35
  );
36
36
  this.args.controller.activeEditorView.dispatch(tr);
37
37
  }
@@ -38,11 +38,11 @@ export default class RdfaDatePluginInsertComponent extends Component<Args> {
38
38
  onlyDate: true,
39
39
  format: this.defaultDateFormat,
40
40
  value: new Date().toISOString(),
41
- })
41
+ }),
42
42
  );
43
43
  if (tr.selection.$anchor.nodeBefore) {
44
44
  const resolvedPos = tr.doc.resolve(
45
- tr.selection.anchor - tr.selection.$anchor.nodeBefore?.nodeSize
45
+ tr.selection.anchor - tr.selection.$anchor.nodeBefore?.nodeSize,
46
46
  );
47
47
  tr.setSelection(new NodeSelection(resolvedPos));
48
48
  }
@@ -15,7 +15,7 @@ type Args = {
15
15
  insert: (
16
16
  measure: Measure,
17
17
  zonalityValue?: string,
18
- temporalValue?: string
18
+ temporalValue?: string,
19
19
  ) => void;
20
20
  };
21
21
 
@@ -35,7 +35,7 @@ export default class ExpandedMeasureComponent extends Component<Args> {
35
35
  changeZonality(event: InputEvent) {
36
36
  assert(
37
37
  'changeZonalityValue must be bound to an input element',
38
- event.target instanceof HTMLInputElement
38
+ event.target instanceof HTMLInputElement,
39
39
  );
40
40
  this.zonalityValue = event.target.value;
41
41
  }
@@ -43,7 +43,7 @@ export default class ExpandedMeasureComponent extends Component<Args> {
43
43
  changeTemporality(event: InputEvent) {
44
44
  assert(
45
45
  'changeTemporality must be bound to an input element',
46
- event.target instanceof HTMLInputElement
46
+ event.target instanceof HTMLInputElement,
47
47
  );
48
48
  this.temporalValue = event.target.value;
49
49
  }
@@ -27,12 +27,12 @@ export default class MeasureTemplateComponent extends Component<Args> {
27
27
  const instructions =
28
28
  await this.roadsignRegistry.getInstructionsForMeasure.perform(
29
29
  this.args.measure,
30
- this.endpoint
30
+ this.endpoint,
31
31
  );
32
32
  const template = includeInstructions(
33
33
  this.args.template,
34
34
  instructions,
35
- this.args.annotated
35
+ this.args.annotated,
36
36
  );
37
37
  this.template = template;
38
38
  });
@@ -52,7 +52,7 @@ export default class RoadsignRegulationCard extends Component<Args> {
52
52
  const besluitNode = findParentNode((node) => {
53
53
  if (node.type === this.schema.nodes['besluit']) {
54
54
  const rdfTypes = (node.attrs['typeof'] as string | undefined)?.split(
55
- ' '
55
+ ' ',
56
56
  );
57
57
  if (rdfTypes?.some((t) => acceptedTypes.includes(t))) {
58
58
  return true;
@@ -134,7 +134,7 @@ export default class RoadsignRegulationCard extends Component<Args> {
134
134
  changeDescription(event: InputEvent) {
135
135
  assert(
136
136
  'changeDescriptionValue must be bound to an input element',
137
- event.target instanceof HTMLInputElement
137
+ event.target instanceof HTMLInputElement,
138
138
  );
139
139
  this.descriptionFilter = event.target.value;
140
140
  this.search();
@@ -165,7 +165,7 @@ export default class RoadsignRegulationCard extends Component<Args> {
165
165
  this.endpoint,
166
166
  term,
167
167
  category,
168
- type
168
+ type,
169
169
  );
170
170
  }
171
171
 
@@ -183,7 +183,7 @@ export default class RoadsignRegulationCard extends Component<Args> {
183
183
  undefined,
184
184
  undefined,
185
185
  undefined,
186
- signs
186
+ signs,
187
187
  );
188
188
  this.codeCombinationOptions = codes;
189
189
  }
@@ -241,7 +241,7 @@ export default class RoadsignRegulationCard extends Component<Args> {
241
241
  ? this.categorySelected.value
242
242
  : undefined,
243
243
  pageStart: this.pageStart,
244
- }
244
+ },
245
245
  );
246
246
  this.tableData = measures;
247
247
  this.count = count;
@@ -251,18 +251,18 @@ export default class RoadsignRegulationCard extends Component<Args> {
251
251
  async insertHtml(
252
252
  measure: Measure,
253
253
  zonalityValue: string,
254
- temporalValue: string
254
+ temporalValue: string,
255
255
  ) {
256
256
  const instructions =
257
257
  await this.roadsignRegistry.fetchInstructionsForMeasure.perform(
258
258
  measure.uri,
259
- this.endpoint
259
+ this.endpoint,
260
260
  );
261
261
  const zonality = zonalityValue ? zonalityValue : measure.zonality;
262
262
  const html = includeInstructions(
263
263
  measure.annotatedTemplate,
264
264
  instructions,
265
- true
265
+ true,
266
266
  );
267
267
  const signsHTML = measure.signs
268
268
  .map((sign) => {
@@ -309,14 +309,14 @@ export default class RoadsignRegulationCard extends Component<Args> {
309
309
  const domParser = new DOMParser();
310
310
  const htmlNode = domParser.parseFromString(regulationHTML, 'text/html');
311
311
  const contentFragment = ProseParser.fromSchema(
312
- this.args.controller.schema
312
+ this.args.controller.schema,
313
313
  ).parseSlice(htmlNode, {
314
314
  preserveWhitespace: false,
315
315
  }).content;
316
316
 
317
317
  this.args.controller.doCommand(
318
318
  insertStructure(besluitArticleStructure, this.intl, contentFragment),
319
- { view: this.args.controller.mainEditorView }
319
+ { view: this.args.controller.mainEditorView },
320
320
  );
321
321
  this.args.closeModal();
322
322
  }
@@ -38,7 +38,7 @@ export default class SnippetPluginSearchModalComponent extends Component<Args> {
38
38
  setInputSearchText(event: InputEvent) {
39
39
  assert(
40
40
  'inputSearchText must be bound to an input element',
41
- event.target instanceof HTMLInputElement
41
+ event.target instanceof HTMLInputElement,
42
42
  );
43
43
 
44
44
  this.inputSearchText = event.target.value;
@@ -42,8 +42,8 @@ export default class SnippetInsertComponent extends Component<Args> {
42
42
  this.controller.withTransaction((tr) => {
43
43
  return tr.replaceSelectionWith(
44
44
  ProseParser.fromSchema(this.controller.schema).parse(
45
- domParser.parseFromString(content, 'text/html')
46
- )
45
+ domParser.parseFromString(content, 'text/html'),
46
+ ),
47
47
  );
48
48
  });
49
49
  }
@@ -19,7 +19,7 @@ type Args = {
19
19
 
20
20
  const HACKY_LOOKUP: Record<string, Resource> = {
21
21
  'http://data.vlaanderen.be/ns/besluit#BehandelingVanAgendapunt': BESLUIT(
22
- 'BehandelingVanAgendapunt'
22
+ 'BehandelingVanAgendapunt',
23
23
  ),
24
24
  'http://data.vlaanderen.be/ns/besluit#Besluit': BESLUIT('Besluit'),
25
25
  'http://data.vlaanderen.be/ns/besluit#Artikel': BESLUIT('Artikel'),
@@ -27,7 +27,7 @@ const HACKY_LOOKUP: Record<string, Resource> = {
27
27
 
28
28
  export function findAncestors(
29
29
  pos: ResolvedPos,
30
- predicate: (node: PNode) => boolean = () => true
30
+ predicate: (node: PNode) => boolean = () => true,
31
31
  ) {
32
32
  const result: { node: PNode; pos: number }[] = [];
33
33
  let depth = pos.depth;
@@ -59,7 +59,7 @@ export default class TemplateProviderComponent extends Component<Args> {
59
59
  get applicableTemplates() {
60
60
  return (
61
61
  this.standardTemplatePlugin.fetchTemplates.last?.value?.filter(
62
- (template) => this.templateIsApplicable(template)
62
+ (template) => this.templateIsApplicable(template),
63
63
  ) || []
64
64
  );
65
65
  }
@@ -74,7 +74,7 @@ export default class TemplateProviderComponent extends Component<Args> {
74
74
  }) ||
75
75
  findAncestors($from, (node) => {
76
76
  return template.contexts.some((type) =>
77
- pnodeHasRdfaAttribute(node, 'typeof', HACKY_LOOKUP[type])
77
+ pnodeHasRdfaAttribute(node, 'typeof', HACKY_LOOKUP[type]),
78
78
  );
79
79
  }).length;
80
80
  const containsDisabledTypes =
@@ -85,7 +85,7 @@ export default class TemplateProviderComponent extends Component<Args> {
85
85
  }) ||
86
86
  findAncestors($from, (node) => {
87
87
  return template.disabledInContexts.some((type) =>
88
- pnodeHasRdfaAttribute(node, 'typeof', HACKY_LOOKUP[type])
88
+ pnodeHasRdfaAttribute(node, 'typeof', HACKY_LOOKUP[type]),
89
89
  );
90
90
  }).length;
91
91
 
@@ -118,9 +118,9 @@ export default class TemplateProviderComponent extends Component<Args> {
118
118
  insertHtml(
119
119
  instantiateUuids(template.body),
120
120
  insertRange.from,
121
- insertRange.to
121
+ insertRange.to,
122
122
  ),
123
- { view: this.controller.mainEditorView }
123
+ { view: this.controller.mainEditorView },
124
124
  );
125
125
  }
126
126
  }
@@ -65,7 +65,7 @@ export default class TableOfContentsComponent extends Component<EmberNodeArgs> {
65
65
  const subResults: OutlineEntry[] = [];
66
66
  node.forEach((child, offset) => {
67
67
  subResults.push(
68
- ...this.extractOutline({ node: child, pos: pos + 1 + offset })
68
+ ...this.extractOutline({ node: child, pos: pos + 1 + offset }),
69
69
  );
70
70
  });
71
71
  if (parent) {
@@ -85,7 +85,7 @@ export default class TableOfContentsComponent extends Component<EmberNodeArgs> {
85
85
  if (selection) {
86
86
  tr.setSelection(selection);
87
87
  const coords = this.controller.mainEditorView.coordsAtPos(
88
- selection.from
88
+ selection.from,
89
89
  );
90
90
  const config = this.config[0];
91
91
  let scrollContainer: HTMLElement | undefined;
@@ -109,7 +109,7 @@ export default class TableOfContentsComponent extends Component<EmberNodeArgs> {
109
109
  0,
110
110
  coords.top +
111
111
  alreadyScrolled -
112
- (scrollContainerDistanceToTop + topPadding)
112
+ (scrollContainerDistanceToTop + topPadding),
113
113
  );
114
114
  } else {
115
115
  tr.scrollIntoView();
@@ -34,7 +34,7 @@ export default class TableOfContentsCardComponent extends Component<Args> {
34
34
  (tr) => {
35
35
  return tr.deleteRange(from, to);
36
36
  },
37
- { view: this.controller.mainEditorView }
37
+ { view: this.controller.mainEditorView },
38
38
  );
39
39
  } else {
40
40
  const { schema } = this.controller;
@@ -46,7 +46,7 @@ export default class TableOfContentsCardComponent extends Component<Args> {
46
46
  state.doc.canReplaceWith(
47
47
  index,
48
48
  index,
49
- schema.nodes['table_of_contents']
49
+ schema.nodes['table_of_contents'],
50
50
  )
51
51
  ) {
52
52
  replacePosition = pos;
@@ -56,7 +56,7 @@ export default class TableOfContentsCardComponent extends Component<Args> {
56
56
  state.doc.canReplaceWith(
57
57
  index + 1,
58
58
  index + 1,
59
- schema.nodes['table_of_contents']
59
+ schema.nodes['table_of_contents'],
60
60
  )
61
61
  ) {
62
62
  replacePosition = pos + node.nodeSize;
@@ -69,10 +69,10 @@ export default class TableOfContentsCardComponent extends Component<Args> {
69
69
  return transaction.replaceWith(
70
70
  replacePosition as number,
71
71
  replacePosition as number,
72
- schema.node('table_of_contents')
72
+ schema.node('table_of_contents'),
73
73
  );
74
74
  },
75
- { view: this.controller.mainEditorView }
75
+ { view: this.controller.mainEditorView },
76
76
  );
77
77
  }
78
78
  }
@@ -8,8 +8,7 @@ import {
8
8
  TextSelection,
9
9
  } from '@lblod/ember-rdfa-editor';
10
10
  import { action } from '@ember/object';
11
- import { tracked } from '@glimmer/tracking';
12
- import { service } from '@ember/service';
11
+ import { inject as service } from '@ember/service';
13
12
  import intlService from 'ember-intl/services/intl';
14
13
  import { localCopy } from 'tracked-toolbox';
15
14
  import {
@@ -17,7 +16,8 @@ import {
17
16
  MINIMUM_VALUE_PNODE_KEY,
18
17
  } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/variable-plugin/utils/constants';
19
18
  import { isBlank } from '@ember/utils';
20
- import n2words from 'n2words';
19
+ import { isNumber } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/strings';
20
+ import { numberToWords } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/variable-plugin/utils/number-to-words';
21
21
 
22
22
  type Args = {
23
23
  getPos: () => number | undefined;
@@ -32,7 +32,6 @@ export default class VariableNumberPluginNumberComponent extends Component<Args>
32
32
  @localCopy('args.node.attrs.value', '') declare inputNumber: string;
33
33
  @localCopy('args.node.attrs.writtenNumber', false)
34
34
  declare writtenNumber: boolean;
35
- @tracked errorMessage = '';
36
35
  @service declare intl: intlService;
37
36
  cursorPositionKeyDown: number | null = null;
38
37
 
@@ -46,13 +45,13 @@ export default class VariableNumberPluginNumberComponent extends Component<Args>
46
45
  get formattedNumber() {
47
46
  const value = this.node.attrs.value as string;
48
47
 
49
- if (Number.isNaN(Number(value)) || value === null || value === '') {
48
+ if (!isNumber(value)) {
50
49
  return value;
51
50
  }
52
51
  if (!this.writtenNumber) {
53
52
  return value;
54
53
  } else {
55
- return n2words(Number(value), { lang: 'nl' });
54
+ return numberToWords(Number(value), { lang: 'nl' });
56
55
  }
57
56
  }
58
57
 
@@ -78,41 +77,41 @@ export default class VariableNumberPluginNumberComponent extends Component<Args>
78
77
  this.args.updateAttribute('writtenNumber', !this.writtenNumber);
79
78
  }
80
79
 
81
- validateAndSave() {
80
+ get errorMessage() {
82
81
  if (isBlank(this.inputNumber)) {
83
- this.errorMessage = '';
84
- this.args.updateAttribute('value', '');
85
- return;
82
+ return '';
86
83
  }
87
-
88
84
  const number = Number(this.inputNumber);
89
85
  if (Number.isNaN(number)) {
90
- this.errorMessage = this.intl.t('variable.number.error-not-number');
91
- return;
86
+ return this.intl.t('variable.number.error-not-number');
92
87
  }
93
88
  const validMinimum = !this.minValue || number >= this.minValue;
94
89
  const validMaximum = !this.maxValue || number <= this.maxValue;
95
90
 
96
91
  if (!validMinimum || !validMaximum) {
97
92
  if (this.minValue && this.maxValue) {
98
- this.errorMessage = this.intl.t(
99
- 'variable.number.error-number-between',
100
- { minValue: this.minValue, maxValue: this.maxValue }
101
- );
93
+ return this.intl.t('variable.number.error-number-between', {
94
+ minValue: this.minValue,
95
+ maxValue: this.maxValue,
96
+ });
102
97
  } else if (this.minValue) {
103
- this.errorMessage = this.intl.t('variable.number.error-number-above', {
98
+ return this.intl.t('variable.number.error-number-above', {
104
99
  minValue: this.minValue,
105
100
  });
106
101
  } else if (this.maxValue) {
107
- this.errorMessage = this.intl.t('variable.number.error-number-below', {
102
+ return this.intl.t('variable.number.error-number-below', {
108
103
  maxValue: this.maxValue,
109
104
  });
110
105
  }
111
- return;
112
106
  }
107
+ return '';
108
+ }
113
109
 
114
- this.errorMessage = '';
115
- this.args.updateAttribute('value', this.inputNumber);
110
+ @action
111
+ validateAndSave() {
112
+ if (!this.errorMessage) {
113
+ this.args.updateAttribute('value', this.inputNumber);
114
+ }
116
115
  }
117
116
 
118
117
  @action
@@ -121,8 +120,8 @@ export default class VariableNumberPluginNumberComponent extends Component<Args>
121
120
  tr.setSelection(
122
121
  NodeSelection.create(
123
122
  this.args.controller.activeEditorState.doc,
124
- this.args.getPos() as number
125
- )
123
+ this.args.getPos() as number,
124
+ ),
126
125
  );
127
126
  this.args.controller.activeEditorView.dispatch(tr);
128
127
  }
@@ -155,7 +154,7 @@ export default class VariableNumberPluginNumberComponent extends Component<Args>
155
154
  setSelectionAt(pos: number) {
156
155
  const tr = this.args.controller.activeEditorState.tr;
157
156
  tr.setSelection(
158
- TextSelection.create(this.args.controller.activeEditorState.doc, pos)
157
+ TextSelection.create(this.args.controller.activeEditorState.doc, pos),
159
158
  );
160
159
  this.args.controller.focus();
161
160
  this.args.controller.activeEditorView.dispatch(tr);
@@ -163,7 +162,7 @@ export default class VariableNumberPluginNumberComponent extends Component<Args>
163
162
 
164
163
  selectAfterNode() {
165
164
  this.setSelectionAt(
166
- (this.args.getPos() as number) + this.args.node.nodeSize
165
+ (this.args.getPos() as number) + this.args.node.nodeSize,
167
166
  );
168
167
  }
169
168
 
@@ -53,6 +53,7 @@
53
53
  <VariablePlugin::NumberSettings
54
54
  @minimumValue={{this.extraAttributes.minimumValue}}
55
55
  @maximumValue={{this.extraAttributes.maximumValue}}
56
+ @error={{this.numberVariableError}}
56
57
  />
57
58
  {{/if}}
58
59
  <AuButton
@@ -60,6 +61,7 @@
60
61
  @disabled={{or
61
62
  (not this.selectedVariable)
62
63
  (and this.hasSubtype (not this.selectedSubtype))
64
+ this.numberVariableError
63
65
  }}
64
66
  >{{t 'variable-plugin.button'}}</AuButton>
65
67
  </c.content>
@@ -10,6 +10,10 @@ import {
10
10
  import { CodeList } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/variable-plugin/utils/fetch-data';
11
11
  import { findParentNodeOfType } from '@curvenote/prosemirror-utils';
12
12
  import { NodeSelection } from '@lblod/ember-rdfa-editor';
13
+ import { service } from '@ember/service';
14
+ import IntlService from 'ember-intl/services/intl';
15
+ import { isNumber } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/strings';
16
+
13
17
  type Args = {
14
18
  controller: SayController;
15
19
  options: {
@@ -19,6 +23,28 @@ type Args = {
19
23
  };
20
24
  };
21
25
 
26
+ type minMaxObj = { minimumValue?: number; maximumValue?: number };
27
+ class ExtraAttributes {
28
+ @tracked minimumValue = '';
29
+ @tracked maximumValue = '';
30
+
31
+ asObject(): minMaxObj {
32
+ const obj: minMaxObj = {};
33
+ if (isNumber(this.minimumValue)) {
34
+ obj.minimumValue = Number(this.minimumValue);
35
+ }
36
+ if (isNumber(this.maximumValue)) {
37
+ obj.maximumValue = Number(this.maximumValue);
38
+ }
39
+ return obj;
40
+ }
41
+
42
+ reset() {
43
+ this.minimumValue = '';
44
+ this.maximumValue = '';
45
+ }
46
+ }
47
+
22
48
  export default class EditorPluginsInsertCodelistCardComponent extends Component<Args> {
23
49
  @tracked variablesArray: VariableType[];
24
50
  @tracked selectedVariable?: VariableType;
@@ -26,10 +52,12 @@ export default class EditorPluginsInsertCodelistCardComponent extends Component<
26
52
  @tracked selectedSubtype?: CodeList;
27
53
  @tracked subtypes?: CodeList[];
28
54
  @tracked variableLabel?: string;
29
- @tracked extraAttributes: Record<string, unknown> = {};
55
+ @tracked extraAttributes = new ExtraAttributes();
30
56
  publisher: string;
31
57
  endpoint: string;
32
58
 
59
+ @service declare intl: IntlService;
60
+
33
61
  constructor(parent: unknown, args: Args) {
34
62
  super(parent, args);
35
63
  const { publisher, variableTypes, defaultEndpoint } =
@@ -52,7 +80,7 @@ export default class EditorPluginsInsertCodelistCardComponent extends Component<
52
80
  variablesArray.push(variableType);
53
81
  } else {
54
82
  console.warn(
55
- `Template Variable Plugin: variable type ${type} not found in the default variable types`
83
+ `Template Variable Plugin: variable type ${type} not found in the default variable types`,
56
84
  );
57
85
  }
58
86
  } else {
@@ -66,6 +94,20 @@ export default class EditorPluginsInsertCodelistCardComponent extends Component<
66
94
  return this.args.controller;
67
95
  }
68
96
 
97
+ get numberVariableError() {
98
+ const minVal = this.extraAttributes.minimumValue;
99
+ const maxVal = this.extraAttributes.maximumValue;
100
+ if (
101
+ isNumber(minVal) &&
102
+ isNumber(maxVal) &&
103
+ Number(minVal) > Number(maxVal)
104
+ ) {
105
+ return this.intl.t('variable.number.error-min-bigger-than-max');
106
+ }
107
+
108
+ return '';
109
+ }
110
+
69
111
  @action
70
112
  updateVariableLabel(event: InputEvent) {
71
113
  this.variableLabel = (event.target as HTMLInputElement).value;
@@ -73,7 +115,7 @@ export default class EditorPluginsInsertCodelistCardComponent extends Component<
73
115
 
74
116
  @action
75
117
  insert() {
76
- if (!this.selectedVariable) {
118
+ if (!this.selectedVariable || this.numberVariableError) {
77
119
  return;
78
120
  }
79
121
 
@@ -83,18 +125,18 @@ export default class EditorPluginsInsertCodelistCardComponent extends Component<
83
125
  label: this.variableLabel !== '' ? this.variableLabel : undefined,
84
126
  attributes: {
85
127
  source: this.endpoint,
86
- ...this.extraAttributes,
128
+ ...this.extraAttributes.asObject(),
87
129
  },
88
130
  });
89
131
 
90
132
  this.variableLabel = '';
91
- this.extraAttributes = {};
133
+ this.extraAttributes.reset();
92
134
 
93
135
  this.controller.withTransaction(
94
136
  (tr) => {
95
137
  return tr.replaceSelectionWith(node);
96
138
  },
97
- { view: this.controller.mainEditorView }
139
+ { view: this.controller.mainEditorView },
98
140
  );
99
141
  }
100
142
 
@@ -113,18 +155,18 @@ export default class EditorPluginsInsertCodelistCardComponent extends Component<
113
155
  async (
114
156
  fetchFunction: (
115
157
  endpoint: string,
116
- publisher: string
117
- ) => Promise<CodeList[]>
158
+ publisher: string,
159
+ ) => Promise<CodeList[]>,
118
160
  ) => {
119
161
  const subtypes = await fetchFunction(this.endpoint, this.publisher);
120
162
  this.subtypes = subtypes;
121
- }
163
+ },
122
164
  );
123
165
 
124
166
  @action
125
167
  updateSubtype(subtype: CodeList) {
126
168
  this.selectedSubtype = subtype;
127
- this.extraAttributes = {};
169
+ this.extraAttributes.reset();
128
170
  }
129
171
 
130
172
  get type() {
@@ -143,7 +185,7 @@ export default class EditorPluginsInsertCodelistCardComponent extends Component<
143
185
  return false;
144
186
  } else {
145
187
  const variable = findParentNodeOfType(
146
- this.args.controller.schema.nodes.variable
188
+ this.args.controller.schema.nodes.variable,
147
189
  )(selection);
148
190
  return !variable;
149
191
  }
@@ -28,4 +28,9 @@
28
28
  />
29
29
  {{/let}}
30
30
  </AuFormRow>
31
+ {{#if @error}}
32
+ <AuHelpText @error={{true}}>
33
+ {{@error}}
34
+ </AuHelpText>
35
+ {{/if}}
31
36
  </div>