@lblod/ember-rdfa-editor-lblod-plugins 11.0.0 → 11.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 (40) hide show
  1. package/CHANGELOG.md +18 -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/number/insert.hbs +2 -0
  12. package/addon/components/variable-plugin/number/insert.ts +30 -8
  13. package/addon/plugins/article-structure-plugin/commands/wrap-structure-content.ts +86 -11
  14. package/addon/plugins/article-structure-plugin/structures/article.ts +1 -0
  15. package/addon/plugins/article-structure-plugin/structures/structure-header.ts +2 -1
  16. package/addon/plugins/article-structure-plugin/structures/title.ts +2 -0
  17. package/addon/plugins/article-structure-plugin/utils/structure.ts +4 -0
  18. package/addon/plugins/document-title-plugin/nodes/document-title.ts +1 -0
  19. package/addon/plugins/generic-rdfa-variable/commands/index.ts +1 -0
  20. package/addon/plugins/generic-rdfa-variable/commands/insert-generic-rdfa.ts +25 -0
  21. package/addon/plugins/snippet-plugin/utils/fetch-data.ts +3 -1
  22. package/addon/plugins/variable-plugin/utils/address-helpers.ts +220 -69
  23. package/addon/plugins/variable-plugin/variables/address.ts +118 -147
  24. package/addon/utils/constants.ts +4 -0
  25. package/addon/utils/find-insertion-contentmatch.ts +61 -0
  26. package/app/components/loading-alert.js +1 -0
  27. package/components/generic-rdfa-variable/insert-menu.d.ts +1 -0
  28. package/components/loading-alert.d.ts +3 -0
  29. package/components/variable-plugin/address/edit.d.ts +31 -8
  30. package/components/variable-plugin/number/insert.d.ts +18 -2
  31. package/package.json +3 -3
  32. package/plugins/article-structure-plugin/utils/structure.d.ts +2 -0
  33. package/plugins/generic-rdfa-variable/commands/index.d.ts +1 -0
  34. package/plugins/generic-rdfa-variable/commands/insert-generic-rdfa.d.ts +2 -0
  35. package/plugins/variable-plugin/utils/address-helpers.d.ts +30 -3
  36. package/plugins/variable-plugin/variables/address.d.ts +6 -14
  37. package/translations/en-US.yaml +25 -6
  38. package/translations/nl-BE.yaml +25 -6
  39. package/utils/constants.d.ts +1 -0
  40. package/utils/find-insertion-contentmatch.d.ts +23 -0
package/CHANGELOG.md CHANGED
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [11.1.0] - 2023-08-29
11
+
12
+ ### Fixed
13
+ - GN-4370: Do not allow header nodes to be split by table
14
+ - Grey out Generic RDFA button in embedded view
15
+ - GN-4425: Smarter content wrapping for structure nodes
16
+
17
+ ### Changed
18
+ - GN-4442: template comments can move up and down over the *whole* document
19
+ - GN-4322: Add ORDER to snippet list query
20
+ - Bumps `@lblod/ember-rdfa-editor` from 5.1.0 to 5.2.0
21
+
10
22
  ## [11.0.0] - 2023-08-22
11
23
 
12
24
  ### Added
@@ -15,8 +27,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
15
27
  - Introduce internationalization in the table of contents node based on the document language.
16
28
  - The whole table of contents node (include its entries) is now exported in its `serialize` method without the need of an `entries` attribute.
17
29
  - GN-4461: update readme to specify needed imports for template comment
30
+ - Check validity on number minimum/maximum inputs
18
31
 
19
32
  ### Changed
33
+ - GN-4263: update address variable edit UI/UX according to updated design
34
+ - Allow the address municipality-edit field to be prefilled
20
35
  - Use one-way-binding in variable label input
21
36
  - Use one-way-binding in number variable inputs
22
37
  - Manage snippet list connection with template
@@ -29,6 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
29
44
  - 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
45
  ### Dependencies
31
46
  - Bumps `@codemirror/view` from 6.12.0 to 6.16.0
47
+ - Bumps `@lblod/ember-rdfa-editor` from 4.2.0 to 5.1.0
32
48
 
33
49
  ## [10.0.0] - 2023-08-08
34
50
  ### Changed
@@ -675,7 +691,7 @@ add onclick handler to pencil icon in variable plugin
675
691
 
676
692
  # Changelog
677
693
 
678
- [unreleased]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v11.0.0...HEAD
694
+ [unreleased]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v11.1.0...HEAD
679
695
  [8.0.0]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v8.0.0...v8.0.1
680
696
  [8.0.0]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v7.1.0...v8.0.0
681
697
  [7.1.0]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v7.0.0...v7.1.0
@@ -691,6 +707,7 @@ add onclick handler to pencil icon in variable plugin
691
707
  [3.0.0]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v2.1.2...v3.0.0
692
708
  [2.1.2]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v2.1.1...v2.1.2
693
709
  [2.1.1]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v2.1.0...v2.1.1
710
+ [11.1.0]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v11.0.0...v11.1.0
694
711
  [11.0.0]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v10.0.0...v11.0.0
695
712
  [10.0.0]: https://github.com/lblod/ember-rdfa-editor-lblod-plugins/compare/v9.1.1...v10.0.0
696
713
  [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
@@ -12,6 +12,7 @@
12
12
  id={{id}}
13
13
  value={{this.minimumValue}}
14
14
  {{on 'input' this.updateMinimumValue}}
15
+ {{this.minimumInput}}
15
16
  placeholder={{t 'variable-plugin.number.minimum-placeholder'}}
16
17
  @width='block'
17
18
  @type="number"
@@ -28,6 +29,7 @@
28
29
  id={{id}}
29
30
  value={{this.maximumValue}}
30
31
  {{on 'input' this.updateMaximumValue}}
32
+ {{this.maximumInput}}
31
33
  placeholder={{t 'variable-plugin.number.maximum-placeholder'}}
32
34
  @width='block'
33
35
  @type="number"