@lblod/ember-rdfa-editor-lblod-plugins 11.0.0 → 11.2.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 (47) hide show
  1. package/CHANGELOG.md +23 -1
  2. package/README.md +5 -1
  3. package/addon/components/generic-rdfa-variable/insert-menu.hbs +1 -0
  4. package/addon/components/generic-rdfa-variable/insert-menu.ts +12 -10
  5. package/addon/components/loading-alert.hbs +28 -0
  6. package/addon/components/loading-alert.ts +3 -0
  7. package/addon/components/template-comments-plugin/edit-card.ts +38 -15
  8. package/addon/components/variable-plugin/address/edit.hbs +79 -29
  9. package/addon/components/variable-plugin/address/edit.ts +176 -39
  10. package/addon/components/variable-plugin/address/nodeview.ts +1 -1
  11. package/addon/components/variable-plugin/codelist/edit.ts +6 -1
  12. package/addon/components/variable-plugin/codelist/insert.hbs +16 -6
  13. package/addon/components/variable-plugin/codelist/insert.ts +40 -9
  14. package/addon/components/variable-plugin/number/insert.hbs +2 -0
  15. package/addon/components/variable-plugin/number/insert.ts +30 -8
  16. package/addon/plugins/article-structure-plugin/commands/wrap-structure-content.ts +86 -11
  17. package/addon/plugins/article-structure-plugin/structures/article.ts +1 -0
  18. package/addon/plugins/article-structure-plugin/structures/structure-header.ts +2 -1
  19. package/addon/plugins/article-structure-plugin/structures/title.ts +2 -0
  20. package/addon/plugins/article-structure-plugin/utils/structure.ts +4 -0
  21. package/addon/plugins/document-title-plugin/nodes/document-title.ts +1 -0
  22. package/addon/plugins/generic-rdfa-variable/commands/index.ts +1 -0
  23. package/addon/plugins/generic-rdfa-variable/commands/insert-generic-rdfa.ts +25 -0
  24. package/addon/plugins/snippet-plugin/utils/fetch-data.ts +3 -1
  25. package/addon/plugins/variable-plugin/utils/address-helpers.ts +220 -69
  26. package/addon/plugins/variable-plugin/utils/attribute-parsers.ts +4 -0
  27. package/addon/plugins/variable-plugin/variables/address.ts +118 -147
  28. package/addon/plugins/variable-plugin/variables/codelist.ts +15 -2
  29. package/addon/utils/constants.ts +4 -0
  30. package/addon/utils/find-insertion-contentmatch.ts +61 -0
  31. package/app/components/loading-alert.js +1 -0
  32. package/components/generic-rdfa-variable/insert-menu.d.ts +1 -0
  33. package/components/loading-alert.d.ts +3 -0
  34. package/components/variable-plugin/address/edit.d.ts +31 -8
  35. package/components/variable-plugin/codelist/insert.d.ts +18 -4
  36. package/components/variable-plugin/number/insert.d.ts +18 -2
  37. package/package.json +5 -4
  38. package/plugins/article-structure-plugin/utils/structure.d.ts +2 -0
  39. package/plugins/generic-rdfa-variable/commands/index.d.ts +1 -0
  40. package/plugins/generic-rdfa-variable/commands/insert-generic-rdfa.d.ts +2 -0
  41. package/plugins/variable-plugin/utils/address-helpers.d.ts +30 -3
  42. package/plugins/variable-plugin/utils/attribute-parsers.d.ts +1 -0
  43. package/plugins/variable-plugin/variables/address.d.ts +6 -14
  44. package/translations/en-US.yaml +28 -6
  45. package/translations/nl-BE.yaml +27 -6
  46. package/utils/constants.d.ts +1 -0
  47. package/utils/find-insertion-contentmatch.d.ts +23 -0
package/CHANGELOG.md CHANGED
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [11.2.0] - 2023-09-04
11
+ ### Added
12
+ - ember-modifier is now explicitely a peerDependency
13
+ - GN4470: ability to specifly single/multi-select per codelist instance
14
+ ## [11.1.0] - 2023-08-29
15
+
16
+ ### Fixed
17
+ - GN-4370: Do not allow header nodes to be split by table
18
+ - Grey out Generic RDFA button in embedded view
19
+ - GN-4425: Smarter content wrapping for structure nodes
20
+
21
+ ### Changed
22
+ - GN-4442: template comments can move up and down over the *whole* document
23
+ - GN-4322: Add ORDER to snippet list query
24
+ - Bumps `@lblod/ember-rdfa-editor` from 5.1.0 to 5.2.0
25
+
10
26
  ## [11.0.0] - 2023-08-22
11
27
 
12
28
  ### Added
@@ -15,8 +31,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
15
31
  - Introduce internationalization in the table of contents node based on the document language.
16
32
  - The whole table of contents node (include its entries) is now exported in its `serialize` method without the need of an `entries` attribute.
17
33
  - GN-4461: update readme to specify needed imports for template comment
34
+ - Check validity on number minimum/maximum inputs
18
35
 
19
36
  ### Changed
37
+ - GN-4263: update address variable edit UI/UX according to updated design
38
+ - Allow the address municipality-edit field to be prefilled
20
39
  - Use one-way-binding in variable label input
21
40
  - Use one-way-binding in number variable inputs
22
41
  - Manage snippet list connection with template
@@ -29,6 +48,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
29
48
  - Removal of the `entries` attribute from the table-of-contents prosemirror node. The node can now generate it's own outline in its `serialize` method.
30
49
  ### Dependencies
31
50
  - Bumps `@codemirror/view` from 6.12.0 to 6.16.0
51
+ - Bumps `@lblod/ember-rdfa-editor` from 4.2.0 to 5.1.0
32
52
 
33
53
  ## [10.0.0] - 2023-08-08
34
54
  ### Changed
@@ -675,7 +695,7 @@ add onclick handler to pencil icon in variable plugin
675
695
 
676
696
  # Changelog
677
697
 
678
- [unreleased]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v11.0.0...HEAD
698
+ [unreleased]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v11.2.0...HEAD
679
699
  [8.0.0]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v8.0.0...v8.0.1
680
700
  [8.0.0]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v7.1.0...v8.0.0
681
701
  [7.1.0]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v7.0.0...v7.1.0
@@ -691,6 +711,8 @@ add onclick handler to pencil icon in variable plugin
691
711
  [3.0.0]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v2.1.2...v3.0.0
692
712
  [2.1.2]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v2.1.1...v2.1.2
693
713
  [2.1.1]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v2.1.0...v2.1.1
714
+ [11.2.0]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v11.1.0...v11.2.0
715
+ [11.1.0]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v11.0.0...v11.1.0
694
716
  [11.0.0]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v10.0.0...v11.0.0
695
717
  [10.0.0]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v9.1.1...v10.0.0
696
718
  [9.1.1]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v9.1.0...v9.1.1
package/README.md CHANGED
@@ -665,9 +665,13 @@ get codelistEditOptions() {
665
665
  This addon provides a seperate edit component which allows users to search for an address and update the select address variable. Additionally, they can also choose whether to include the housenumber of an address.
666
666
  You can add this edit-component to a template as follows:
667
667
  ```hbs
668
- <VariablePlugin::Address::Edit @controller={{this.controller}}/>
668
+ <VariablePlugin::Address::Edit @controller={{this.controller}} @defaultMuncipality='Antwerpen'/>
669
669
  ```
670
670
 
671
+ The edit card can be configured with two arguments:
672
+ - An instance of a `SayController` (required)
673
+ - A `defaultMuncipality` which should be used as the default value of the `muncipality` field in the edit-card (optional)
674
+
671
675
  ## validation-plugin
672
676
 
673
677
  see [the plugin docs](addon/plugins/validation/README.md)
@@ -2,6 +2,7 @@
2
2
  @title={{t 'generic-rdfa-variable.menu.insert'}}
3
3
  @icon='html-plus'
4
4
  {{on 'click' this.showModal}}
5
+ @disabled={{not this.canInsert}}
5
6
  />
6
7
  <AuModal
7
8
  @modalOpen={{this.modalOpen}}
@@ -3,13 +3,13 @@ import { action } from '@ember/object';
3
3
  import { SayController } from '@lblod/ember-rdfa-editor';
4
4
  import { tracked } from 'tracked-built-ins';
5
5
 
6
- import { DOMParser as ProseParser } from 'prosemirror-model';
7
-
8
6
  import { basicSetup, EditorView } from 'codemirror';
9
7
  import { EditorState } from '@codemirror/state';
10
8
  import { html } from '@codemirror/lang-html';
11
9
  import { tooltips } from '@codemirror/view';
12
10
 
11
+ import { insertGenericRdfa } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/generic-rdfa-variable/commands/insert-generic-rdfa';
12
+
13
13
  type Args = {
14
14
  controller: SayController;
15
15
  };
@@ -26,6 +26,14 @@ export default class GenericRdfaVariableInsertMenu extends Component<Args> {
26
26
  return this.args.controller.schema;
27
27
  }
28
28
 
29
+ get canInsert() {
30
+ if (this.controller.inEmbeddedView) {
31
+ return false;
32
+ }
33
+
34
+ return this.controller.checkCommand(insertGenericRdfa(''));
35
+ }
36
+
29
37
  @action
30
38
  showModal() {
31
39
  this.modalOpen = true;
@@ -82,14 +90,8 @@ export default class GenericRdfaVariableInsertMenu extends Component<Args> {
82
90
  return;
83
91
  }
84
92
 
85
- const domParser = new DOMParser();
86
-
87
- this.controller.withTransaction((tr) => {
88
- return tr.replaceSelectionWith(
89
- ProseParser.fromSchema(this.schema).parse(
90
- domParser.parseFromString(editorContent, 'text/html'),
91
- ),
92
- );
93
+ this.args.controller.doCommand(insertGenericRdfa(editorContent), {
94
+ view: this.controller.mainEditorView,
93
95
  });
94
96
 
95
97
  this.closeModal();
@@ -0,0 +1,28 @@
1
+ {{#if this.isVisible}}
2
+ <div
3
+ class="au-c-alert {{this.skin}} {{this.size}}"
4
+ role="alert"
5
+ data-test-alert
6
+ ...attributes
7
+ >
8
+ <AuLoader/>
9
+ <div class="au-c-alert__content">
10
+ {{#if @title}}
11
+ <p class="au-c-alert__title" data-test-alert-title>{{@title}}</p>
12
+ {{/if}}
13
+ <div class="au-c-alert__message" data-test-alert-message>{{yield}}</div>
14
+ </div>
15
+ {{#if @closable}}
16
+ <button
17
+ class="au-c-alert__close"
18
+ type="button"
19
+ data-test-alert-close
20
+ {{on "click" this.closeAlert}}
21
+ >
22
+ <AuIcon @icon="cross" @size="large" />
23
+ {{!-- template-lint-disable no-bare-strings --}}
24
+ <span class="au-u-hidden-visually">Sluit alert</span>
25
+ </button>
26
+ {{/if}}
27
+ </div>
28
+ {{/if}}
@@ -0,0 +1,3 @@
1
+ //@ts-expect-error ember-appuniversum uses vanilla javascript
2
+ import AuAlertComponent from '@appuniversum/ember-appuniversum/components/au-alert';
3
+ export default class LoadingAlertComponent extends AuAlertComponent {}
@@ -2,7 +2,14 @@ import { action } from '@ember/object';
2
2
  import Component from '@glimmer/component';
3
3
  import { SayController } from '@lblod/ember-rdfa-editor/addon';
4
4
  import { TextSelection } from '@lblod/ember-rdfa-editor';
5
- import { findParentNodeOfType } from '@curvenote/prosemirror-utils';
5
+ import {
6
+ findParentNodeOfType,
7
+ hasParentNodeOfType,
8
+ } from '@curvenote/prosemirror-utils';
9
+ import {
10
+ findContentMatchPosLeft,
11
+ findContentMatchPosRight,
12
+ } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/find-insertion-contentmatch';
6
13
 
7
14
  type Args = {
8
15
  controller: SayController;
@@ -43,17 +50,22 @@ export default class TemplateCommentsPluginEditCardComponent extends Component<A
43
50
  const comment = this.templateComment;
44
51
  if (!comment) return;
45
52
  const { node: node, pos: pos } = comment;
46
- const resolvedPos = this.controller.mainEditorState.doc.resolve(pos);
47
- const nodeBefore = resolvedPos.nodeBefore;
48
- if (!nodeBefore) return;
49
- const amountToMove = -nodeBefore.nodeSize;
53
+ const insertPos = findContentMatchPosLeft(
54
+ this.controller.mainEditorState.doc,
55
+ pos,
56
+ this.commentType,
57
+ ($pos) =>
58
+ !hasParentNodeOfType(this.commentType)(new TextSelection($pos, $pos)),
59
+ );
60
+ if (insertPos === undefined) return;
61
+
62
+ const amountToMove = -(pos - insertPos);
50
63
  const initialCursorPos =
51
64
  this.controller.mainEditorState.selection.$head.pos;
52
- const newPos = pos + amountToMove;
53
65
  const newCursorPos = initialCursorPos + amountToMove;
54
66
  this.controller.withTransaction((tr) => {
55
67
  tr.delete(pos, pos + node.nodeSize);
56
- tr.insert(newPos, node);
68
+ tr.insert(insertPos, node);
57
69
  const mappedSelection = TextSelection.create(
58
70
  tr.doc,
59
71
  newCursorPos,
@@ -72,21 +84,32 @@ export default class TemplateCommentsPluginEditCardComponent extends Component<A
72
84
  if (!comment) return;
73
85
 
74
86
  const { node: commentNode, pos: startPos } = comment;
75
- const posAfterComment = startPos + commentNode.nodeSize;
76
- const resolvedPos =
77
- this.controller.mainEditorState.doc.resolve(posAfterComment);
78
- const nodeAfterComment = resolvedPos.nodeAfter;
79
- if (!nodeAfterComment) return;
87
+ const searchStart = startPos + commentNode.nodeSize;
88
+ const $afterPos = this.controller.mainEditorState.doc.resolve(searchStart);
89
+
90
+ // lists in template comments can have any content, including template comments...
91
+ // This means we have to avoid moving inside a template comment, as the contentMatch would be valid
92
+ const posToInsert = findContentMatchPosRight(
93
+ this.controller.mainEditorState.doc,
94
+ $afterPos,
95
+ commentNode.type,
96
+ (pos) => {
97
+ const $pos = this.controller.mainEditorState.doc.resolve(pos);
98
+ return !hasParentNodeOfType(this.commentType)(
99
+ new TextSelection($pos, $pos),
100
+ );
101
+ },
102
+ );
80
103
 
81
- const amountToMove = commentNode.nodeSize + nodeAfterComment.nodeSize;
104
+ if (posToInsert === undefined) return;
105
+ const amountToMove = posToInsert - startPos;
82
106
 
83
- const newPos = startPos + amountToMove;
84
107
  const initialCursorPos =
85
108
  this.controller.mainEditorState.selection.$head.pos;
86
109
  const newCursorPos = initialCursorPos + amountToMove;
87
110
 
88
111
  this.controller.withTransaction((tr) => {
89
- tr.insert(newPos, commentNode);
112
+ tr.insert(posToInsert, commentNode);
90
113
  // do delete after setting the selection,
91
114
  //so the selection position can be easily constructed
92
115
  const mappedSelection = TextSelection.create(
@@ -1,35 +1,85 @@
1
1
  {{#if this.showCard}}
2
2
  <AuCard @flex={{true}} @divided={{true}} @shadow={{true}} @size="small" as |c|>
3
3
  <c.content>
4
- <AuLabel for='address-select'>
5
- {{t "editor-plugins.address.edit.title"}}
6
- </AuLabel>
7
- <PowerSelect
8
- id="adress-select"
9
- @loadingMessage={{t "editor-plugins.utils.loading"}}
10
- @searchMessage={{t "editor-plugins.address.edit.search-message"}}
11
- @noMatchesMessage={{t "editor-plugins.address.edit.no-results"}}
12
- @placeholder={{if this.includeHouseNumber
13
- (t "editor-plugins.address.edit.placeholder-with-number")
14
- (t "editor-plugins.address.edit.placeholder-without-number")}}
15
- @renderInPlace={{true}}
16
- @searchEnabled={{true}}
17
- @search={{perform this.searchAddress}}
18
- @selected={{this.selectedAddress}}
19
- @onChange={{this.selectAddress}} as |address|>
20
- {{address.formatted}}
21
- </PowerSelect>
22
- <AuToggleSwitch
23
- @checked={{this.includeHouseNumber}}
24
- @onChange={{this.toggleIncludeHouseNumber}}
25
- @label={{t "editor-plugins.address.edit.include-housenumber"}}
26
- />
27
- <AuButton
28
- {{on 'click' (perform this.updateAddressVariable)}}
29
- @disabled={{not this.canUpdate}}
30
- @loading={{this.updateAddressVariable.isRunning}}>
31
- {{t "editor-plugins.utils.insert"}}
32
- </AuButton>
4
+ <form class="au-c-form">
5
+ <AuLabel for='municipality-select'>
6
+ {{t "editor-plugins.address.edit.municipality.label"}}*
7
+ </AuLabel>
8
+ <PowerSelect
9
+ id="municipality-select"
10
+ @loadingMessage={{t "editor-plugins.utils.loading"}}
11
+ @searchMessage={{t "editor-plugins.address.edit.municipality.search-message"}}
12
+ @noMatchesMessage={{t "editor-plugins.address.edit.municipality.no-results"}}
13
+ @placeholder={{t "editor-plugins.address.edit.municipality.placeholder"}}
14
+ @renderInPlace={{true}}
15
+ @searchEnabled={{true}}
16
+ @search={{perform this.searchMunicipality}}
17
+ @selected={{this.newMunicipality}}
18
+ @onChange={{this.selectMunicipality}} as |municipality|>
19
+ {{municipality}}
20
+ </PowerSelect>
21
+ <AuLabel for='streetname-select'>
22
+ {{t "editor-plugins.address.edit.street.label"}}*
23
+ </AuLabel>
24
+ <PowerSelect
25
+ id="streetname-select"
26
+ @loadingMessage={{t "editor-plugins.utils.loading"}}
27
+ @searchMessage={{t "editor-plugins.address.edit.street.search-message"}}
28
+ @noMatchesMessage={{t "editor-plugins.address.edit.street.no-results"}}
29
+ @placeholder={{t "editor-plugins.address.edit.street.placeholder"}}
30
+ @renderInPlace={{true}}
31
+ @searchEnabled={{true}}
32
+ @search={{perform this.searchStreet}}
33
+ @selected={{this.newStreetName}}
34
+ @disabled={{not this.canUpdateStreet}}
35
+ @onChange={{this.selectStreet}} as |street|>
36
+ {{street}}
37
+ </PowerSelect>
38
+ <div class="au-o-grid au-o-grid--tiny">
39
+ <div class="au-o-grid__item au-u-1-2@medium">
40
+ <AuLabel for="housenumber-select">
41
+ {{t "editor-plugins.address.edit.housenumber.label"}}
42
+ </AuLabel>
43
+ <AuNativeInput
44
+ id="housenumber-select"
45
+ placeholder={{t "editor-plugins.address.edit.housenumber.placeholder"}}
46
+ @width="block"
47
+ value={{this.newHousenumber}}
48
+ @disabled={{not this.canUpdateHousenumber}}
49
+ {{on 'input' this.updateHousenumber}}
50
+ />
51
+ </div>
52
+ <div class="au-o-grid__item au-u-1-2@medium">
53
+ <AuLabel for="busnumber-select">
54
+ {{t "editor-plugins.address.edit.busnumber.label"}}
55
+ </AuLabel>
56
+ <AuNativeInput
57
+ id="busnumber-select"
58
+ placeholder={{t "editor-plugins.address.edit.busnumber.placeholder"}}
59
+ @width="block"
60
+ value={{this.newBusnumber}}
61
+ @disabled={{not this.canUpdateBusnumber}}
62
+ {{on 'input' this.updateBusnumber}}
63
+ />
64
+ </div>
65
+ </div>
66
+
67
+ {{#if this.newAddress.isRunning}}
68
+ <LoadingAlert @title={{t "editor-plugins.address.edit.loading"}} @size="small" @skin="info"/>
69
+ {{/if}}
70
+ {{#if this.message}}
71
+ <AuAlert @skin={{this.message.skin}} @icon={{this.message.icon}} @title={{this.message.title}}>
72
+ {{this.message.body}}
73
+ </AuAlert>
74
+ {{/if}}
75
+ <AuButton
76
+ {{on 'click' this.updateAddressVariable}}
77
+ @disabled={{not this.canUpdateAddressVariable}}>
78
+ {{t "editor-plugins.utils.insert"}}
79
+ </AuButton>
80
+
81
+ </form>
82
+
33
83
  </c.content>
34
84
  </AuCard>
35
85
  {{/if}}
@@ -3,43 +3,101 @@ import Component from '@glimmer/component';
3
3
  import { NodeSelection, SayController } from '@lblod/ember-rdfa-editor';
4
4
  import { Address } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/variable-plugin/variables';
5
5
  import {
6
- fetchAddresses,
6
+ AddressError,
7
+ fetchMunicipalities,
8
+ fetchStreets,
7
9
  resolveAddress,
10
+ resolveStreet,
8
11
  } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/variable-plugin/utils/address-helpers';
9
- import { dropTask, restartableTask, timeout } from 'ember-concurrency';
12
+ import { restartableTask, timeout } from 'ember-concurrency';
10
13
  import { localCopy, trackedReset } from 'tracked-toolbox';
14
+ import { trackedTask } from 'ember-resources/util/ember-concurrency';
15
+ import { service } from '@ember/service';
16
+ import IntlService from 'ember-intl/services/intl';
11
17
 
12
18
  type Args = {
13
19
  controller: SayController;
20
+ defaultMunicipality?: string;
14
21
  };
15
22
 
16
23
  export default class AddressEditComponent extends Component<Args> {
17
- @localCopy('currentAddress')
18
- selectedAddress?: Address;
24
+ @service declare intl: IntlService;
19
25
 
20
- @trackedReset<AddressEditComponent, boolean>({
26
+ @trackedReset<AddressEditComponent, string | undefined>({
21
27
  memo: 'currentAddress',
22
- update(component, _key, last) {
23
- if (component.currentAddress) {
24
- return component.currentAddress.hasHouseNumber;
25
- } else {
26
- return last;
27
- }
28
+ update(component) {
29
+ const { currentMunicipality } = component;
30
+ return currentMunicipality
31
+ ? currentMunicipality
32
+ : component.args.defaultMunicipality;
28
33
  },
29
34
  })
30
- includeHouseNumber = true;
35
+ newMunicipality?: string;
31
36
 
32
- @action
33
- toggleIncludeHouseNumber() {
34
- this.includeHouseNumber = !this.includeHouseNumber;
35
- this.selectedAddress = undefined;
37
+ @localCopy('currentStreetName') newStreetName?: string;
38
+
39
+ @localCopy('currentHousenumber') newHousenumber?: string;
40
+
41
+ @localCopy('currentBusnumber') newBusnumber?: string;
42
+
43
+ get message() {
44
+ const value = this.newAddress.value as Address | undefined;
45
+ if (
46
+ this.newAddress.isSuccessful &&
47
+ value &&
48
+ !value.sameAs(this.currentAddress)
49
+ ) {
50
+ return {
51
+ skin: 'success',
52
+ icon: 'check',
53
+ title: this.intl.t('editor-plugins.address.edit.success.address-found'),
54
+ body: value.formatted,
55
+ };
56
+ } else if (
57
+ this.newAddress.isError &&
58
+ this.newAddress.error instanceof AddressError
59
+ ) {
60
+ const { error } = this.newAddress;
61
+ return {
62
+ skin: 'warning',
63
+ icon: 'alert-triangle',
64
+ title: this.intl.t(error.translation, { status: error.status }),
65
+ body: this.intl.t('editor-plugins.address.edit.errors.contact', {
66
+ htmlSafe: true,
67
+ email: 'gelinktnotuleren@vlaanderen.be',
68
+ }),
69
+ };
70
+ } else {
71
+ return;
72
+ }
36
73
  }
37
74
 
38
75
  get currentAddress() {
39
- return this.selectedAddressVariable?.node.attrs.address as
40
- | Address
41
- | undefined
42
- | null;
76
+ return this.selectedAddressVariable?.node.attrs.value as Address | null;
77
+ }
78
+
79
+ get currentMunicipality() {
80
+ return this.currentAddress?.municipality;
81
+ }
82
+
83
+ get currentStreetName() {
84
+ return this.currentAddress?.street;
85
+ }
86
+
87
+ get currentHousenumber() {
88
+ if (this.currentAddress instanceof Address) {
89
+ return this.currentAddress.housenumber;
90
+ } else {
91
+ return;
92
+ }
93
+ }
94
+
95
+ get currentBusnumber() {
96
+ if (this.currentAddress instanceof Address) {
97
+ return this.currentAddress.busnumber;
98
+ } else {
99
+ return;
100
+ }
43
101
  }
44
102
 
45
103
  get selectedAddressVariable() {
@@ -53,44 +111,123 @@ export default class AddressEditComponent extends Component<Args> {
53
111
  return;
54
112
  }
55
113
 
114
+ get canUpdateStreet() {
115
+ return !!this.newMunicipality;
116
+ }
117
+
118
+ get canUpdateHousenumber() {
119
+ return this.newMunicipality && this.newStreetName;
120
+ }
121
+
122
+ get canUpdateBusnumber() {
123
+ return this.newMunicipality && this.newStreetName && this.newHousenumber;
124
+ }
125
+
56
126
  get showCard() {
57
127
  return !!this.selectedAddressVariable;
58
128
  }
59
129
 
60
- get canUpdate() {
130
+ get canUpdateAddressVariable() {
61
131
  return (
62
- !!this.selectedAddress &&
63
- !this.selectedAddress.sameAs(
64
- this.selectedAddressVariable?.node.attrs.address as Address | undefined,
65
- )
132
+ this.newAddress.isSuccessful &&
133
+ this.newAddress.value &&
134
+ !this.currentAddress?.sameAs(this.newAddress.value as Address)
66
135
  );
67
136
  }
68
137
 
69
- updateAddressVariable = dropTask(async () => {
70
- if (this.selectedAddressVariable && this.selectedAddress) {
71
- const { pos } = this.selectedAddressVariable;
138
+ resolveAddressTask = restartableTask(async () => {
139
+ const { newStreetName, newMunicipality, newHousenumber, newBusnumber } =
140
+ this;
141
+ if (newMunicipality && newStreetName) {
142
+ if (
143
+ this.currentAddress?.sameAs({
144
+ street: newStreetName,
145
+ municipality: newMunicipality,
146
+ busnumber: newBusnumber,
147
+ housenumber: newHousenumber,
148
+ })
149
+ ) {
150
+ return this.currentAddress;
151
+ } else {
152
+ await timeout(200);
153
+ if (newHousenumber) {
154
+ return resolveAddress({
155
+ street: newStreetName,
156
+ municipality: newMunicipality,
157
+ housenumber: newHousenumber,
158
+ busnumber: newBusnumber,
159
+ });
160
+ } else {
161
+ return resolveStreet({
162
+ street: newStreetName,
163
+ municipality: newMunicipality,
164
+ });
165
+ }
166
+ }
167
+ } else {
168
+ return;
169
+ }
170
+ });
171
+
172
+ newAddress = trackedTask(this, this.resolveAddressTask, () => [
173
+ this.newMunicipality,
174
+ this.newStreetName,
175
+ this.newHousenumber,
176
+ this.newBusnumber,
177
+ ]);
72
178
 
73
- const address =
74
- this.includeHouseNumber && this.selectedAddress.hasHouseNumber
75
- ? await resolveAddress(this.selectedAddress)
76
- : this.selectedAddress;
179
+ @action
180
+ updateAddressVariable() {
181
+ if (this.selectedAddressVariable && this.newAddress.isSuccessful) {
182
+ const { pos } = this.selectedAddressVariable;
77
183
  this.controller.withTransaction((tr) => {
78
- return tr.setNodeAttribute(pos, 'address', address);
184
+ return tr.setNodeAttribute(pos, 'value', this.newAddress.value);
79
185
  });
80
186
  }
81
- });
187
+ }
82
188
 
83
189
  @action
84
- selectAddress(address: Address) {
85
- this.selectedAddress = address;
190
+ selectMunicipality(municipality: string) {
191
+ this.newMunicipality = municipality;
192
+ this.newStreetName = '';
193
+ this.newHousenumber = '';
194
+ this.newBusnumber = '';
195
+ }
196
+
197
+ @action
198
+ selectStreet(street: string) {
199
+ this.newStreetName = street;
200
+ this.newHousenumber = '';
201
+ this.newBusnumber = '';
202
+ }
203
+
204
+ @action
205
+ updateHousenumber(event: InputEvent) {
206
+ this.newHousenumber = (event.target as HTMLInputElement).value;
207
+ this.newBusnumber = '';
208
+ }
209
+
210
+ @action
211
+ updateBusnumber(event: InputEvent) {
212
+ this.newBusnumber = (event.target as HTMLInputElement).value;
86
213
  }
87
214
 
88
215
  get controller() {
89
216
  return this.args.controller;
90
217
  }
91
218
 
92
- searchAddress = restartableTask(async (term: string) => {
93
- await timeout(400);
94
- return fetchAddresses(term, this.includeHouseNumber);
219
+ searchMunicipality = restartableTask(async (term: string) => {
220
+ await timeout(200);
221
+ return fetchMunicipalities(term);
222
+ });
223
+
224
+ searchStreet = restartableTask(async (term: string) => {
225
+ if (this.newMunicipality) {
226
+ await timeout(200);
227
+ const streets = await fetchStreets(term, this.newMunicipality);
228
+ return streets;
229
+ } else {
230
+ return [];
231
+ }
95
232
  });
96
233
  }
@@ -14,7 +14,7 @@ export default class AddressNodeviewComponent extends Component<Args> {
14
14
  }
15
15
 
16
16
  get address() {
17
- return this.node.attrs.address as Address | null;
17
+ return this.node.attrs.value as Address | null;
18
18
  }
19
19
 
20
20
  @action
@@ -72,7 +72,12 @@ export default class CodelistEditComponent extends Component<Args> {
72
72
  });
73
73
 
74
74
  get multiSelect() {
75
- return this.codelistOptions.value?.type === MULTI_SELECT_CODELIST_TYPE;
75
+ const localStyle = this.selectedCodelist.value?.node.attrs
76
+ .selectionStyle as string;
77
+ if (localStyle) {
78
+ return localStyle === 'multi';
79
+ } else
80
+ return this.codelistOptions.value?.type === MULTI_SELECT_CODELIST_TYPE;
76
81
  }
77
82
 
78
83
  @action