@lblod/ember-rdfa-editor-lblod-plugins 35.6.0 → 36.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/addon/components/roadsign-regulation-plugin/expanded-measure.gts +85 -15
  3. package/addon/components/roadsign-regulation-plugin/roadsigns-modal.gts +10 -0
  4. package/addon/components/roadsign-regulation-plugin/roadsigns-table.gts +3 -0
  5. package/addon/plugins/decision-plugin/actions/insert-article.ts +89 -46
  6. package/addon/plugins/location-plugin/utils/get-document-locations.ts +63 -0
  7. package/addon/plugins/roadsign-regulation-plugin/actions/insert-measure.ts +7 -83
  8. package/addon/plugins/roadsign-regulation-plugin/helpers/construct-measure-fragment.ts +96 -0
  9. package/addon/plugins/variable-plugin/actions/create-classic-location-variable.ts +3 -10
  10. package/addon/plugins/variable-plugin/contextual-actions/index.ts +188 -0
  11. package/addon/plugins/variable-plugin/utils/codelist-utils.ts +1 -1
  12. package/addon/utils/document-structure-utils.ts +17 -0
  13. package/declarations/addon/components/roadsign-regulation-plugin/expanded-measure.d.ts +22 -1
  14. package/declarations/addon/components/roadsign-regulation-plugin/roadsigns-modal.d.ts +2 -1
  15. package/declarations/addon/components/roadsign-regulation-plugin/roadsigns-table.d.ts +2 -0
  16. package/declarations/addon/plugins/decision-plugin/actions/insert-article.d.ts +1 -0
  17. package/declarations/addon/plugins/location-plugin/utils/get-document-locations.d.ts +4 -0
  18. package/declarations/addon/plugins/roadsign-regulation-plugin/actions/insert-measure.d.ts +2 -1
  19. package/declarations/addon/plugins/roadsign-regulation-plugin/helpers/construct-measure-fragment.d.ts +4 -0
  20. package/declarations/addon/plugins/variable-plugin/actions/create-classic-location-variable.d.ts +1 -1
  21. package/declarations/addon/plugins/variable-plugin/contextual-actions/index.d.ts +17 -0
  22. package/declarations/addon/plugins/variable-plugin/utils/codelist-utils.d.ts +10 -0
  23. package/declarations/addon/utils/document-structure-utils.d.ts +6 -0
  24. package/package.json +3 -3
  25. package/translations/en-US.yaml +5 -1
  26. package/translations/nl-BE.yaml +9 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @lblod/ember-rdfa-editor-lblod-plugins
2
2
 
3
+ ## 36.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [#637](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/pull/637) [`d2d939b`](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/commit/d2d939bd5fe39e51146ad1df777aa48d6f54236b) Thanks [@kobemertens](https://github.com/kobemertens)! - Bump editor
8
+
9
+ - [#637](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/pull/637) [`23a40c0`](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/commit/23a40c0389687eb34933fd2e740789ac29450e1e) Thanks [@kobemertens](https://github.com/kobemertens)! - Add contextual actions for inserting place descriptions
10
+
11
+ ### Minor Changes
12
+
13
+ - [#651](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/pull/651) [`c03484c`](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/commit/c03484cd40fca81c9cdeafa3f0d5f2dcbb6b340f) Thanks [@lagartoverde](https://github.com/lagartoverde)! - Add function to search the document for oslo locations
14
+
15
+ ### Patch Changes
16
+
17
+ - [#643](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/pull/643) [`42cd09c`](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/commit/42cd09c7b199b7c4f487d90b1823f272fe5ff0ab) Thanks [@kobemertens](https://github.com/kobemertens)! - Add slash commands plugin
18
+
19
+ - [#648](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/pull/648) [`329813f`](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/commit/329813f43ee6cdbc25a8c0acb18ba2188f753d1b) Thanks [@kobemertens](https://github.com/kobemertens)! - Adds ability to choose insert position for a mobility measure article
20
+
21
+ - [`8ac430e`](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/commit/8ac430e1b89167275c7cceeb50e331bfe271e46a) Thanks [@kobemertens](https://github.com/kobemertens)! - fix translation mobility measure insert position
22
+
3
23
  ## 35.6.0
4
24
 
5
25
  ### Minor Changes
@@ -5,7 +5,6 @@ import { tracked } from '@glimmer/tracking';
5
5
  import t from 'ember-intl/helpers/t';
6
6
  import MeasurePreview from './measure-preview';
7
7
  import AuRadioGroup from '@appuniversum/ember-appuniversum/components/au-radio-group';
8
- import AuButtonGroup from '@appuniversum/ember-appuniversum/components/au-button-group';
9
8
  import AuButton from '@appuniversum/ember-appuniversum/components/au-button';
10
9
  import { MobilityMeasureConcept } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/roadsign-regulation-plugin/schemas/mobility-measure-concept';
11
10
  import { action } from '@ember/object';
@@ -16,10 +15,15 @@ import {
16
15
  } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/roadsign-regulation-plugin/constants';
17
16
  import { Task } from 'ember-concurrency';
18
17
  import { isSome } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/option';
18
+ import set from '@lblod/ember-rdfa-editor-lblod-plugins/helpers/set';
19
+ import { service } from '@ember/service';
20
+ import IntlService from 'ember-intl/services/intl';
21
+ import { PNode } from '@lblod/ember-rdfa-editor';
22
+ import PowerSelect from 'ember-power-select/components/power-select';
19
23
 
20
24
  export type InsertMobilityMeasureTask = Task<
21
25
  void,
22
- [MobilityMeasureConcept, ZonalOrNot, boolean]
26
+ [MobilityMeasureConcept, ZonalOrNot, boolean, number?]
23
27
  >;
24
28
  type Signature = {
25
29
  Args: {
@@ -27,12 +31,43 @@ type Signature = {
27
31
  selectRow: (uri: string) => void;
28
32
  insert: InsertMobilityMeasureTask;
29
33
  endpoint: string;
34
+ articleNodes: PNode[];
30
35
  };
31
36
  };
32
37
 
38
+ type InsertPositionOption = {
39
+ label: string;
40
+ position: 'first' | 'last' | 'custom';
41
+ insertIndex?: number;
42
+ };
43
+
33
44
  export default class ExpandedMeasure extends Component<Signature> {
45
+ @service declare intl: IntlService;
46
+
34
47
  @tracked zonalityValue?: ZonalOrNot;
35
48
  @tracked temporalValue?: boolean;
49
+ @tracked selectedInsertPosition: InsertPositionOption;
50
+
51
+ insertPositionOptionFirst: InsertPositionOption;
52
+ insertPositionOptionLast: InsertPositionOption;
53
+
54
+ constructor(owner: unknown, args: Signature['Args']) {
55
+ super(owner, args);
56
+ this.insertPositionOptionFirst = {
57
+ label: this.intl.t(
58
+ 'editor-plugins.roadsign-regulation.expanded-measure.as-first-article',
59
+ ),
60
+ position: 'first',
61
+ insertIndex: 0,
62
+ };
63
+ this.insertPositionOptionLast = {
64
+ label: this.intl.t(
65
+ 'editor-plugins.roadsign-regulation.expanded-measure.as-last-article',
66
+ ),
67
+ position: 'last',
68
+ };
69
+ this.selectedInsertPosition = this.insertPositionOptionLast;
70
+ }
36
71
 
37
72
  get isPotentiallyZonal() {
38
73
  return this.args.concept.zonality === ZONALITY_OPTIONS.POTENTIALLY_ZONAL;
@@ -41,6 +76,7 @@ export default class ExpandedMeasure extends Component<Signature> {
41
76
  get insertButtonDisabled() {
42
77
  return (
43
78
  (this.isPotentiallyZonal && !this.zonalityValue) ||
79
+ this.args.insert.isRunning ||
44
80
  (this.args.concept.variableSignage && !isSome(this.temporalValue))
45
81
  );
46
82
  }
@@ -57,11 +93,13 @@ export default class ExpandedMeasure extends Component<Signature> {
57
93
 
58
94
  @action
59
95
  insert() {
96
+ const { insertIndex } = this.selectedInsertPosition;
60
97
  this.args.insert.perform(
61
98
  this.args.concept,
62
99
  // POTENTIALLY_ZONAL option is filtered out by requiring a zonalityValue to submit
63
100
  (this.zonalityValue ?? this.args.concept.zonality) as ZonalOrNot,
64
101
  this.temporalValue ?? false,
102
+ insertIndex,
65
103
  );
66
104
  }
67
105
 
@@ -70,6 +108,29 @@ export default class ExpandedMeasure extends Component<Signature> {
70
108
  this.args.selectRow(this.args.concept.uri);
71
109
  }
72
110
 
111
+ get articlesInDocument() {
112
+ return this.args.articleNodes;
113
+ }
114
+
115
+ get insertPositionOptions() {
116
+ return [
117
+ this.insertPositionOptionLast,
118
+ this.insertPositionOptionFirst,
119
+ ...this.articlesInDocument.slice(1).map((_, index) => ({
120
+ label: this.intl.t(
121
+ 'editor-plugins.roadsign-regulation.expanded-measure.after-article-x',
122
+ { articleNumber: index + 1 },
123
+ ),
124
+ position: 'custom',
125
+ insertIndex: index + 1,
126
+ })),
127
+ ];
128
+ }
129
+
130
+ get insertPositionDropdownTitle() {
131
+ return this.selectedInsertPosition?.label.toLowerCase();
132
+ }
133
+
73
134
  <template>
74
135
  <tr class='au-c-data-table__detail'>
75
136
  <td colspan='5' class='au-o-flow au-o-flow--small'>
@@ -135,19 +196,28 @@ export default class ExpandedMeasure extends Component<Signature> {
135
196
  </AuRadioGroup>
136
197
  </div>
137
198
  {{/if}}
138
- <AuButtonGroup>
139
- <AuButton
140
- {{on 'click' this.insert}}
141
- @loading={{@insert.isRunning}}
142
- @loadingMessage={{t 'common.loading'}}
143
- @disabled={{this.insertButtonDisabled}}
144
- >
145
- {{t 'editor-plugins.utils.insert'}}
146
- </AuButton>
147
- <AuButton @skin='secondary' {{on 'click' this.unselectRow}}>
148
- {{t 'editor-plugins.utils.cancel'}}
149
- </AuButton>
150
- </AuButtonGroup>
199
+ <AuHeading @level='6' @skin='6'>
200
+ {{t
201
+ 'editor-plugins.roadsign-regulation.expanded-measure.insert-position'
202
+ }}
203
+ </AuHeading>
204
+ <PowerSelect
205
+ class='au-u-1-5'
206
+ @allowClear={{false}}
207
+ @onChange={{set this 'selectedInsertPosition'}}
208
+ @selected={{this.selectedInsertPosition}}
209
+ @options={{this.insertPositionOptions}}
210
+ as |option|
211
+ >{{option.label}}</PowerSelect>
212
+ <AuButton
213
+ {{on 'click' this.insert}}
214
+ @skin='primary'
215
+ @loading={{@insert.isRunning}}
216
+ @loadingMessage={{t 'common.loading'}}
217
+ @disabled={{this.insertButtonDisabled}}
218
+ >
219
+ {{t 'common.insert'}}
220
+ </AuButton>
151
221
  </td>
152
222
  </tr>
153
223
  </template>
@@ -41,6 +41,7 @@ import { Variable } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/roadsig
41
41
  import { generateVariableInstanceUri } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/variable-plugin/utils/variable-helpers';
42
42
  import { mapObject } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/map-object';
43
43
  import { v4 as uuid } from 'uuid';
44
+ import { getArticleNodes } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/document-structure-utils';
44
45
 
45
46
  type Option = {
46
47
  uri: string;
@@ -319,6 +320,7 @@ export default class RoadsignsModal extends Component<Signature> {
319
320
  concept: MobilityMeasureConcept,
320
321
  zonality: ZonalOrNot,
321
322
  temporal: boolean,
323
+ position?: number,
322
324
  ) => {
323
325
  if (!this.decisionLocation) {
324
326
  return;
@@ -355,6 +357,7 @@ export default class RoadsignsModal extends Component<Signature> {
355
357
  decisionUri,
356
358
  zonality,
357
359
  temporal,
360
+ position,
358
361
  })(this.controller.mainEditorState).transaction;
359
362
  },
360
363
  { view: this.controller.mainEditorView },
@@ -386,6 +389,12 @@ export default class RoadsignsModal extends Component<Signature> {
386
389
  this.pageNumber = pageNumber;
387
390
  }
388
391
 
392
+ get articleNodes() {
393
+ return getArticleNodes(this.controller.mainEditorState).map(
394
+ (node) => node.node,
395
+ );
396
+ }
397
+
389
398
  <template>
390
399
  <AuModal
391
400
  class='au-c-modal--flush'
@@ -516,6 +525,7 @@ export default class RoadsignsModal extends Component<Signature> {
516
525
  @isLoading={{this.measureConceptsQuery.isRunning}}
517
526
  @insert={{this.insertMeasure}}
518
527
  @options={{@options}}
528
+ @articleNodes={{this.articleNodes}}
519
529
  />
520
530
  {{#if this.measureConceptCount}}
521
531
  {{#let
@@ -21,6 +21,7 @@ import { on } from '@ember/modifier';
21
21
  import { fn } from '@ember/helper';
22
22
  import { TRAFFIC_SIGNAL_CONCEPT_TYPES } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/roadsign-regulation-plugin/constants';
23
23
  import removeZFromLabel from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/roadsign-regulation-plugin/helpers/removeZFromLabel';
24
+ import { PNode } from '@lblod/ember-rdfa-editor';
24
25
 
25
26
  type Signature = {
26
27
  Args: {
@@ -28,6 +29,7 @@ type Signature = {
28
29
  content?: MobilityMeasureConcept[];
29
30
  isLoading?: boolean;
30
31
  insert: InsertMobilityMeasureTask;
32
+ articleNodes: PNode[];
31
33
  };
32
34
  };
33
35
 
@@ -163,6 +165,7 @@ export default class RoadSignsTable extends Component<Signature> {
163
165
  @insert={{@insert}}
164
166
  @selectRow={{this.selectRow}}
165
167
  @endpoint={{@options.endpoint}}
168
+ @articleNodes={{@articleNodes}}
166
169
  />
167
170
  {{/if}}
168
171
  {{else}}
@@ -20,6 +20,7 @@ interface InsertArticleToDecisionArgs {
20
20
  node: PNode;
21
21
  decisionUri: string;
22
22
  insertFreely?: false;
23
+ position?: number;
23
24
  }
24
25
  interface InsertArticleFreelyArgs {
25
26
  node: PNode;
@@ -46,7 +47,7 @@ export function insertArticle(
46
47
  };
47
48
  }
48
49
 
49
- const { decisionUri } = args;
50
+ const { decisionUri, position } = args;
50
51
  const decision = getNodesBySubject(state, decisionUri)[0];
51
52
  if (!decision) {
52
53
  return {
@@ -55,56 +56,98 @@ export function insertArticle(
55
56
  result: false,
56
57
  };
57
58
  }
59
+
58
60
  const decisionResource = decision.value.attrs.subject;
59
61
  const container = getOutgoingTriple(decision.value.attrs, PROV('value'));
60
- if (container) {
61
- const location = findNodeByRdfaId(state.doc, container.object.value);
62
- if (location) {
63
- const insertLocation = location.pos + location.value.nodeSize - 1;
64
- const factory = new SayDataFactory();
65
- const tr = state.tr;
66
- const combiResult = transactionCombinator(
67
- state,
68
- tr.replaceWith(insertLocation, insertLocation, node),
69
- )([
70
- addPropertyToNode({
71
- resource: decisionResource,
72
- property: {
73
- predicate: ELI('has_part').full,
74
- object: factory.resourceNode(node.attrs.subject),
75
- },
76
- }),
77
- recalculateNumbers,
78
- ]);
79
-
80
- const { result, transaction } = combiResult;
81
-
82
- transaction.setSelection(
83
- TextSelection.create(
84
- transaction.doc,
85
- insertLocation + 1,
86
- insertLocation + node.nodeSize - 1,
87
- ),
88
- );
89
-
90
- transaction.scrollIntoView();
91
- return {
92
- initialState: state,
93
- transaction,
94
- result: result.every((ok) => ok),
95
- };
96
- } else {
97
- return {
98
- initialState: state,
99
- transaction: state.tr,
100
- result: false,
101
- };
102
- }
62
+ if (!container) {
63
+ return {
64
+ initialState: state,
65
+ transaction: state.tr,
66
+ result: false,
67
+ };
68
+ }
69
+
70
+ const location = findNodeByRdfaId(state.doc, container.object.value);
71
+ if (!location) {
72
+ return {
73
+ initialState: state,
74
+ transaction: state.tr,
75
+ result: false,
76
+ };
103
77
  }
78
+
79
+ const insertLocation = resolveInsertLocation(location, position);
80
+
81
+ const factory = new SayDataFactory();
82
+ const tr = state.tr;
83
+ const combiResult = transactionCombinator(
84
+ state,
85
+ tr.replaceWith(insertLocation, insertLocation, node),
86
+ )([
87
+ addPropertyToNode({
88
+ resource: decisionResource,
89
+ property: {
90
+ predicate: ELI('has_part').full,
91
+ object: factory.resourceNode(node.attrs.subject),
92
+ },
93
+ }),
94
+ recalculateNumbers,
95
+ ]);
96
+
97
+ const { result, transaction } = combiResult;
98
+
99
+ transaction.setSelection(
100
+ TextSelection.create(
101
+ transaction.doc,
102
+ insertLocation + 1,
103
+ insertLocation + node.nodeSize - 1,
104
+ ),
105
+ );
106
+
107
+ transaction.scrollIntoView();
104
108
  return {
105
109
  initialState: state,
106
- transaction: state.tr,
107
- result: false,
110
+ transaction,
111
+ result: result.every((ok) => ok),
108
112
  };
109
113
  };
110
114
  }
115
+
116
+ /**
117
+ * Resolves the document position at which to insert a new article node
118
+ *
119
+ * - If `position` is undefined, insert at the end of the container.
120
+ * - If `position` is 0, insert before the first child.
121
+ * - If `position` >= childCount, insert after the last child (append).
122
+ * - Otherwise, insert before the child at that index.
123
+ */
124
+ function resolveInsertLocation(
125
+ location: { pos: number; value: PNode },
126
+ position: number | undefined,
127
+ ): number {
128
+ const containerNode = location.value;
129
+
130
+ if (position === undefined) {
131
+ return location.pos + containerNode.nodeSize - 1;
132
+ }
133
+
134
+ const childCount = containerNode.childCount;
135
+
136
+ if (position >= childCount) {
137
+ return location.pos + containerNode.nodeSize - 1;
138
+ }
139
+
140
+ let offset = location.pos + 1; // +1 to step inside the container node
141
+ let articleIndex = 0;
142
+ for (const child of containerNode.children) {
143
+ if (articleIndex === position) {
144
+ return offset;
145
+ }
146
+ offset += child.nodeSize;
147
+ if (child.attrs.structureType === 'article') {
148
+ articleIndex += 1;
149
+ }
150
+ }
151
+
152
+ return location.pos + containerNode.nodeSize - 1;
153
+ }
@@ -0,0 +1,63 @@
1
+ import { EditorState } from '@lblod/ember-rdfa-editor';
2
+ import { Area, Place } from './geo-helpers';
3
+ import { Address } from './address-helpers';
4
+
5
+ type LocationsWithDistanceType = {
6
+ location: Place | Address | Area;
7
+ distance: number;
8
+ };
9
+
10
+ type LocationMetadataType = {
11
+ [locationUri: string]: { ocurrences: number; distance: number };
12
+ };
13
+
14
+ export default function getDocumentLocations(state: EditorState) {
15
+ const doc = state.doc;
16
+ const locationsWithDistance: LocationsWithDistanceType[] = [];
17
+ const selection = state.selection;
18
+ doc.descendants((node, pos) => {
19
+ if (node.type.name === 'oslo_location') {
20
+ const distance = Math.abs(pos - selection.from);
21
+ locationsWithDistance.push({
22
+ location: node.attrs.value,
23
+ distance: distance,
24
+ });
25
+ return false;
26
+ }
27
+ return true;
28
+ });
29
+ const locationMetadata: LocationMetadataType = {};
30
+ const locationsDedup: (Place | Address | Area)[] = [];
31
+ for (const locationWithDistance of locationsWithDistance) {
32
+ const uri =
33
+ (locationWithDistance.location as Address).belgianAddressUri ||
34
+ locationWithDistance.location.uri;
35
+ if (!locationMetadata[uri]) {
36
+ locationMetadata[uri] = {
37
+ ocurrences: 1,
38
+ distance: locationWithDistance.distance,
39
+ };
40
+ locationsDedup.push(locationWithDistance.location);
41
+ } else {
42
+ locationMetadata[uri].ocurrences++;
43
+ if (locationWithDistance.distance < locationMetadata[uri].distance) {
44
+ locationMetadata[uri].distance = locationWithDistance.distance;
45
+ }
46
+ }
47
+ }
48
+
49
+ const locations = locationsDedup.sort((a, b) => {
50
+ const uriA = (a as Address).belgianAddressUri || a.uri;
51
+ const uriB = (b as Address).belgianAddressUri || b.uri;
52
+ if (
53
+ locationMetadata[uriA].ocurrences === locationMetadata[uriB].ocurrences
54
+ ) {
55
+ return locationMetadata[uriA].distance - locationMetadata[uriB].distance;
56
+ } else {
57
+ return (
58
+ locationMetadata[uriB].ocurrences - locationMetadata[uriA].ocurrences
59
+ );
60
+ }
61
+ });
62
+ return locations;
63
+ }
@@ -7,10 +7,7 @@ import {
7
7
  } from '@lblod/ember-rdfa-editor';
8
8
  import { v4 as uuid } from 'uuid';
9
9
  import { addPropertyToNode } from '@lblod/ember-rdfa-editor/utils/rdfa-utils';
10
- import {
11
- type IncomingTriple,
12
- type FullTriple,
13
- } from '@lblod/ember-rdfa-editor/core/rdfa-processor';
10
+ import { type FullTriple } from '@lblod/ember-rdfa-editor/core/rdfa-processor';
14
11
  import {
15
12
  DCT,
16
13
  EXT,
@@ -36,16 +33,12 @@ import {
36
33
  ZONALITY_OPTIONS,
37
34
  ZonalOrNot,
38
35
  } from '../constants';
39
- import { createTextVariable } from '../../variable-plugin/actions/create-text-variable';
40
- import { createNumberVariable } from '../../variable-plugin/actions/create-number-variable';
41
- import { createDateVariable } from '../../variable-plugin/actions/create-date-variable';
42
- import { createClassicLocationVariable } from '../../variable-plugin/actions/create-classic-location-variable';
43
36
  import { isTrafficSignal, TrafficSignal } from '../schemas/traffic-signal';
44
37
  import { MobilityMeasureDesign } from '../schemas/mobility-measure-design';
45
38
  import { VariableInstance } from '../schemas/variable-instance';
46
- import { createCodelistVariable } from '../../variable-plugin/actions/create-codelist-variable';
47
39
  import removeZFromLabel from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/roadsign-regulation-plugin/helpers/removeZFromLabel';
48
40
  import { namespace } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/namespace';
41
+ import { constructMeasureFragment } from '../helpers/construct-measure-fragment';
49
42
 
50
43
  // This is defined locally as it's an implementation quirk that we don't want to use generally
51
44
  const RELATIE_OBJECT = namespace(
@@ -60,6 +53,7 @@ type InsertMeasureArgs = {
60
53
  variables: Record<string, VariableInstance & { __rdfaId: string }>;
61
54
  templateString: string;
62
55
  decisionUri: string;
56
+ position?: number;
63
57
  articleUriGenerator?: () => string;
64
58
  } & (
65
59
  | {
@@ -78,6 +72,7 @@ export default function insertMeasure({
78
72
  templateString,
79
73
  articleUriGenerator,
80
74
  decisionUri,
75
+ position,
81
76
  ...args
82
77
  }: InsertMeasureArgs): TransactionMonad<boolean> {
83
78
  return function (state: EditorState) {
@@ -153,7 +148,7 @@ export default function insertMeasure({
153
148
  ];
154
149
  }
155
150
  const measureUri = `http://data.lblod.info/mobiliteitsmaatregels/${uuid()}`;
156
- const measureBody = constructMeasureBody(
151
+ const measureBody = constructMeasureFragment(
157
152
  templateString,
158
153
  variables,
159
154
  schema,
@@ -221,7 +216,7 @@ export default function insertMeasure({
221
216
  ],
222
217
  externalTriples,
223
218
  },
224
- [measureBody, ...signSection, ...(temporalNode ? [temporalNode] : [])],
219
+ [...measureBody, ...signSection, ...(temporalNode ? [temporalNode] : [])],
225
220
  );
226
221
  const articleNode = buildArticleStructure(
227
222
  state.schema,
@@ -230,6 +225,7 @@ export default function insertMeasure({
230
225
  const initialTransaction = insertArticle({
231
226
  node: articleNode,
232
227
  decisionUri,
228
+ position,
233
229
  })(state).transaction;
234
230
  const resultingSelection = initialTransaction.selection;
235
231
  const { transaction, result } = transactionCombinator(
@@ -268,34 +264,6 @@ export default function insertMeasure({
268
264
  };
269
265
  }
270
266
 
271
- function constructMeasureBody(
272
- templateString: string,
273
- variables: Record<string, VariableInstance>,
274
- schema: Schema,
275
- backlinks?: IncomingTriple[],
276
- ) {
277
- const parts = templateString.split(/(\$\{[^{}$]+\})/);
278
- const nodes = [];
279
- for (const part of parts) {
280
- if (!part) {
281
- continue;
282
- }
283
- const match = /^\$\{([^{}$]+)\}$/.exec(part);
284
- if (match) {
285
- const variableName = match[1];
286
- const matchedVariable = variables[variableName];
287
- if (matchedVariable) {
288
- nodes.push(constructVariableNode(matchedVariable, schema, backlinks));
289
- } else {
290
- nodes.push(schema.text(part));
291
- }
292
- } else {
293
- nodes.push(schema.text(part));
294
- }
295
- }
296
- return schema.nodes.paragraph.create({}, nodes);
297
- }
298
-
299
267
  function determineSignLabel(signConcept: TrafficSignalConcept) {
300
268
  switch (signConcept.type) {
301
269
  case TRAFFIC_SIGNAL_CONCEPT_TYPES.TRAFFIC_LIGHT:
@@ -363,47 +331,3 @@ function constructSignalNode(
363
331
  );
364
332
  return node;
365
333
  }
366
-
367
- function constructVariableNode(
368
- variableInstance: VariableInstance,
369
- schema: Schema,
370
- backlinks?: IncomingTriple[],
371
- ) {
372
- const variable = variableInstance.variable;
373
- const valueStr =
374
- variableInstance.value instanceof Date
375
- ? variableInstance.value.toISOString()
376
- : variableInstance.value?.toString();
377
- const args = {
378
- schema,
379
- backlinks,
380
- variable: variable.uri,
381
- variableInstance: variableInstance.uri,
382
- __rdfaId: variableInstance.__rdfaId,
383
- value: valueStr,
384
- valueLabel:
385
- 'valueLabel' in variableInstance
386
- ? variableInstance.valueLabel
387
- : undefined,
388
- label: variable.label,
389
- };
390
- switch (variable.type) {
391
- case 'text':
392
- return createTextVariable(args);
393
- case 'number':
394
- return createNumberVariable(args);
395
- case 'date':
396
- return createDateVariable(args);
397
- case 'codelist':
398
- return createCodelistVariable({
399
- ...args,
400
- source: variable.source,
401
- codelist: variable.codelistUri,
402
- });
403
- case 'location':
404
- return createClassicLocationVariable({
405
- ...args,
406
- source: variable.source,
407
- });
408
- }
409
- }
@@ -0,0 +1,96 @@
1
+ import { Schema } from '@lblod/ember-rdfa-editor';
2
+ import { type IncomingTriple } from '@lblod/ember-rdfa-editor/core/rdfa-processor';
3
+ import { VariableInstance } from '../schemas/variable-instance';
4
+ import { createTextVariable } from '../../variable-plugin/actions/create-text-variable';
5
+ import { createNumberVariable } from '../../variable-plugin/actions/create-number-variable';
6
+ import { createDateVariable } from '../../variable-plugin/actions/create-date-variable';
7
+ import { createClassicLocationVariable } from '../../variable-plugin/actions/create-classic-location-variable';
8
+ import { createCodelistVariable } from '../../variable-plugin/actions/create-codelist-variable';
9
+
10
+ export function constructMeasureFragment(
11
+ templateString: string,
12
+ variables: Record<string, VariableInstance>,
13
+ schema: Schema,
14
+ backlinks?: IncomingTriple[],
15
+ ) {
16
+ // TODO: extract this functionality of parsing a text with "variable" placeholders into a fragment to a more general place
17
+ const parts = templateString.split(/(\$\{[^{}$]+\})/);
18
+ const fragment = [];
19
+ let currentParagraphContent = [];
20
+ for (const part of parts) {
21
+ if (!part) {
22
+ continue;
23
+ }
24
+ const match = /^\$\{([^{}$]+)\}$/.exec(part);
25
+ if (match) {
26
+ const variableName = match[1];
27
+ const matchedVariable = variables[variableName];
28
+ if (matchedVariable) {
29
+ const node = constructVariableNode(matchedVariable, schema, backlinks);
30
+ if (node.type.isBlock) {
31
+ if (currentParagraphContent.length > 0) {
32
+ fragment.push(
33
+ schema.nodes.paragraph.create({}, currentParagraphContent),
34
+ );
35
+ currentParagraphContent = [];
36
+ }
37
+ fragment.push(node);
38
+ }
39
+ } else {
40
+ currentParagraphContent.push(schema.text(part));
41
+ }
42
+ } else {
43
+ currentParagraphContent.push(schema.text(part));
44
+ }
45
+ }
46
+
47
+ if (currentParagraphContent.length > 0) {
48
+ fragment.push(schema.nodes.paragraph.create({}, currentParagraphContent));
49
+ }
50
+
51
+ return fragment;
52
+ }
53
+
54
+ function constructVariableNode(
55
+ variableInstance: VariableInstance,
56
+ schema: Schema,
57
+ backlinks?: IncomingTriple[],
58
+ ) {
59
+ const variable = variableInstance.variable;
60
+ const valueStr =
61
+ variableInstance.value instanceof Date
62
+ ? variableInstance.value.toISOString()
63
+ : variableInstance.value?.toString();
64
+ const args = {
65
+ schema,
66
+ backlinks,
67
+ variable: variable.uri,
68
+ variableInstance: variableInstance.uri,
69
+ __rdfaId: variableInstance.__rdfaId,
70
+ value: valueStr,
71
+ valueLabel:
72
+ 'valueLabel' in variableInstance
73
+ ? variableInstance.valueLabel
74
+ : undefined,
75
+ label: variable.label,
76
+ };
77
+ switch (variable.type) {
78
+ case 'text':
79
+ return createTextVariable(args);
80
+ case 'number':
81
+ return createNumberVariable(args);
82
+ case 'date':
83
+ return createDateVariable(args);
84
+ case 'codelist':
85
+ return createCodelistVariable({
86
+ ...args,
87
+ source: variable.source,
88
+ codelist: variable.codelistUri,
89
+ });
90
+ case 'location':
91
+ return createClassicLocationVariable({
92
+ ...args,
93
+ source: variable.source,
94
+ });
95
+ }
96
+ }
@@ -20,16 +20,9 @@ type CreateClassicLocationVariableArgs = {
20
20
  export function createClassicLocationVariable(
21
21
  args: CreateClassicLocationVariableArgs,
22
22
  ) {
23
- const { schema, value, label } = args;
23
+ const { schema } = args;
24
24
  const attrs = createClassicLocationVariableAttrs(args);
25
- return schema.nodes.location.create(
26
- attrs,
27
- value
28
- ? schema.text(value)
29
- : schema.node('placeholder', {
30
- placeholderText: label,
31
- }),
32
- );
25
+ return schema.nodes.block_rdfa.create(attrs, schema.nodes.paragraph.create());
33
26
  }
34
27
 
35
28
  type CreateClassicLocationVariableAttrsArgs = {
@@ -88,7 +81,7 @@ export function createClassicLocationVariableAttrs({
88
81
  __rdfaId,
89
82
  externalTriples,
90
83
  backlinks: [...backlinks, ...addedBacklinks],
91
- label,
84
+ label: label ?? 'Plaatsbeschrijving',
92
85
  source,
93
86
  };
94
87
  }
@@ -0,0 +1,188 @@
1
+ import {
2
+ EditorState,
3
+ NodeSelection,
4
+ Transaction,
5
+ } from '@lblod/ember-rdfa-editor';
6
+ import { fetchCodeListOptions } from '../utils/fetch-data';
7
+ import { findParentNode } from '@curvenote/prosemirror-utils';
8
+ import {
9
+ getOutgoingTriple,
10
+ hasOutgoingNamedNodeTriple,
11
+ } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/namespace';
12
+ import {
13
+ EXT,
14
+ MOBILITEIT,
15
+ RDF,
16
+ } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
17
+ import {
18
+ ZONALITY_OPTIONS,
19
+ ZONALITY_OPTIONS_LEGACY,
20
+ } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/roadsign-regulation-plugin/constants';
21
+ import { ProseParser } from '@lblod/ember-rdfa-editor';
22
+ import { wrapVariableInHighlight } from '../utils/codelist-utils';
23
+ import { getActiveEditableNode } from '@lblod/ember-rdfa-editor/plugins/editable-node';
24
+ import { isRdfaAttrs } from '@lblod/ember-rdfa-editor/core/rdfa-types';
25
+ import { v4 as uuidv4 } from 'uuid';
26
+ import { getTranslationFunction } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/translation';
27
+
28
+ const plaatsbepalingGroupId =
29
+ 'plaatsbepaling-1d8563d6-bfd8-487f-a2a0-6d7a6ab01cb5';
30
+
31
+ function getSelectedLocation(state: EditorState) {
32
+ const { selection } = state;
33
+ if (
34
+ selection instanceof NodeSelection &&
35
+ selection.node.type === state.schema.nodes.location
36
+ ) {
37
+ return {
38
+ node: selection.node,
39
+ pos: selection.from,
40
+ };
41
+ } else {
42
+ return;
43
+ }
44
+ }
45
+
46
+ function getSource(state: EditorState, fallback?: string) {
47
+ const selectedLocation = getSelectedLocation(state);
48
+ if (selectedLocation) {
49
+ const { node } = selectedLocation;
50
+ const source = node.attrs.source;
51
+ if (source) {
52
+ return source;
53
+ }
54
+ }
55
+
56
+ return fallback;
57
+ }
58
+
59
+ function getIsZonal(state: EditorState) {
60
+ const { selection } = state;
61
+ const mobilityMeasureNode = findParentNode((node) =>
62
+ hasOutgoingNamedNodeTriple(
63
+ node.attrs,
64
+ RDF('type'),
65
+ MOBILITEIT('Mobiliteitsmaatregel'),
66
+ ),
67
+ )(selection)?.node;
68
+ if (!mobilityMeasureNode) {
69
+ return false;
70
+ }
71
+ const zonalityTriple = getOutgoingTriple(
72
+ mobilityMeasureNode.attrs,
73
+ EXT('zonality'),
74
+ );
75
+ if (!zonalityTriple) {
76
+ return false;
77
+ }
78
+ return (
79
+ zonalityTriple.object.value === ZONALITY_OPTIONS.ZONAL ||
80
+ zonalityTriple.object.value === ZONALITY_OPTIONS_LEGACY.ZONAL
81
+ );
82
+ }
83
+
84
+ type GetContextualActionsAttrs = {
85
+ zonalLocationCodelistUri: string;
86
+ nonZonalLocationCodelistUri: string;
87
+ endpoint?: string;
88
+ };
89
+
90
+ function humanReadableLabel(label: string) {
91
+ return label.replace(/\$\{[^}]+\}/g, '…');
92
+ }
93
+
94
+ function createInsertPlaceDescriptionCommand(label: string) {
95
+ return (state: EditorState, dispatch: (tr: Transaction) => void) => {
96
+ if (dispatch) {
97
+ let htmlToInsert = label;
98
+ htmlToInsert = wrapVariableInHighlight(htmlToInsert);
99
+ const domParser = new DOMParser();
100
+ const htmlNode = domParser.parseFromString(htmlToInsert, 'text/html');
101
+ const contentFragment = ProseParser.fromSchema(state.schema).parseSlice(
102
+ htmlNode,
103
+ {
104
+ preserveWhitespace: false,
105
+ },
106
+ );
107
+
108
+ const tr = state.tr;
109
+ const startPos = tr.selection.from;
110
+ tr.replaceSelection(contentFragment);
111
+
112
+ let highlightPos: number | null = null;
113
+
114
+ contentFragment.content.descendants((child, pos) => {
115
+ if (highlightPos !== null) {
116
+ return false;
117
+ }
118
+ if (child.type.name === state.schema.nodes.placeholder.name) {
119
+ highlightPos = startPos + pos;
120
+ return false;
121
+ }
122
+ return true;
123
+ });
124
+
125
+ if (highlightPos !== null) {
126
+ tr.setSelection(NodeSelection.create(tr.doc, highlightPos));
127
+ }
128
+ dispatch(tr);
129
+ }
130
+ return true;
131
+ };
132
+ }
133
+
134
+ export function getContextualActions({
135
+ zonalLocationCodelistUri,
136
+ nonZonalLocationCodelistUri,
137
+ endpoint,
138
+ }: GetContextualActionsAttrs) {
139
+ return async function (state: EditorState) {
140
+ const source = getSource(state, endpoint);
141
+ const isZonal = getIsZonal(state);
142
+ const result = await fetchCodeListOptions(
143
+ source,
144
+ isZonal ? zonalLocationCodelistUri : nonZonalLocationCodelistUri,
145
+ );
146
+
147
+ return result.options.map((option) => {
148
+ return {
149
+ id: uuidv4(),
150
+ label: humanReadableLabel(option.label),
151
+ group: plaatsbepalingGroupId,
152
+ command: createInsertPlaceDescriptionCommand(option.label),
153
+ };
154
+ });
155
+ };
156
+ }
157
+
158
+ function contextualGroupIsVisible(state: EditorState) {
159
+ const activeNode = getActiveEditableNode(state);
160
+ const isPlaatsbepaling =
161
+ activeNode &&
162
+ isRdfaAttrs(activeNode.value.attrs) &&
163
+ activeNode.value.attrs.backlinks.some((value) =>
164
+ MOBILITEIT('plaatsbepaling').matches(value.predicate),
165
+ );
166
+
167
+ const isEmptySelection = state.selection.empty;
168
+ return (
169
+ (activeNode?.value.type.name === 'location' || isPlaatsbepaling) &&
170
+ isEmptySelection
171
+ );
172
+ }
173
+
174
+ export function getContextualActionGroups() {
175
+ return function (state: EditorState) {
176
+ return contextualGroupIsVisible(state)
177
+ ? [
178
+ {
179
+ id: plaatsbepalingGroupId,
180
+ label: getTranslationFunction(state)(
181
+ 'variable.location.label',
182
+ 'Plaatsbeschrijving',
183
+ ),
184
+ },
185
+ ]
186
+ : [];
187
+ };
188
+ }
@@ -14,7 +14,7 @@ import { unwrap } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/option';
14
14
  * E.g. `This is a variable with ${placeholder}` gets converted to:
15
15
  * `This is a variable with <span class="mark-highlight-manual">${placeholder}</span>`
16
16
  */
17
- function wrapVariableInHighlight(text: string) {
17
+ export function wrapVariableInHighlight(text: string) {
18
18
  return text.replace(
19
19
  /\$\{(.+?)\}/g,
20
20
  '<span class="mark-highlight-manual">${$1}</span>',
@@ -0,0 +1,17 @@
1
+ import { EditorState } from '@lblod/ember-rdfa-editor';
2
+ import { PNode } from '@lblod/ember-rdfa-editor';
3
+
4
+ export function getArticleNodes(state: EditorState) {
5
+ const articles: { node: PNode; pos: number }[] = [];
6
+
7
+ state.doc.descendants((node, pos) => {
8
+ if (node.attrs.structureType === 'article') {
9
+ articles.push({ node, pos });
10
+ return false;
11
+ }
12
+
13
+ return true;
14
+ });
15
+
16
+ return articles;
17
+ }
@@ -2,10 +2,13 @@ import Component from '@glimmer/component';
2
2
  import { MobilityMeasureConcept } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/roadsign-regulation-plugin/schemas/mobility-measure-concept';
3
3
  import { ZonalOrNot } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/roadsign-regulation-plugin/constants';
4
4
  import { Task } from 'ember-concurrency';
5
+ import IntlService from 'ember-intl/services/intl';
6
+ import { PNode } from '@lblod/ember-rdfa-editor';
5
7
  export type InsertMobilityMeasureTask = Task<void, [
6
8
  MobilityMeasureConcept,
7
9
  ZonalOrNot,
8
- boolean
10
+ boolean,
11
+ number?
9
12
  ]>;
10
13
  type Signature = {
11
14
  Args: {
@@ -13,16 +16,34 @@ type Signature = {
13
16
  selectRow: (uri: string) => void;
14
17
  insert: InsertMobilityMeasureTask;
15
18
  endpoint: string;
19
+ articleNodes: PNode[];
16
20
  };
17
21
  };
22
+ type InsertPositionOption = {
23
+ label: string;
24
+ position: 'first' | 'last' | 'custom';
25
+ insertIndex?: number;
26
+ };
18
27
  export default class ExpandedMeasure extends Component<Signature> {
28
+ intl: IntlService;
19
29
  zonalityValue?: ZonalOrNot;
20
30
  temporalValue?: boolean;
31
+ selectedInsertPosition: InsertPositionOption;
32
+ insertPositionOptionFirst: InsertPositionOption;
33
+ insertPositionOptionLast: InsertPositionOption;
34
+ constructor(owner: unknown, args: Signature['Args']);
21
35
  get isPotentiallyZonal(): boolean;
22
36
  get insertButtonDisabled(): boolean;
23
37
  changeZonality(zonality: ZonalOrNot): void;
24
38
  changeTemporality(temporality: 'true' | 'false'): void;
25
39
  insert(): void;
26
40
  unselectRow(): void;
41
+ get articlesInDocument(): PNode[];
42
+ get insertPositionOptions(): (InsertPositionOption | {
43
+ label: string;
44
+ position: string;
45
+ insertIndex: number;
46
+ })[];
47
+ get insertPositionDropdownTitle(): string;
27
48
  }
28
49
  export {};
@@ -134,10 +134,11 @@ export default class RoadsignsModal extends Component<Signature> {
134
134
  }))[];
135
135
  }[] | undefined;
136
136
  get measureConceptCount(): number | undefined;
137
- insertMeasure: import("ember-concurrency").TaskForAsyncTaskFunction<unknown, (concept: MobilityMeasureConcept, zonality: ZonalOrNot, temporal: boolean) => Promise<void>>;
137
+ insertMeasure: import("ember-concurrency").TaskForAsyncTaskFunction<unknown, (concept: MobilityMeasureConcept, zonality: ZonalOrNot, temporal: boolean, position?: number) => Promise<void>>;
138
138
  resetPagination(): void;
139
139
  goToPreviousPage(): void;
140
140
  goToNextPage(): void;
141
141
  goToPage(pageNumber: number): void;
142
+ get articleNodes(): import("prosemirror-model").Node[];
142
143
  }
143
144
  export {};
@@ -2,12 +2,14 @@ import Component from '@glimmer/component';
2
2
  import { RoadsignRegulationPluginOptions } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/roadsign-regulation-plugin';
3
3
  import { MobilityMeasureConcept } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/roadsign-regulation-plugin/schemas/mobility-measure-concept';
4
4
  import { InsertMobilityMeasureTask } from './expanded-measure';
5
+ import { PNode } from '@lblod/ember-rdfa-editor';
5
6
  type Signature = {
6
7
  Args: {
7
8
  options: RoadsignRegulationPluginOptions;
8
9
  content?: MobilityMeasureConcept[];
9
10
  isLoading?: boolean;
10
11
  insert: InsertMobilityMeasureTask;
12
+ articleNodes: PNode[];
11
13
  };
12
14
  };
13
15
  export default class RoadSignsTable extends Component<Signature> {
@@ -4,6 +4,7 @@ interface InsertArticleToDecisionArgs {
4
4
  node: PNode;
5
5
  decisionUri: string;
6
6
  insertFreely?: false;
7
+ position?: number;
7
8
  }
8
9
  interface InsertArticleFreelyArgs {
9
10
  node: PNode;
@@ -0,0 +1,4 @@
1
+ import { EditorState } from '@lblod/ember-rdfa-editor';
2
+ import { Area, Place } from './geo-helpers';
3
+ import { Address } from './address-helpers';
4
+ export default function getDocumentLocations(state: EditorState): (Address | Place | Area)[];
@@ -12,11 +12,12 @@ type InsertMeasureArgs = {
12
12
  }>;
13
13
  templateString: string;
14
14
  decisionUri: string;
15
+ position?: number;
15
16
  articleUriGenerator?: () => string;
16
17
  } & ({
17
18
  measureConcept: MobilityMeasureConcept;
18
19
  } | {
19
20
  measureDesign: MobilityMeasureDesign;
20
21
  });
21
- export default function insertMeasure({ arDesignUri, zonality, temporal, variables, templateString, articleUriGenerator, decisionUri, ...args }: InsertMeasureArgs): TransactionMonad<boolean>;
22
+ export default function insertMeasure({ arDesignUri, zonality, temporal, variables, templateString, articleUriGenerator, decisionUri, position, ...args }: InsertMeasureArgs): TransactionMonad<boolean>;
22
23
  export {};
@@ -0,0 +1,4 @@
1
+ import { Schema } from '@lblod/ember-rdfa-editor';
2
+ import { type IncomingTriple } from '@lblod/ember-rdfa-editor/core/rdfa-processor';
3
+ import { VariableInstance } from '../schemas/variable-instance';
4
+ export declare function constructMeasureFragment(templateString: string, variables: Record<string, VariableInstance>, schema: Schema, backlinks?: IncomingTriple[]): import("prosemirror-model").Node[];
@@ -21,7 +21,7 @@ export declare function createClassicLocationVariableAttrs({ variable, variableI
21
21
  __rdfaId: string | undefined;
22
22
  externalTriples: FullTriple[];
23
23
  backlinks: IncomingTriple[];
24
- label: string | undefined;
24
+ label: string;
25
25
  source: string | undefined;
26
26
  };
27
27
  export {};
@@ -0,0 +1,17 @@
1
+ import { EditorState, Transaction } from '@lblod/ember-rdfa-editor';
2
+ type GetContextualActionsAttrs = {
3
+ zonalLocationCodelistUri: string;
4
+ nonZonalLocationCodelistUri: string;
5
+ endpoint?: string;
6
+ };
7
+ export declare function getContextualActions({ zonalLocationCodelistUri, nonZonalLocationCodelistUri, endpoint, }: GetContextualActionsAttrs): (state: EditorState) => Promise<{
8
+ id: string;
9
+ label: string;
10
+ group: string;
11
+ command: (state: EditorState, dispatch: (tr: Transaction) => void) => boolean;
12
+ }[]>;
13
+ export declare function getContextualActionGroups(): (state: EditorState) => {
14
+ id: string;
15
+ label: string;
16
+ }[];
17
+ export {};
@@ -1,5 +1,15 @@
1
1
  import { CodeListOption } from './fetch-data';
2
2
  import { PNode, SayController } from '@lblod/ember-rdfa-editor';
3
+ /**
4
+ *
5
+ * @param text content of variable option which needs to be inserted
6
+ * @returns content of variable option where the placeholders (indicated by ${...})
7
+ * are wrapped in a span with class `mark-highlight-manual`.
8
+ *
9
+ * E.g. `This is a variable with ${placeholder}` gets converted to:
10
+ * `This is a variable with <span class="mark-highlight-manual">${placeholder}</span>`
11
+ */
12
+ export declare function wrapVariableInHighlight(text: string): string;
3
13
  export declare function updateCodelistVariable(selectedCodelist: {
4
14
  node: PNode;
5
15
  pos: number;
@@ -0,0 +1,6 @@
1
+ import { EditorState } from '@lblod/ember-rdfa-editor';
2
+ import { PNode } from '@lblod/ember-rdfa-editor';
3
+ export declare function getArticleNodes(state: EditorState): {
4
+ node: PNode;
5
+ pos: number;
6
+ }[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lblod/ember-rdfa-editor-lblod-plugins",
3
- "version": "35.6.0",
3
+ "version": "36.0.0",
4
4
  "description": "Ember addon providing lblod specific plugins for the ember-rdfa-editor",
5
5
  "keywords": [
6
6
  "ember-addon",
@@ -111,8 +111,8 @@
111
111
  "@glint/ember-tsc": "^1.5.0",
112
112
  "@glint/environment-ember-loose": "^1.5.0",
113
113
  "@glint/environment-ember-template-imports": "^1.5.0",
114
+ "@lblod/ember-rdfa-editor": "13.7.1",
114
115
  "@glint/template": "^1.7.7",
115
- "@lblod/ember-rdfa-editor": "13.6.0",
116
116
  "@rdfjs/to-ntriples": "^3.0.1",
117
117
  "@rdfjs/types": "^1.1.0",
118
118
  "@release-it/keep-a-changelog": "^4.0.0",
@@ -184,7 +184,7 @@
184
184
  "@appuniversum/ember-appuniversum": "^3.12.0",
185
185
  "@ember/string": "3.x",
186
186
  "@glint/template": "^1.4.0",
187
- "@lblod/ember-rdfa-editor": "^12.15.0 || ^13.0.0",
187
+ "@lblod/ember-rdfa-editor": "^13.7.1",
188
188
  "ember-concurrency": "^4.0.2",
189
189
  "ember-element-helper": "^0.8.6",
190
190
  "ember-intl": "^7.0.0",
@@ -208,7 +208,7 @@ variable:
208
208
  multi-select: Multiple selection
209
209
  label: codelist
210
210
  location:
211
- label: location
211
+ label: place description
212
212
  text:
213
213
  label: text
214
214
  date:
@@ -316,6 +316,10 @@ editor-plugins:
316
316
  roadsign-regulation:
317
317
  expanded-measure:
318
318
  insert-measure: 'Insert measure:'
319
+ as-last-article: As last article
320
+ as-first-article: As first article
321
+ after-article-x: After article {articleNumber}
322
+ insert-position: 'Insertion position:'
319
323
  select-zonality:
320
324
  label: 'Select zonal validity:'
321
325
  zonal: Zonal
@@ -212,7 +212,7 @@ variable:
212
212
  multi-select: Meervoudige selectie
213
213
  label: codelijst
214
214
  location:
215
- label: locatie
215
+ label: plaatsbeschrijving
216
216
  text:
217
217
  label: tekst
218
218
  date:
@@ -232,7 +232,7 @@ variable-plugin:
232
232
  enter-variable-value: Selecteer waarde
233
233
  unknown-codelist: Er werden geen mogelijke waarden voor deze codelijst gevonden
234
234
  label: Label
235
- labelPlaceholder: Type iets...
235
+ labelPlaceholder: Label invullen…
236
236
  number:
237
237
  minimum: Minimum
238
238
  minimum-placeholder: minimumwaarde
@@ -272,7 +272,7 @@ snippet-plugin:
272
272
  search:
273
273
  title: Filter op
274
274
  label: Fragmentnaam
275
- placeholder: Typ iets...
275
+ placeholder: Vul in…
276
276
  snippet-list:
277
277
  open-modal: Fragmentlijsten beheren
278
278
  modal:
@@ -281,7 +281,7 @@ snippet-plugin:
281
281
  search:
282
282
  title: Filter op
283
283
  label: Naam lijst
284
- placeholder: Typ iets..
284
+ placeholder: Vul in…
285
285
  button:
286
286
  cancel: Annuleer
287
287
  update: Fragmentlijsten opslaan
@@ -315,6 +315,10 @@ editor-plugins:
315
315
  roadsign-regulation:
316
316
  expanded-measure:
317
317
  insert-measure: 'Voeg maatregel in:'
318
+ as-last-article: Als laatste artikel
319
+ as-first-article: Als eerste artikel
320
+ after-article-x: Na artikel {articleNumber}
321
+ insert-position: 'Invoegpositie:'
318
322
  select-zonality:
319
323
  label: 'Selecteer zonale geldigheid:'
320
324
  zonal: Zonaal
@@ -445,7 +449,7 @@ location-plugin:
445
449
  place: Plaats
446
450
  area: Gebied
447
451
  label: Label
448
- labelPlaceholder: Type iets...
452
+ labelPlaceholder: Vul in…
449
453
  default-label: locatie
450
454
  map:
451
455
  hint: