@lblod/ember-rdfa-editor-lblod-plugins 32.8.0 → 33.0.0-dev.7d01346456985efa3fc4438c828b4fbc31de297e

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 (45) hide show
  1. package/.changeset/strange-otters-buy.md +5 -0
  2. package/.changeset/tender-actors-shout.md +5 -0
  3. package/CHANGELOG.md +15 -0
  4. package/addon/components/besluit-topic-plugin/besluit-topic-toolbar-dropdown.ts +1 -1
  5. package/addon/components/besluit-type-plugin/toolbar-dropdown.gts +1 -1
  6. package/addon/components/decision-plugin/decision-plugin-card.gts +3 -2
  7. package/addon/components/decision-plugin/insert-article.gts +1 -1
  8. package/addon/components/document-validation-plugin/card.gts +130 -33
  9. package/addon/components/lpdc-plugin/lpdc-insert.ts +1 -1
  10. package/addon/components/roadsign-regulation-plugin/roadsign-regulation-card.gts +1 -1
  11. package/addon/components/roadsign-regulation-plugin/roadsigns-modal.gts +5 -2
  12. package/addon/components/variable-plugin/location/edit.ts +8 -2
  13. package/addon/plugins/besluit-type-plugin/utils/besluit-type-instances.ts +1 -1
  14. package/addon/plugins/besluit-type-plugin/utils/set-besluit-type.ts +1 -1
  15. package/addon/plugins/decision-plugin/commands/insert-article-container.ts +14 -1
  16. package/addon/plugins/decision-plugin/commands/insert-description.ts +9 -1
  17. package/addon/plugins/decision-plugin/commands/insert-motivation.ts +9 -1
  18. package/addon/plugins/decision-plugin/commands/insert-title.ts +9 -1
  19. package/addon/plugins/document-validation-plugin/common-fixes.ts +125 -0
  20. package/addon/plugins/document-validation-plugin/index.ts +61 -32
  21. package/addon/plugins/roadsign-regulation-plugin/actions/insert-measure.ts +9 -2
  22. package/addon/plugins/roadsign-regulation-plugin/constants.ts +46 -0
  23. package/addon/plugins/roadsign-regulation-plugin/nodes.ts +54 -11
  24. package/addon/plugins/roadsign-regulation-plugin/queries/mobility-measure-concept.ts +27 -4
  25. package/addon/plugins/roadsign-regulation-plugin/queries/traffic-signal-concept.ts +0 -5
  26. package/addon/plugins/roadsign-regulation-plugin/schemas/traffic-signal-concept.ts +1 -2
  27. package/addon/{plugins/besluit-topic-plugin/utils/helpers.ts → utils/decision-utils.ts} +33 -9
  28. package/addon/utils/types.ts +2 -0
  29. package/declarations/addon/components/document-validation-plugin/card.d.ts +51 -1
  30. package/declarations/addon/components/roadsign-regulation-plugin/roadsigns-modal.d.ts +7 -6
  31. package/declarations/addon/plugins/decision-plugin/commands/insert-article-container.d.ts +3 -1
  32. package/declarations/addon/plugins/document-validation-plugin/common-fixes.d.ts +6 -0
  33. package/declarations/addon/plugins/document-validation-plugin/index.d.ts +30 -6
  34. package/declarations/addon/plugins/roadsign-regulation-plugin/constants.d.ts +12 -0
  35. package/declarations/addon/plugins/roadsign-regulation-plugin/nodes.d.ts +1 -0
  36. package/declarations/addon/plugins/roadsign-regulation-plugin/queries/mobility-measure-concept.d.ts +3 -3
  37. package/declarations/addon/plugins/roadsign-regulation-plugin/queries/traffic-signal-concept.d.ts +0 -2
  38. package/declarations/addon/plugins/roadsign-regulation-plugin/schemas/mobility-measure-concept.d.ts +5 -14
  39. package/declarations/addon/plugins/roadsign-regulation-plugin/schemas/traffic-signal-concept.d.ts +0 -7
  40. package/declarations/addon/{plugins/besluit-topic-plugin/utils/helpers.d.ts → utils/decision-utils.d.ts} +5 -1
  41. package/declarations/addon/utils/types.d.ts +1 -0
  42. package/package.json +4 -4
  43. package/pnpm-lock.yaml +416 -314
  44. package/translations/en-US.yaml +1 -0
  45. package/translations/nl-BE.yaml +1 -0
@@ -0,0 +1,5 @@
1
+ ---
2
+ '@lblod/ember-rdfa-editor-lblod-plugins': patch
3
+ ---
4
+
5
+ Fix ordering of measures in IRGN plugin
@@ -0,0 +1,5 @@
1
+ ---
2
+ '@lblod/ember-rdfa-editor-lblod-plugins': minor
3
+ ---
4
+
5
+ Add actions to document validation plugin
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @lblod/ember-rdfa-editor-lblod-plugins
2
2
 
3
+ ## 33.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [#604](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/pull/604) [`6299352`](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/commit/629935200df1c15d3094483465dcffc734daf55c) Thanks [@elpoelma](https://github.com/elpoelma)! - Increase `@lblod/ember-rdfa-editor` peerdep requirement to version [12.5.0](https://github.com/lblod/ember-rdfa-editor/releases/tag/%40lblod%2Fember-rdfa-editor%4012.15.0)
8
+ This versions contains `block_rdfa` support for model migrations.
9
+
10
+ ### Minor Changes
11
+
12
+ - [#607](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/pull/607) [`9032503`](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/commit/903250362f411c8c1f49912deb60f80f09c0ef89) Thanks [@piemonkey](https://github.com/piemonkey)! - Update RDFa output of roadsign-regulation-plugin to more closely match the data model
13
+
14
+ ### Patch Changes
15
+
16
+ - [#604](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/pull/604) [`cf02699`](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/commit/cf02699ef6e7811195546eaf9d4c98a873d08ab3) Thanks [@elpoelma](https://github.com/elpoelma)! - Update zonality concept URIs based on new URI bases
17
+
3
18
  ## 32.8.0
4
19
 
5
20
  ### Minor Changes
@@ -15,7 +15,7 @@ import {
15
15
  import {
16
16
  getCurrentBesluitRange,
17
17
  getCurrentBesluitURI,
18
- } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/besluit-topic-plugin/utils/helpers';
18
+ } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/decision-utils';
19
19
  import {
20
20
  updateBesluitTopicResource,
21
21
  TOPIC_PREDICATE,
@@ -16,7 +16,7 @@ import { CircleXIcon } from '@appuniversum/ember-appuniversum/components/icons/c
16
16
  import { SayController } from '@lblod/ember-rdfa-editor';
17
17
  import fetchBesluitTypes from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/besluit-type-plugin/utils/fetchBesluitTypes';
18
18
  import { BesluitTypePluginOptions } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/besluit-type-plugin';
19
- import { getCurrentBesluitRange } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/besluit-topic-plugin/utils/helpers';
19
+ import { getCurrentBesluitRange } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/decision-utils';
20
20
  import {
21
21
  BesluitTypeInstance,
22
22
  checkBesluitTypeInstance,
@@ -23,7 +23,7 @@ import { on } from '@ember/modifier';
23
23
  import { not } from 'ember-truth-helpers';
24
24
  import t from 'ember-intl/helpers/t';
25
25
  import { TemplateOnlyComponent } from '@ember/component/template-only';
26
- import { getCurrentBesluitRange } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/besluit-topic-plugin/utils/helpers';
26
+ import { getCurrentBesluitRange } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/decision-utils';
27
27
 
28
28
  interface DecisionCardOptions {
29
29
  articleUriGenerator?: () => string;
@@ -145,12 +145,13 @@ export default class DecisionPluginCard extends Component<Sig> {
145
145
  }
146
146
  @action
147
147
  insertArticleBlock() {
148
- if (this.decisionUri) {
148
+ if (this.decisionUri && this.decisionNodeLocation) {
149
149
  this.controller.doCommand(
150
150
  insertArticleContainer({
151
151
  intl: this.intl,
152
152
  decisionUri: this.decisionUri,
153
153
  articleUriGenerator: this.args.options?.articleUriGenerator,
154
+ decisionLocation: this.decisionNodeLocation,
154
155
  }),
155
156
  {
156
157
  view: this.controller.mainEditorView,
@@ -4,7 +4,7 @@ import { action } from '@ember/object';
4
4
  import Component from '@glimmer/component';
5
5
  import { AddIcon } from '@appuniversum/ember-appuniversum/components/icons/add';
6
6
  import { PNode, SayController } from '@lblod/ember-rdfa-editor';
7
- import { getCurrentBesluitRange } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/besluit-topic-plugin/utils/helpers';
7
+ import { getCurrentBesluitRange } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/decision-utils';
8
8
  import { buildArticleStructure } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/decision-plugin/utils/build-article-structure';
9
9
  import { not } from 'ember-truth-helpers';
10
10
  import { service } from '@ember/service';
@@ -12,6 +12,8 @@ import AuButton from '@appuniversum/ember-appuniversum/components/au-button';
12
12
  import { ExternalLinkIcon } from '@appuniversum/ember-appuniversum/components/icons/external-link';
13
13
  import t from 'ember-intl/helpers/t';
14
14
  import { eq } from 'ember-truth-helpers';
15
+ import ValidationReport from 'rdf-validate-shacl/src/validation-report';
16
+ import { CircleInfoIcon } from '@appuniversum/ember-appuniversum/components/icons/circle-info';
15
17
 
16
18
  interface Sig {
17
19
  Args: {
@@ -19,6 +21,17 @@ interface Sig {
19
21
  };
20
22
  }
21
23
 
24
+ type ExtractWithKey<T, K extends PropertyKey> = T extends Record<K, unknown>
25
+ ? T
26
+ : never;
27
+
28
+ function hasProperty<
29
+ O extends object = object,
30
+ K extends PropertyKey = PropertyKey,
31
+ >(obj: O, key: K): obj is ExtractWithKey<O, K> {
32
+ return key in obj;
33
+ }
34
+
22
35
  export default class DocumentValidationPluginCard extends Component<Sig> {
23
36
  get controller() {
24
37
  return this.args.controller;
@@ -37,10 +50,26 @@ export default class DocumentValidationPluginCard extends Component<Sig> {
37
50
  }
38
51
  get documentValidationErrors() {
39
52
  if (!this.validationState) return [];
40
- const { propertiesWithErrors } = this.validationState;
53
+
54
+ const { propertiesWithErrors, rules } = this.validationState;
41
55
  if (!propertiesWithErrors) return undefined;
42
56
 
43
- return propertiesWithErrors;
57
+ const documentValidationErrors = propertiesWithErrors.map((property) => {
58
+ const rule = rules.find((rule) => property?.shape === rule.shaclRule);
59
+ if (rule && 'violations' in rule) {
60
+ const rulePerConstraint = rule.violations[property?.constraint];
61
+ return {
62
+ ...property,
63
+ rule: rulePerConstraint,
64
+ };
65
+ } else {
66
+ return {
67
+ ...property,
68
+ rule: rule,
69
+ };
70
+ }
71
+ });
72
+ return documentValidationErrors;
44
73
  }
45
74
  get propertiesWithoutErrors() {
46
75
  if (!this.validationState) return [];
@@ -65,6 +94,53 @@ export default class DocumentValidationPluginCard extends Component<Sig> {
65
94
  return ['valid', 'no-matches'].includes(this.status);
66
95
  }
67
96
 
97
+ doActionAndTriggerValidation = async (
98
+ action: (controller: SayController, report: ValidationReport) => void,
99
+ ) => {
100
+ action(this.controller, this.validationState?.report as ValidationReport);
101
+ const pluginState = documentValidationPluginKey.getState(
102
+ this.controller.mainEditorView.state,
103
+ );
104
+ if (!pluginState) return;
105
+ const { validationCallback } = pluginState;
106
+ await validationCallback(
107
+ this.controller.mainEditorView,
108
+ this.controller.htmlContent,
109
+ );
110
+ };
111
+
112
+ oldVal: typeof this.documentValidationErrors;
113
+
114
+ dedupeDocumentValidationErrors = (
115
+ val: typeof this.documentValidationErrors,
116
+ ) => {
117
+ if (this.compareDocumentValidationErrors(val, this.oldVal)) {
118
+ return this.oldVal;
119
+ } else {
120
+ this.oldVal = val;
121
+ return val;
122
+ }
123
+ };
124
+
125
+ compareDocumentValidationErrors = (
126
+ val1: typeof this.documentValidationErrors,
127
+ val2: typeof this.documentValidationErrors,
128
+ ) => {
129
+ if (!val1?.length) return false;
130
+ if (val1.length !== val2?.length) return false;
131
+ for (let i = 0; i < val1.length; i++) {
132
+ if (
133
+ !val1 ||
134
+ !val2 ||
135
+ !val1[i] ||
136
+ !val2[i] ||
137
+ val1[i].shape !== val2[i].shape
138
+ )
139
+ return false;
140
+ }
141
+ return true;
142
+ };
143
+
68
144
  <template>
69
145
  <AuCard
70
146
  @flex={{true}}
@@ -94,42 +170,63 @@ export default class DocumentValidationPluginCard extends Component<Sig> {
94
170
  </p>
95
171
  </c.header>
96
172
  <c.content>
97
- <p class='au-u-medium au-u-para-small'>{{t
98
- 'document-validation-plugin.description'
99
- }}</p>
100
- {{#each this.documentValidationErrors as |error|}}
101
- <div class='say-document-validation__error-container'>
102
- <AuIcon
103
- @icon={{CloseFilledIcon}}
104
- @size='large'
105
- @ariaHidden={{true}}
106
- class='say-document-validation__icon-error au-u-margin-right-small'
107
- />
108
- <div>
109
- {{error.message}}
110
- <AuButton
111
- class='au-u-padding-left-none au-u-padding-right-none'
112
- @icon={{ExternalLinkIcon}}
113
- @skin='link'
114
- title={{error.subject}}
115
- {{on 'click' (fn this.goToSubject error.subject)}}
116
- >{{t 'document-validation-plugin.see-related-node'}}</AuButton>
117
- </div>
118
- </div>
119
- {{/each}}
120
- {{#each this.propertiesWithoutErrors as |property|}}
121
- <div class='say-document-validation__error-container'>
122
- <div class='au-u-margin-right-small'>
173
+ <div>
174
+ {{#each
175
+ (this.dedupeDocumentValidationErrors this.documentValidationErrors)
176
+ as |error|
177
+ }}
178
+ <div class='say-document-validation__error-container'>
123
179
  <AuIcon
124
- @icon={{CheckFilledIcon}}
180
+ @icon={{CloseFilledIcon}}
125
181
  @size='large'
126
182
  @ariaHidden={{true}}
127
- class='say-document-validation__icon-success'
183
+ class='say-document-validation__icon-error au-u-margin-right-small'
128
184
  />
185
+ <div>
186
+ {{error.message}}
187
+ <AuButton
188
+ class='au-u-padding-left-none au-u-padding-right-none'
189
+ @icon={{ExternalLinkIcon}}
190
+ @skin='link'
191
+ title={{error.subject}}
192
+ {{on 'click' (fn this.goToSubject error.subject)}}
193
+ >{{t 'document-validation-plugin.see-related-node'}}</AuButton>
194
+ {{#if error.rule}}
195
+ {{#if (hasProperty error.rule 'action')}}
196
+ <AuButton
197
+ class='au-u-padding-left-none au-u-padding-right-none'
198
+ @icon={{ExternalLinkIcon}}
199
+ @skin='link'
200
+ title={{error.subject}}
201
+ {{on
202
+ 'click'
203
+ (fn this.doActionAndTriggerValidation error.rule.action)
204
+ }}
205
+ >{{error.rule.buttonTitle}}</AuButton>
206
+ {{/if}}
207
+ {{#if (hasProperty error.rule 'helpText')}}
208
+ <span title={{error.rule.helpText}}>
209
+ <AuIcon @icon={{CircleInfoIcon}} />
210
+ </span>
211
+ {{/if}}
212
+ {{/if}}
213
+ </div>
214
+ </div>
215
+ {{/each}}
216
+ {{#each this.propertiesWithoutErrors as |property|}}
217
+ <div class='say-document-validation__error-container'>
218
+ <div class='au-u-margin-right-small'>
219
+ <AuIcon
220
+ @icon={{CheckFilledIcon}}
221
+ @size='large'
222
+ @ariaHidden={{true}}
223
+ class='say-document-validation__icon-success'
224
+ />
225
+ </div>
226
+ {{property.message}}
129
227
  </div>
130
- {{property.message}}
131
- </div>
132
- {{/each}}
228
+ {{/each}}
229
+ </div>
133
230
  </c.content>
134
231
 
135
232
  </AuCard>
@@ -11,7 +11,7 @@ import {
11
11
  type LpdcPluginConfig,
12
12
  } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/lpdc-plugin';
13
13
  import { v4 as uuidv4 } from 'uuid';
14
- import { getCurrentBesluitURI } from '../../plugins/besluit-topic-plugin/utils/helpers';
14
+ import { getCurrentBesluitURI } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/decision-utils';
15
15
  import { SRO } from '../../utils/constants';
16
16
 
17
17
  interface Args {
@@ -3,7 +3,7 @@ import { action } from '@ember/object';
3
3
  import Component from '@glimmer/component';
4
4
  import { tracked } from '@glimmer/tracking';
5
5
  import { SayController } from '@lblod/ember-rdfa-editor';
6
- import { getCurrentBesluitRange } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/besluit-topic-plugin/utils/helpers';
6
+ import { getCurrentBesluitRange } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/decision-utils';
7
7
  import { RoadsignRegulationPluginOptions } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/roadsign-regulation-plugin';
8
8
  import { RDF } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
9
9
  import { OutgoingTriple } from '@lblod/ember-rdfa-editor/core/rdfa-processor';
@@ -6,7 +6,7 @@ import { action } from '@ember/object';
6
6
  import Component from '@glimmer/component';
7
7
  import { tracked } from '@glimmer/tracking';
8
8
  import { SayController } from '@lblod/ember-rdfa-editor';
9
- import { getCurrentBesluitRange } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/besluit-topic-plugin/utils/helpers';
9
+ import { getCurrentBesluitRange } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/decision-utils';
10
10
  import { RoadsignRegulationPluginOptions } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/roadsign-regulation-plugin';
11
11
  import {
12
12
  countMobilityMeasures,
@@ -43,7 +43,10 @@ type Option = {
43
43
  label: string;
44
44
  };
45
45
 
46
- type Zonality = Option;
46
+ type Zonality = {
47
+ uri: (typeof ZONALITY_OPTIONS)[keyof typeof ZONALITY_OPTIONS];
48
+ label: string;
49
+ };
47
50
  type TypeOption = Option;
48
51
  type Code = Option;
49
52
  type Category = Option;
@@ -12,7 +12,10 @@ import { unwrap } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/option';
12
12
  import { trackedFunction } from 'reactiveweb/function';
13
13
  import { updateCodelistVariable } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/variable-plugin/utils/codelist-utils';
14
14
  import { tracked } from '@glimmer/tracking';
15
- import { ZONALITY_OPTIONS } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/roadsign-regulation-plugin/constants';
15
+ import {
16
+ ZONALITY_OPTIONS,
17
+ ZONALITY_OPTIONS_LEGACY,
18
+ } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/roadsign-regulation-plugin/constants';
16
19
  import {
17
20
  getOutgoingTriple,
18
21
  hasOutgoingNamedNodeTriple,
@@ -109,7 +112,10 @@ export default class LocationEditComponent extends Component<Args> {
109
112
  if (!zonalityTriple) {
110
113
  return false;
111
114
  }
112
- return zonalityTriple.object.value === ZONALITY_OPTIONS.ZONAL;
115
+ return (
116
+ zonalityTriple.object.value === ZONALITY_OPTIONS.ZONAL ||
117
+ zonalityTriple.object.value === ZONALITY_OPTIONS_LEGACY.ZONAL
118
+ );
113
119
  }
114
120
 
115
121
  locationOptions = trackedFunction(this, async () => {
@@ -1,6 +1,6 @@
1
1
  import { type EditorState } from '@lblod/ember-rdfa-editor';
2
2
  import { getOutgoingTripleList } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/namespace';
3
- import { getCurrentBesluitRange } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/besluit-topic-plugin/utils/helpers';
3
+ import { getCurrentBesluitRange } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/decision-utils';
4
4
  import { RDF } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
5
5
  import { type BesluitType } from './fetchBesluitTypes';
6
6
  import { type NamedNodeTriple } from '@lblod/ember-rdfa-editor/core/rdfa-processor';
@@ -8,7 +8,7 @@ import {
8
8
  removePropertyFromNode,
9
9
  } from '@lblod/ember-rdfa-editor/utils/rdfa-utils';
10
10
  import { sayDataFactory } from '@lblod/ember-rdfa-editor/core/say-data-factory';
11
- import { getCurrentBesluitURI } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/besluit-topic-plugin/utils/helpers';
11
+ import { getCurrentBesluitURI } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/decision-utils';
12
12
  import {
13
13
  extractBesluitTypeUris,
14
14
  isValidTypeChoice,
@@ -8,16 +8,19 @@ import { buildArticleStructure } from '../utils/build-article-structure';
8
8
  import { transactionCombinator } from '@lblod/ember-rdfa-editor/utils/transaction-utils';
9
9
  import { insertArticle } from '../actions/insert-article';
10
10
  import { recalculateNumbers } from '../../structure-plugin/monads/recalculate-structure-numbers';
11
+ import { NodeWithPos } from '@curvenote/prosemirror-utils';
11
12
 
12
13
  interface InsertArticleContainerArgs {
13
14
  intl: IntlService;
14
15
  decisionUri: string;
15
16
  articleUriGenerator?: () => string;
17
+ decisionLocation: NodeWithPos;
16
18
  }
17
19
 
18
20
  export default function insertArticleContainer({
19
21
  decisionUri,
20
22
  articleUriGenerator,
23
+ decisionLocation,
21
24
  }: InsertArticleContainerArgs): Command {
22
25
  return function (state: EditorState, dispatch?: (tr: Transaction) => void) {
23
26
  const { schema } = state;
@@ -33,9 +36,19 @@ export default function insertArticleContainer({
33
36
  const articleNode = buildArticleStructure(schema, articleUriGenerator);
34
37
 
35
38
  const factory = new SayDataFactory();
39
+ let replaceTr;
40
+ if (state.selection.$from.pos === decisionLocation.pos) {
41
+ replaceTr = state.tr.replaceRangeWith(
42
+ decisionLocation.pos + decisionLocation.node.nodeSize - 1,
43
+ decisionLocation.pos + decisionLocation.node.nodeSize - 1,
44
+ containerNode,
45
+ );
46
+ } else {
47
+ replaceTr = state.tr.replaceSelectionWith(containerNode);
48
+ }
36
49
  const { transaction: newTr, result } = transactionCombinator<boolean>(
37
50
  state,
38
- state.tr.replaceSelectionWith(containerNode),
51
+ replaceTr,
39
52
  )([
40
53
  addPropertyToNode({
41
54
  resource: decisionUri,
@@ -31,7 +31,15 @@ export default function insertDescription({
31
31
  );
32
32
  const tr = state.tr;
33
33
 
34
- tr.replaceSelectionWith(nodeToInsert);
34
+ if (state.selection.$from.pos === decisionLocation.pos) {
35
+ tr.replaceRangeWith(
36
+ decisionLocation.pos + decisionLocation.node.nodeSize - 1,
37
+ decisionLocation.pos + decisionLocation.node.nodeSize - 1,
38
+ nodeToInsert,
39
+ );
40
+ } else {
41
+ tr.replaceSelectionWith(nodeToInsert);
42
+ }
35
43
 
36
44
  const factory = new SayDataFactory();
37
45
  const { transaction: newTr, result } = transactionCombinator<boolean>(
@@ -110,7 +110,15 @@ export default function insertMotivation({
110
110
  ],
111
111
  );
112
112
  const tr = state.tr;
113
- tr.replaceSelectionWith(nodeToInsert);
113
+ if (state.selection.$from.pos === decisionLocation.pos) {
114
+ tr.replaceRangeWith(
115
+ decisionLocation.pos + decisionLocation.node.nodeSize - 1,
116
+ decisionLocation.pos + decisionLocation.node.nodeSize - 1,
117
+ nodeToInsert,
118
+ );
119
+ } else {
120
+ tr.replaceSelectionWith(nodeToInsert);
121
+ }
114
122
  const factory = new SayDataFactory();
115
123
 
116
124
  const { transaction: newTr, result } = transactionCombinator<boolean>(
@@ -31,7 +31,15 @@ export default function insertTitle({
31
31
  );
32
32
 
33
33
  const tr = state.tr;
34
- tr.replaceSelectionWith(nodeToInsert);
34
+ if (state.selection.$from.pos === decisionLocation.pos) {
35
+ tr.replaceRangeWith(
36
+ decisionLocation.pos + decisionLocation.node.nodeSize - 1,
37
+ decisionLocation.pos + decisionLocation.node.nodeSize - 1,
38
+ nodeToInsert,
39
+ );
40
+ } else {
41
+ tr.replaceSelectionWith(nodeToInsert);
42
+ }
35
43
 
36
44
  const factory = new SayDataFactory();
37
45
  const { transaction: newTr, result } = transactionCombinator<boolean>(
@@ -0,0 +1,125 @@
1
+ import { SayController } from '@lblod/ember-rdfa-editor';
2
+ import { getDecisionNodeLocation } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/decision-utils';
3
+ import IntlService from 'ember-intl/services/intl';
4
+ import {
5
+ Notification,
6
+ notificationPluginKey,
7
+ } from '@lblod/ember-rdfa-editor/plugins/notification';
8
+ import {
9
+ insertMotivation,
10
+ insertArticleContainer,
11
+ insertDescription,
12
+ insertTitle,
13
+ } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/decision-plugin/commands';
14
+ import { CircleXIcon } from '@appuniversum/ember-appuniversum/components/icons/circle-x';
15
+
16
+ export function insertTitleAtCursor(
17
+ controller: SayController,
18
+ intl: IntlService,
19
+ ) {
20
+ const decisionNodeLocation = getDecisionNodeLocation(controller);
21
+ if (!decisionNodeLocation) {
22
+ return sendNotificationError(
23
+ controller,
24
+ intl.t('document-validation-plugin.decision-node-not-found'),
25
+ );
26
+ }
27
+ controller.doCommand(
28
+ insertTitle({
29
+ placeholderText: intl.t('besluit-plugin.placeholder.decision-title'),
30
+ decisionLocation: decisionNodeLocation,
31
+ }),
32
+ { view: controller.mainEditorView },
33
+ );
34
+ controller.focus();
35
+ }
36
+
37
+ export function insertDescriptionAtCursor(
38
+ controller: SayController,
39
+ intl: IntlService,
40
+ ) {
41
+ const decisionNodeLocation = getDecisionNodeLocation(controller);
42
+ if (!decisionNodeLocation) {
43
+ return sendNotificationError(
44
+ controller,
45
+ intl.t('document-validation-plugin.decision-node-not-found'),
46
+ );
47
+ }
48
+ controller.doCommand(
49
+ insertDescription({
50
+ placeholderText: intl.t(
51
+ 'besluit-plugin.placeholder.decision-description',
52
+ ),
53
+ decisionLocation: decisionNodeLocation,
54
+ }),
55
+ {
56
+ view: controller.mainEditorView,
57
+ },
58
+ );
59
+ controller.focus();
60
+ }
61
+
62
+ export function insertMotivationAtCursor(
63
+ controller: SayController,
64
+ intl: IntlService,
65
+ ) {
66
+ const decisionNodeLocation = getDecisionNodeLocation(controller);
67
+ if (!decisionNodeLocation) {
68
+ return sendNotificationError(
69
+ controller,
70
+ intl.t('document-validation-plugin.decision-node-not-found'),
71
+ );
72
+ }
73
+ controller.doCommand(
74
+ insertMotivation({
75
+ intl: intl,
76
+ decisionLocation: decisionNodeLocation,
77
+ }),
78
+ {
79
+ view: controller.mainEditorView,
80
+ },
81
+ );
82
+ controller.focus();
83
+ }
84
+
85
+ export function insertArticleContainerAtCursor(
86
+ controller: SayController,
87
+ intl: IntlService,
88
+ articleUriGenerator?: () => string,
89
+ ) {
90
+ const decisionNodeLocation = getDecisionNodeLocation(controller);
91
+ if (!decisionNodeLocation) {
92
+ return sendNotificationError(
93
+ controller,
94
+ intl.t('document-validation-plugin.decision-node-not-found'),
95
+ );
96
+ }
97
+ controller.doCommand(
98
+ insertArticleContainer({
99
+ intl: intl,
100
+ decisionUri: decisionNodeLocation?.node.attrs.subject,
101
+ articleUriGenerator: articleUriGenerator,
102
+ decisionLocation: decisionNodeLocation,
103
+ }),
104
+ {
105
+ view: controller.mainEditorView,
106
+ },
107
+ );
108
+ }
109
+
110
+ function sendNotificationError(controller: SayController, text: string) {
111
+ // Show a notification via the notification plugin
112
+ const { notificationCallback } = notificationPluginKey.getState(
113
+ controller.mainEditorState,
114
+ ) as {
115
+ notificationCallback: (notification: Notification) => void;
116
+ intl: IntlService;
117
+ };
118
+ notificationCallback({
119
+ title: text,
120
+ options: {
121
+ type: 'error',
122
+ icon: CircleXIcon,
123
+ },
124
+ });
125
+ }