@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.
- package/CHANGELOG.md +20 -0
- package/addon/components/roadsign-regulation-plugin/expanded-measure.gts +85 -15
- package/addon/components/roadsign-regulation-plugin/roadsigns-modal.gts +10 -0
- package/addon/components/roadsign-regulation-plugin/roadsigns-table.gts +3 -0
- package/addon/plugins/decision-plugin/actions/insert-article.ts +89 -46
- package/addon/plugins/location-plugin/utils/get-document-locations.ts +63 -0
- package/addon/plugins/roadsign-regulation-plugin/actions/insert-measure.ts +7 -83
- package/addon/plugins/roadsign-regulation-plugin/helpers/construct-measure-fragment.ts +96 -0
- package/addon/plugins/variable-plugin/actions/create-classic-location-variable.ts +3 -10
- package/addon/plugins/variable-plugin/contextual-actions/index.ts +188 -0
- package/addon/plugins/variable-plugin/utils/codelist-utils.ts +1 -1
- package/addon/utils/document-structure-utils.ts +17 -0
- package/declarations/addon/components/roadsign-regulation-plugin/expanded-measure.d.ts +22 -1
- package/declarations/addon/components/roadsign-regulation-plugin/roadsigns-modal.d.ts +2 -1
- package/declarations/addon/components/roadsign-regulation-plugin/roadsigns-table.d.ts +2 -0
- package/declarations/addon/plugins/decision-plugin/actions/insert-article.d.ts +1 -0
- package/declarations/addon/plugins/location-plugin/utils/get-document-locations.d.ts +4 -0
- package/declarations/addon/plugins/roadsign-regulation-plugin/actions/insert-measure.d.ts +2 -1
- package/declarations/addon/plugins/roadsign-regulation-plugin/helpers/construct-measure-fragment.d.ts +4 -0
- package/declarations/addon/plugins/variable-plugin/actions/create-classic-location-variable.d.ts +1 -1
- package/declarations/addon/plugins/variable-plugin/contextual-actions/index.d.ts +17 -0
- package/declarations/addon/plugins/variable-plugin/utils/codelist-utils.d.ts +10 -0
- package/declarations/addon/utils/document-structure-utils.d.ts +6 -0
- package/package.json +3 -3
- package/translations/en-US.yaml +5 -1
- 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
|
-
<
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
</
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
|
107
|
-
result:
|
|
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 =
|
|
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
|
|
23
|
+
const { schema } = args;
|
|
24
24
|
const attrs = createClassicLocationVariableAttrs(args);
|
|
25
|
-
return schema.nodes.
|
|
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> {
|
|
@@ -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[];
|
package/declarations/addon/plugins/variable-plugin/actions/create-classic-location-variable.d.ts
CHANGED
|
@@ -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
|
|
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;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lblod/ember-rdfa-editor-lblod-plugins",
|
|
3
|
-
"version": "
|
|
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": "^
|
|
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",
|
package/translations/en-US.yaml
CHANGED
|
@@ -208,7 +208,7 @@ variable:
|
|
|
208
208
|
multi-select: Multiple selection
|
|
209
209
|
label: codelist
|
|
210
210
|
location:
|
|
211
|
-
label:
|
|
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
|
package/translations/nl-BE.yaml
CHANGED
|
@@ -212,7 +212,7 @@ variable:
|
|
|
212
212
|
multi-select: Meervoudige selectie
|
|
213
213
|
label: codelijst
|
|
214
214
|
location:
|
|
215
|
-
label:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
452
|
+
labelPlaceholder: Vul in…
|
|
449
453
|
default-label: locatie
|
|
450
454
|
map:
|
|
451
455
|
hint:
|