@lblod/ember-rdfa-editor-lblod-plugins 13.0.0 → 14.1.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 (66) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/README.md +1 -1
  3. package/addon/components/besluit-type-plugin/toolbar-dropdown.ts +1 -8
  4. package/addon/components/citation-plugin/citation-card.hbs +7 -7
  5. package/addon/components/citation-plugin/citation-card.ts +21 -16
  6. package/addon/components/citation-plugin/citation-insert.hbs +1 -1
  7. package/addon/components/citation-plugin/citation-insert.ts +8 -8
  8. package/addon/components/citation-plugin/citations/article-preview.hbs +1 -1
  9. package/addon/components/citation-plugin/citations/article-preview.ts +13 -0
  10. package/addon/components/citation-plugin/citations/{decision-detail.hbs → legal-document-detail.hbs} +6 -6
  11. package/addon/components/citation-plugin/citations/{decision-detail.ts → legal-document-detail.ts} +6 -3
  12. package/addon/components/citation-plugin/citations/{decision-list.hbs → legal-document-list.hbs} +6 -6
  13. package/addon/components/citation-plugin/citations/{decision-preview.hbs → legal-document-preview.hbs} +5 -5
  14. package/addon/components/citation-plugin/citations/{decision-preview.ts → legal-document-preview.ts} +4 -4
  15. package/addon/components/citation-plugin/citations/search-modal.hbs +12 -12
  16. package/addon/components/citation-plugin/citations/search-modal.ts +22 -19
  17. package/addon/components/standard-template-plugin/card.hbs +1 -1
  18. package/addon/components/standard-template-plugin/card.ts +5 -0
  19. package/addon/components/standard-template-plugin/template-provider.hbs +1 -2
  20. package/addon/components/standard-template-plugin/template-provider.ts +6 -14
  21. package/addon/components/variable-plugin/address/edit.hbs +13 -11
  22. package/addon/components/variable-plugin/address/edit.ts +88 -22
  23. package/addon/components/variable-plugin/date/edit.hbs +12 -10
  24. package/addon/components/variable-plugin/date/edit.ts +7 -0
  25. package/addon/models/template.ts +6 -13
  26. package/addon/plugins/besluit-type-plugin/index.ts +1 -0
  27. package/addon/plugins/citation-plugin/index.ts +1 -1
  28. package/addon/plugins/citation-plugin/utils/legal-documents.ts +3 -3
  29. package/addon/plugins/citation-plugin/utils/public-decisions.ts +6 -4
  30. package/addon/plugins/citation-plugin/utils/types.ts +7 -3
  31. package/addon/plugins/standard-template-plugin/index.ts +2 -0
  32. package/addon/plugins/standard-template-plugin/utils/instantiate-uuids.ts +5 -13
  33. package/addon/plugins/variable-plugin/utils/address-helpers.ts +19 -5
  34. package/addon/plugins/variable-plugin/variables/date.ts +15 -2
  35. package/addon/utils/memoize.ts +11 -3
  36. package/app/components/citation-plugin/citations/{decision-list.js → legal-document-detail.js} +1 -1
  37. package/app/components/citation-plugin/citations/{decision-detail.js → legal-document-list.js} +1 -1
  38. package/app/components/citation-plugin/citations/{decision-preview.js → legal-document-preview.js} +1 -1
  39. package/components/besluit-type-plugin/toolbar-dropdown.d.ts +0 -2
  40. package/components/citation-plugin/citation-card.d.ts +7 -7
  41. package/components/citation-plugin/citation-insert.d.ts +2 -2
  42. package/components/citation-plugin/citations/article-preview.d.ts +9 -0
  43. package/components/citation-plugin/citations/{decision-detail.d.ts → legal-document-detail.d.ts} +2 -2
  44. package/components/citation-plugin/citations/{decision-preview.d.ts → legal-document-preview.d.ts} +2 -2
  45. package/components/citation-plugin/citations/search-modal.d.ts +10 -11
  46. package/components/standard-template-plugin/card.d.ts +3 -0
  47. package/components/standard-template-plugin/template-provider.d.ts +5 -7
  48. package/components/variable-plugin/address/edit.d.ts +5 -3
  49. package/components/variable-plugin/date/edit.d.ts +1 -0
  50. package/models/template.d.ts +1 -7
  51. package/package.json +2 -9
  52. package/plugins/besluit-type-plugin/index.d.ts +1 -0
  53. package/plugins/citation-plugin/utils/types.d.ts +5 -4
  54. package/plugins/standard-template-plugin/index.d.ts +1 -0
  55. package/plugins/variable-plugin/utils/address-helpers.d.ts +3 -2
  56. package/translations/en-US.yaml +2 -0
  57. package/translations/nl-BE.yaml +2 -0
  58. package/utils/memoize.d.ts +6 -1
  59. package/addon/services/standard-template-plugin.ts +0 -55
  60. package/app/services/standard-template-plugin.js +0 -1
  61. package/services/standard-template-plugin.d.ts +0 -20
  62. package/types/lblod/frontend-gelinkt-notuleren/models/account.d.ts +0 -10
  63. package/types/lblod/frontend-gelinkt-notuleren/models/bestuurseenheid-classificatie-code.d.ts +0 -10
  64. package/types/lblod/frontend-gelinkt-notuleren/models/bestuurseenheid.d.ts +0 -12
  65. package/types/lblod/frontend-gelinkt-notuleren/models/gebruiker-model.d.ts +0 -18
  66. package/types/lblod/frontend-gelinkt-notuleren/services/current-session.d.ts +0 -30
@@ -1,4 +1,4 @@
1
- <StandardTemplatePlugin::TemplateProvider @controller={{@controller}} as |provider|>
1
+ <StandardTemplatePlugin::TemplateProvider @controller={{@controller}} @templates={{@templates}} as |provider|>
2
2
  {{#if provider.hasApplicableTemplates}}
3
3
  {{#each provider.applicableTemplates as |template|}}
4
4
  <AuList::Item>
@@ -1,11 +1,16 @@
1
1
  import Component from '@glimmer/component';
2
2
  import { SayController } from '@lblod/ember-rdfa-editor';
3
+ import StandardTemplate from '@lblod/ember-rdfa-editor-lblod-plugins/models/template';
3
4
 
4
5
  type Args = {
5
6
  controller: SayController;
7
+ templates: StandardTemplate[];
6
8
  };
7
9
  export default class StandardTemplatePluginCardComponent extends Component<Args> {
8
10
  get controller() {
9
11
  return this.args.controller;
10
12
  }
13
+ get templates() {
14
+ return this.args.templates;
15
+ }
11
16
  }
@@ -1,8 +1,7 @@
1
- <div {{did-insert (perform this.standardTemplatePlugin.fetchTemplates)}}>
1
+ <div>
2
2
  {{yield (hash
3
3
  applicableTemplates=this.applicableTemplates
4
4
  hasApplicableTemplates=this.hasApplicableTemplates
5
- busy=this.busy
6
5
  insert=this.insert
7
6
  )}}
8
7
  </div>
@@ -1,9 +1,7 @@
1
1
  import Component from '@glimmer/component';
2
2
  import { action } from '@ember/object';
3
- import { inject as service } from '@ember/service';
4
- import StandardTemplatePluginService from '@lblod/ember-rdfa-editor-lblod-plugins/services/standard-template-plugin';
5
3
  import { SayController } from '@lblod/ember-rdfa-editor';
6
- import TemplateModel from '@lblod/ember-rdfa-editor-lblod-plugins/models/template';
4
+ import StandardTemplate from '@lblod/ember-rdfa-editor-lblod-plugins/models/template';
7
5
  import { insertHtml } from '@lblod/ember-rdfa-editor/commands/insert-html-command';
8
6
  import instantiateUuids from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/standard-template-plugin/utils/instantiate-uuids';
9
7
  import { PNode, ResolvedPos } from '@lblod/ember-rdfa-editor';
@@ -15,6 +13,7 @@ import {
15
13
 
16
14
  type Args = {
17
15
  controller: SayController;
16
+ templates: StandardTemplate[];
18
17
  };
19
18
 
20
19
  const HACKY_LOOKUP: Record<string, Resource> = {
@@ -42,12 +41,6 @@ export function findAncestors(
42
41
  }
43
42
 
44
43
  export default class TemplateProviderComponent extends Component<Args> {
45
- @service declare standardTemplatePlugin: StandardTemplatePluginService;
46
-
47
- get busy() {
48
- return this.standardTemplatePlugin.fetchTemplates.isRunning;
49
- }
50
-
51
44
  get controller() {
52
45
  return this.args.controller;
53
46
  }
@@ -58,13 +51,13 @@ export default class TemplateProviderComponent extends Component<Args> {
58
51
 
59
52
  get applicableTemplates() {
60
53
  return (
61
- this.standardTemplatePlugin.fetchTemplates.last?.value?.filter(
62
- (template) => this.templateIsApplicable(template),
54
+ this.args.templates.filter((template) =>
55
+ this.templateIsApplicable(template),
63
56
  ) || []
64
57
  );
65
58
  }
66
59
 
67
- templateIsApplicable(template: TemplateModel) {
60
+ templateIsApplicable(template: StandardTemplate) {
68
61
  const { $from } = this.controller.mainEditorState.selection;
69
62
  const containsTypes =
70
63
  this.controller.externalContextStore
@@ -93,8 +86,7 @@ export default class TemplateProviderComponent extends Component<Args> {
93
86
  }
94
87
 
95
88
  @action
96
- async insert(template: TemplateModel) {
97
- await template.reload();
89
+ insert(template: StandardTemplate) {
98
90
  const selection = this.controller.mainEditorState.selection;
99
91
  let insertRange: { from: number; to: number } = selection;
100
92
  const { $from, $to } = selection;
@@ -11,6 +11,7 @@
11
11
  @searchMessage={{t "editor-plugins.address.edit.municipality.search-message"}}
12
12
  @noMatchesMessage={{t "editor-plugins.address.edit.municipality.no-results"}}
13
13
  @placeholder={{t "editor-plugins.address.edit.municipality.placeholder"}}
14
+ @allowClear={{true}}
14
15
  @renderInPlace={{true}}
15
16
  @searchEnabled={{true}}
16
17
  @search={{perform this.searchMunicipality}}
@@ -27,6 +28,7 @@
27
28
  @searchMessage={{t "editor-plugins.address.edit.street.search-message"}}
28
29
  @noMatchesMessage={{t "editor-plugins.address.edit.street.no-results"}}
29
30
  @placeholder={{t "editor-plugins.address.edit.street.placeholder"}}
31
+ @allowClear={{true}}
30
32
  @renderInPlace={{true}}
31
33
  @searchEnabled={{true}}
32
34
  @search={{perform this.searchStreet}}
@@ -40,11 +42,11 @@
40
42
  <AuLabel for="housenumber-select">
41
43
  {{t "editor-plugins.address.edit.housenumber.label"}}
42
44
  </AuLabel>
43
- <AuNativeInput
45
+ <AuNativeInput
44
46
  id="housenumber-select"
45
47
  placeholder={{t "editor-plugins.address.edit.housenumber.placeholder"}}
46
- @width="block"
47
- value={{this.newHousenumber}}
48
+ @width="block"
49
+ value={{this.newHousenumber}}
48
50
  @disabled={{not this.canUpdateHousenumber}}
49
51
  {{on 'input' this.updateHousenumber}}
50
52
  />
@@ -53,17 +55,17 @@
53
55
  <AuLabel for="busnumber-select">
54
56
  {{t "editor-plugins.address.edit.busnumber.label"}}
55
57
  </AuLabel>
56
- <AuNativeInput
58
+ <AuNativeInput
57
59
  id="busnumber-select"
58
60
  placeholder={{t "editor-plugins.address.edit.busnumber.placeholder"}}
59
- @width="block"
60
- value={{this.newBusnumber}}
61
+ @width="block"
62
+ value={{this.newBusnumber}}
61
63
  @disabled={{not this.canUpdateBusnumber}}
62
64
  {{on 'input' this.updateBusnumber}}
63
65
  />
64
66
  </div>
65
67
  </div>
66
-
68
+
67
69
  {{#if this.newAddress.isRunning}}
68
70
  <LoadingAlert @title={{t "editor-plugins.address.edit.loading"}} @size="small" @skin="info"/>
69
71
  {{/if}}
@@ -72,14 +74,14 @@
72
74
  {{this.message.body}}
73
75
  </AuAlert>
74
76
  {{/if}}
75
- <AuButton
76
- {{on 'click' this.updateAddressVariable}}
77
+ <AuButton
78
+ {{on 'click' this.updateAddressVariable}}
77
79
  @disabled={{not this.canUpdateAddressVariable}}>
78
80
  {{t "editor-plugins.utils.insert"}}
79
81
  </AuButton>
80
-
82
+
81
83
  </form>
82
-
84
+
83
85
  </c.content>
84
86
  </AuCard>
85
87
  {{/if}}
@@ -10,7 +10,7 @@ import {
10
10
  resolveStreet,
11
11
  } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/variable-plugin/utils/address-helpers';
12
12
  import { restartableTask, timeout } from 'ember-concurrency';
13
- import { localCopy, trackedReset } from 'tracked-toolbox';
13
+ import { trackedReset } from 'tracked-toolbox';
14
14
  import { trackedTask } from 'ember-resources/util/ember-concurrency';
15
15
  import { inject as service } from '@ember/service';
16
16
  import IntlService from 'ember-intl/services/intl';
@@ -23,9 +23,9 @@ type Args = {
23
23
  export default class AddressEditComponent extends Component<Args> {
24
24
  @service declare intl: IntlService;
25
25
 
26
- @trackedReset<AddressEditComponent, string | undefined>({
26
+ @trackedReset({
27
27
  memo: 'currentAddress',
28
- update(component) {
28
+ update(component: AddressEditComponent) {
29
29
  const { currentMunicipality } = component;
30
30
  return currentMunicipality
31
31
  ? currentMunicipality
@@ -34,14 +34,33 @@ export default class AddressEditComponent extends Component<Args> {
34
34
  })
35
35
  newMunicipality?: string;
36
36
 
37
- @localCopy('currentStreetName') newStreetName?: string;
37
+ @trackedReset({
38
+ memo: 'currentAddress',
39
+ update(component: AddressEditComponent) {
40
+ return component.currentStreetName;
41
+ },
42
+ })
43
+ newStreetName?: string;
38
44
 
39
- @localCopy('currentHousenumber') newHousenumber?: string;
45
+ @trackedReset({
46
+ memo: 'currentAddress',
47
+ update(component: AddressEditComponent) {
48
+ return component.currentHousenumber;
49
+ },
50
+ })
51
+ newHousenumber?: string;
40
52
 
41
- @localCopy('currentBusnumber') newBusnumber?: string;
53
+ @trackedReset({
54
+ memo: 'currentAddress',
55
+ update(component: AddressEditComponent) {
56
+ return component.currentBusnumber;
57
+ },
58
+ })
59
+ newBusnumber?: string;
42
60
 
43
61
  get message() {
44
62
  const value = this.newAddress.value as Address | undefined;
63
+
45
64
  if (
46
65
  this.newAddress.isSuccessful &&
47
66
  value &&
@@ -53,11 +72,28 @@ export default class AddressEditComponent extends Component<Args> {
53
72
  title: this.intl.t('editor-plugins.address.edit.success.address-found'),
54
73
  body: value.formatted,
55
74
  };
56
- } else if (
75
+ }
76
+
77
+ if (
57
78
  this.newAddress.isError &&
58
79
  this.newAddress.error instanceof AddressError
59
80
  ) {
60
81
  const { error } = this.newAddress;
82
+
83
+ if (this.newAddress.error.alternativeAddress) {
84
+ return {
85
+ skin: 'warning',
86
+ icon: 'alert-triangle',
87
+ title: this.intl.t(
88
+ 'editor-plugins.address.edit.errors.address-not-found-short',
89
+ ),
90
+ body: this.intl.t(
91
+ 'editor-plugins.address.edit.errors.alternative-address',
92
+ { address: this.newAddress.error.alternativeAddress.formatted },
93
+ ),
94
+ };
95
+ }
96
+
61
97
  return {
62
98
  skin: 'warning',
63
99
  icon: 'alert-triangle',
@@ -67,9 +103,9 @@ export default class AddressEditComponent extends Component<Args> {
67
103
  email: 'gelinktnotuleren@vlaanderen.be',
68
104
  }),
69
105
  };
70
- } else {
71
- return;
72
106
  }
107
+
108
+ return;
73
109
  }
74
110
 
75
111
  get currentAddress() {
@@ -127,12 +163,38 @@ export default class AddressEditComponent extends Component<Args> {
127
163
  return !!this.selectedAddressVariable;
128
164
  }
129
165
 
166
+ get alternativeAddressFromError() {
167
+ if (
168
+ this.newAddress.isError &&
169
+ this.newAddress.error instanceof AddressError &&
170
+ this.newAddress.error.alternativeAddress
171
+ ) {
172
+ return this.newAddress.error.alternativeAddress;
173
+ }
174
+
175
+ return undefined;
176
+ }
177
+
178
+ get addressToInsert() {
179
+ if (this.newAddress.isSuccessful) {
180
+ return this.newAddress.value;
181
+ }
182
+
183
+ return this.alternativeAddressFromError;
184
+ }
185
+
130
186
  get canUpdateAddressVariable() {
131
- return (
132
- this.newAddress.isSuccessful &&
133
- this.newAddress.value &&
134
- !this.currentAddress?.sameAs(this.newAddress.value as Address)
135
- );
187
+ const addressToInsert = this.addressToInsert;
188
+
189
+ if (!addressToInsert) {
190
+ return false;
191
+ }
192
+
193
+ if (this.currentAddress?.sameAs(this.addressToInsert)) {
194
+ return false;
195
+ }
196
+
197
+ return true;
136
198
  }
137
199
 
138
200
  resolveAddressTask = restartableTask(async () => {
@@ -169,19 +231,23 @@ export default class AddressEditComponent extends Component<Args> {
169
231
  }
170
232
  });
171
233
 
172
- newAddress = trackedTask(this, this.resolveAddressTask, () => [
173
- this.newMunicipality,
174
- this.newStreetName,
175
- this.newHousenumber,
176
- this.newBusnumber,
177
- ]);
234
+ newAddress = trackedTask<Address | undefined>(
235
+ this,
236
+ this.resolveAddressTask,
237
+ () => [
238
+ this.newMunicipality,
239
+ this.newStreetName,
240
+ this.newHousenumber,
241
+ this.newBusnumber,
242
+ ],
243
+ );
178
244
 
179
245
  @action
180
246
  updateAddressVariable() {
181
- if (this.selectedAddressVariable && this.newAddress.isSuccessful) {
247
+ if (this.selectedAddressVariable && this.addressToInsert) {
182
248
  const { pos } = this.selectedAddressVariable;
183
249
  this.controller.withTransaction((tr) => {
184
- return tr.setNodeAttribute(pos, 'value', this.newAddress.value);
250
+ return tr.setNodeAttribute(pos, 'value', this.addressToInsert);
185
251
  });
186
252
  }
187
253
  }
@@ -56,16 +56,18 @@
56
56
  />
57
57
  </AuFormRow>
58
58
  {{/each}}
59
- <AuFormRow>
60
- <AuControlRadio
61
- @label={{t "date-plugin.card.custom-date" }}
62
- @identifier="custom"
63
- @name="dateFormat"
64
- @value="custom"
65
- checked={{eq this.dateFormatType "custom"}}
66
- @onChange={{this.setDateFormatFromKey}}
67
- />
68
- </AuFormRow>
59
+ {{#if this.isCustomAllowed}}
60
+ <AuFormRow>
61
+ <AuControlRadio
62
+ @label={{t "date-plugin.card.custom-date" }}
63
+ @identifier="custom"
64
+ @name="dateFormat"
65
+ @value="custom"
66
+ checked={{eq this.dateFormatType "custom"}}
67
+ @onChange={{this.setDateFormatFromKey}}
68
+ />
69
+ </AuFormRow>
70
+ {{/if}}
69
71
  {{#if (eq this.dateFormatType "custom")}}
70
72
  <AuFormRow @alignment="post">
71
73
  <AuButton @skin="secondary" @icon="info-circle"
@@ -125,6 +125,13 @@ export default class DateEditComponent extends Component<Args> {
125
125
  return unwrapOr(false, this.selectedDateNode?.attrs.custom as boolean);
126
126
  }
127
127
 
128
+ get isCustomAllowed(): boolean {
129
+ return unwrapOr(
130
+ true,
131
+ this.selectedDateNode?.attrs.customAllowed as boolean,
132
+ );
133
+ }
134
+
128
135
  get dateFormatType(): string {
129
136
  if (this.isCustom) {
130
137
  return 'custom';
@@ -1,14 +1,7 @@
1
- import Model, { attr } from '@ember-data/model';
2
- declare module 'ember-data/types/registries/model' {
3
- export default interface ModelRegistry {
4
- template: TemplateModel;
5
- }
6
- }
7
- export default class TemplateModel extends Model {
8
- @attr declare title: string;
9
- @attr('string-set', { defaultValue: () => [] }) declare matches: string[];
10
- @attr declare body: string;
11
- @attr('string-set', { defaultValue: () => [] }) declare contexts: string[];
12
- @attr('string-set', { defaultValue: () => [] })
13
- declare disabledInContexts: string[];
1
+ export default interface StandardTemplate {
2
+ title: string;
3
+ matches: string[];
4
+ body: string;
5
+ contexts: string[];
6
+ disabledInContexts: string[];
14
7
  }
@@ -1,3 +1,4 @@
1
1
  export type BesluitTypePluginOptions = {
2
2
  endpoint: string;
3
+ classificatieUri: string;
3
4
  };
@@ -84,7 +84,7 @@ const ENUM_ROYAL = `genummerd${NNWS}?${ROYAL}`;
84
84
  /**
85
85
  * match for "decision of the flemish government"
86
86
  */
87
- const DECISION = 'besluit';
87
+ const DECISION = 'gemeentebesluit';
88
88
 
89
89
  /**
90
90
  * The type of citation that we need to search for
@@ -1,5 +1,5 @@
1
1
  import {
2
- isBesluitType,
2
+ isGemeenteBesluitType,
3
3
  LEGISLATION_TYPE_CONCEPTS,
4
4
  } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/types';
5
5
  import { fetchVlaamseCodexLegalDocuments } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/vlaamse-codex';
@@ -47,7 +47,7 @@ export class LegalDocument {
47
47
  }
48
48
 
49
49
  export const isBesluitLegalDocument = (legalDocument: LegalDocument) =>
50
- isBesluitType(legalDocument.legislationType?.value ?? '');
50
+ isGemeenteBesluitType(legalDocument.legislationType?.value ?? '');
51
51
 
52
52
  export const fetchLegalDocumentsCache = new Map<
53
53
  string,
@@ -109,7 +109,7 @@ export async function fetchLegalDocuments({
109
109
  return results;
110
110
  } else {
111
111
  const shouldQueryPublicDecisions =
112
- isBesluitType(filter.type) && config.decisionsEndpoint;
112
+ isGemeenteBesluitType(filter.type) && config.decisionsEndpoint;
113
113
 
114
114
  const fetchConfig = {
115
115
  words,
@@ -95,15 +95,16 @@ const getCountQuery = ({
95
95
  ?session besluit:behandelt ?agendaPoint.
96
96
  ?agendaPointTreatment dct:subject ?agendaPoint;
97
97
  prov:generated ?decision.
98
- ?decision eli:title ?decisionTitle.
98
+ ?decision eli:title ?decisionTitleViaAgenda.
99
99
  }
100
100
  OPTIONAL {
101
101
  ?session ext:uittreksel ?treatment.
102
102
  ?treatment mu:uuid ?treatmentUuid.
103
103
  ?treatment ext:uittrekselBvap ?agendaPointTreatment.
104
104
  ?agendaPointTreatment prov:generated ?decision.
105
- ?decision eli:title ?decisionTitle.
105
+ ?decision eli:title ?decisionTitleViaTreatment.
106
106
  }
107
+ BIND(COALESCE(?decisionTitleViaAgenda, ?decisionTitleViaTreatment) as ?decisionTitle)
107
108
  ${filterString}
108
109
  }
109
110
  `;
@@ -145,15 +146,16 @@ const getQuery = ({
145
146
  ?session besluit:behandelt ?agendaPoint.
146
147
  ?agendaPointTreatment dct:subject ?agendaPoint;
147
148
  prov:generated ?decision.
148
- ?decision eli:title ?decisionTitle.
149
+ ?decision eli:title ?decisionTitleViaAgenda.
149
150
  }
150
151
  OPTIONAL {
151
152
  ?session ext:uittreksel ?treatment.
152
153
  ?treatment mu:uuid ?treatmentUuid.
153
154
  ?treatment ext:uittrekselBvap ?agendaPointTreatment.
154
155
  ?agendaPointTreatment prov:generated ?decision.
155
- ?decision eli:title ?decisionTitle.
156
+ ?decision eli:title ?decisionTitleViaTreatment.
156
157
  }
158
+ BIND(COALESCE(?decisionTitleViaAgenda, ?decisionTitleViaTreatment) as ?decisionTitle)
157
159
  ${filterString}
158
160
  }
159
161
  ORDER BY DESC (?documentDate) (?decisionTitle) LIMIT ${pageSize} OFFSET ${
@@ -26,20 +26,24 @@ export const LEGISLATION_TYPES = {
26
26
  'genummerd koninklijk besluit':
27
27
  'https://data.vlaanderen.be/id/concept/AardWetgeving/GenummerdKoninklijkBesluit',
28
28
  protocol: 'https://data.vlaanderen.be/id/concept/AardWetgeving/Protocol',
29
- besluit: 'https://data.vlaanderen.be/doc/concept/AardWetgeving/Besluit',
29
+ gemeentebesluit:
30
+ 'https://data.vlaanderen.be/doc/concept/AardWetgeving/Besluit',
30
31
  };
31
32
 
32
33
  export const legislationKeysCapitalized = Object.keys(LEGISLATION_TYPES).map(
33
34
  capitalize,
34
35
  ) as [Capitalize<keyof typeof LEGISLATION_TYPES>];
35
36
 
37
+ export const legislationKeysCapitalizedWithoutGemeentebesluit =
38
+ legislationKeysCapitalized.filter((key) => key !== 'Gemeentebesluit');
39
+
36
40
  export const isLegislationType = (
37
41
  type: string,
38
42
  ): type is keyof typeof LEGISLATION_TYPES =>
39
43
  Object.keys(LEGISLATION_TYPES).includes(type);
40
44
 
41
- export const isBesluitType = (type: string) =>
42
- type === LEGISLATION_TYPES['besluit'];
45
+ export const isGemeenteBesluitType = (type: string) =>
46
+ type === LEGISLATION_TYPES['gemeentebesluit'];
43
47
 
44
48
  export const LEGISLATION_TYPE_CONCEPTS = Object.entries(LEGISLATION_TYPES).map(
45
49
  ([label, value]) => ({
@@ -11,6 +11,8 @@ import {
11
11
  besluitArticleStructure,
12
12
  } from './utils/nodes';
13
13
 
14
+ export { default as instantiateUuids } from './utils/instantiate-uuids';
15
+
14
16
  export const besluitNodes = {
15
17
  besluit,
16
18
  besluit_title,
@@ -17,7 +17,8 @@ import { v4 as uuidv4 } from 'uuid';
17
17
  */
18
18
 
19
19
  export default function instantiateUuids(templateString: string) {
20
- const generateBoundUuid = memoize(uuidv4) as (...args: unknown[]) => string;
20
+ // We're not interested in the args in this case, we just use them to memoize
21
+ const generateBoundUuid = memoize((..._args: unknown[]) => uuidv4());
21
22
 
22
23
  const determineFunction = (string: string) => {
23
24
  switch (string) {
@@ -31,18 +32,9 @@ export default function instantiateUuids(templateString: string) {
31
32
  };
32
33
  return templateString.replace(
33
34
  /\$\{(generateUuid|generateBoundUuid)\(([^()]*)\)\}/g,
34
- (string) => {
35
- const match = /\$\{(generateUuid|generateBoundUuid)\(([^()]*)\)\}/.exec(
36
- string,
37
- );
38
- if (match) {
39
- const functionName = match[1];
40
- const functionArgs = match[2];
41
- const func = determineFunction(functionName);
42
- return functionArgs ? func(functionArgs) : func();
43
- } else {
44
- return string;
45
- }
35
+ (_match, functionName, functionArgs) => {
36
+ const func = determineFunction(functionName);
37
+ return functionArgs ? func(functionArgs) : func();
46
38
  },
47
39
  );
48
40
  }
@@ -22,7 +22,7 @@ type StreetSearchResult = {
22
22
  gemeente: {
23
23
  gemeentenaam: { geografischeNaam: { spelling: string } };
24
24
  };
25
- straatnaam: {
25
+ straatnaam?: {
26
26
  straatnaam: {
27
27
  geografischeNaam: { spelling: string };
28
28
  };
@@ -75,14 +75,20 @@ type AddressDetailResult = {
75
75
  export class AddressError extends Error {
76
76
  translation: string;
77
77
  status?: number;
78
+ alternativeAddress?: Address;
78
79
  constructor({
79
80
  message,
80
81
  translation,
81
82
  status,
82
- }: Pick<AddressError, 'message' | 'translation' | 'status'>) {
83
+ alternativeAddress,
84
+ }: Pick<
85
+ AddressError,
86
+ 'message' | 'translation' | 'status' | 'alternativeAddress'
87
+ >) {
83
88
  super(message);
84
89
  this.translation = translation;
85
90
  this.status = status;
91
+ this.alternativeAddress = alternativeAddress;
86
92
  }
87
93
  }
88
94
 
@@ -129,9 +135,11 @@ export async function fetchStreets(term: string, municipality: string) {
129
135
  });
130
136
  if (result.ok) {
131
137
  const jsonResult = (await result.json()) as StreetSearchResult;
132
- const streetnames = jsonResult.adresMatches.map((entry) => {
133
- return entry.straatnaam.straatnaam.geografischeNaam.spelling;
134
- });
138
+
139
+ const streetnames = jsonResult.adresMatches
140
+ .map((entry) => entry.straatnaam?.straatnaam.geografischeNaam.spelling)
141
+ .filter(Boolean);
142
+
135
143
  return streetnames;
136
144
  } else {
137
145
  throw new AddressError({
@@ -217,9 +225,15 @@ export async function resolveAddress(info: AddressInfo) {
217
225
  });
218
226
  }
219
227
  } else {
228
+ const alternativeAddress = await resolveStreet({
229
+ street: info.street,
230
+ municipality: info.municipality,
231
+ });
232
+
220
233
  throw new AddressError({
221
234
  translation: 'editor-plugins.address.edit.errors.address-not-found',
222
235
  message: `Could not find address in address register`,
236
+ alternativeAddress,
223
237
  });
224
238
  }
225
239
  }
@@ -65,6 +65,7 @@ const parseDOM = [
65
65
  onlyDate,
66
66
  format: node.dataset.format,
67
67
  custom: node.dataset.custom === 'true',
68
+ customAllowed: node.dataset.customAllowed !== 'false',
68
69
  };
69
70
  }
70
71
  return false;
@@ -96,6 +97,7 @@ const parseDOM = [
96
97
  value: value,
97
98
  format: format,
98
99
  custom: dateNode?.dataset.custom === 'true',
100
+ customAllowed: dateNode?.dataset.customAllowed !== 'false',
99
101
  label,
100
102
  };
101
103
  }
@@ -108,8 +110,15 @@ const parseDOM = [
108
110
  const serialize = (node: PNode, state: EditorState) => {
109
111
  const t = getTranslationFunction(state);
110
112
 
111
- const { value, onlyDate, format, mappingResource, custom, label } =
112
- node.attrs;
113
+ const {
114
+ value,
115
+ onlyDate,
116
+ format,
117
+ mappingResource,
118
+ custom,
119
+ customAllowed,
120
+ label,
121
+ } = node.attrs;
113
122
  const datatype = onlyDate ? XSD('date') : XSD('dateTime');
114
123
  let humanReadableDate: string;
115
124
  if (value) {
@@ -130,6 +139,7 @@ const serialize = (node: PNode, state: EditorState) => {
130
139
  datatype: datatype.prefixed,
131
140
  'data-format': format as string,
132
141
  'data-custom': custom ? 'true' : 'false',
142
+ 'data-custom-allowed': customAllowed ? 'true' : 'false',
133
143
  ...(!!value && { content: value as string }),
134
144
  };
135
145
  return mappingSpan(
@@ -164,6 +174,9 @@ const emberNodeConfig = (options: DateOptions): EmberNodeConfig => ({
164
174
  custom: {
165
175
  default: false,
166
176
  },
177
+ customAllowed: {
178
+ default: options.allowCustomFormat,
179
+ },
167
180
  label: { default: null },
168
181
  },
169
182
  // TODO: is this property still required?