@lblod/ember-rdfa-editor-lblod-plugins 19.2.0 → 19.3.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 (62) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/addon/components/location-plugin/edit.gts +198 -106
  3. package/addon/components/location-plugin/insert.gts +167 -35
  4. package/addon/components/location-plugin/map.gts +131 -0
  5. package/addon/components/location-plugin/nodeview.gts +67 -0
  6. package/addon/components/snippet-plugin/nodes/placeholder.gts +27 -1
  7. package/addon/components/snippet-plugin/snippet-insert-placeholder.gts +6 -2
  8. package/addon/components/snippet-plugin/snippet-list/snippet-list-modal.ts +10 -2
  9. package/addon/components/snippet-plugin/snippet-list-select-rdfa.ts +5 -3
  10. package/addon/components/variable-plugin/address/nodeview.ts +1 -0
  11. package/addon/components/variable-plugin/date/nodeview.ts +3 -0
  12. package/addon/components/variable-plugin/location/nodeview.ts +3 -0
  13. package/addon/components/variable-plugin/number/nodeview.ts +1 -0
  14. package/addon/components/variable-plugin/text/insert.ts +3 -1
  15. package/addon/components/variable-plugin/variable/nodeview.ts +3 -0
  16. package/addon/plugins/location-plugin/node-contents/address.ts +203 -0
  17. package/addon/plugins/location-plugin/node-contents/index.ts +40 -0
  18. package/addon/plugins/location-plugin/node-contents/place.ts +57 -0
  19. package/addon/plugins/location-plugin/node-contents/point.ts +75 -0
  20. package/addon/plugins/location-plugin/node.ts +210 -0
  21. package/addon/plugins/location-plugin/utils/address-helpers.ts +87 -98
  22. package/addon/plugins/location-plugin/utils/geo-helpers.ts +152 -0
  23. package/addon/plugins/location-plugin/utils/node-utils.ts +1 -1
  24. package/addon/plugins/snippet-plugin/commands/index.ts +1 -1
  25. package/addon/plugins/snippet-plugin/commands/update-snippet-ids.ts +12 -2
  26. package/addon/plugins/snippet-plugin/nodes/snippet-placeholder.ts +12 -2
  27. package/addon/plugins/variable-plugin/recreateUuidsOnPaste.ts +95 -0
  28. package/addon/plugins/variable-plugin/variables/address.ts +1 -1
  29. package/addon/utils/constants.ts +1 -0
  30. package/app/styles/location-plugin.scss +27 -0
  31. package/app/styles/variable-plugin.scss +3 -2
  32. package/declarations/addon/components/location-plugin/edit.d.ts +18 -9
  33. package/declarations/addon/components/location-plugin/insert.d.ts +20 -5
  34. package/declarations/addon/components/location-plugin/map.d.ts +25 -0
  35. package/declarations/addon/components/location-plugin/nodeview.d.ts +10 -9
  36. package/declarations/addon/components/snippet-plugin/nodes/placeholder.d.ts +5 -0
  37. package/declarations/addon/components/snippet-plugin/snippet-insert-placeholder.d.ts +1 -1
  38. package/declarations/addon/components/snippet-plugin/snippet-list/snippet-list-modal.d.ts +1 -1
  39. package/declarations/addon/components/snippet-plugin/snippet-list-select-rdfa.d.ts +1 -1
  40. package/declarations/addon/plugins/location-plugin/node-contents/address.d.ts +6 -0
  41. package/declarations/addon/plugins/location-plugin/node-contents/index.d.ts +22 -0
  42. package/declarations/addon/plugins/location-plugin/node-contents/place.d.ts +4 -0
  43. package/declarations/addon/plugins/location-plugin/node-contents/point.d.ts +6 -0
  44. package/declarations/addon/plugins/location-plugin/node.d.ts +7 -0
  45. package/declarations/addon/plugins/location-plugin/utils/address-helpers.d.ts +23 -30
  46. package/declarations/addon/plugins/location-plugin/utils/geo-helpers.d.ts +69 -0
  47. package/declarations/addon/plugins/snippet-plugin/commands/index.d.ts +1 -1
  48. package/declarations/addon/plugins/snippet-plugin/commands/update-snippet-ids.d.ts +5 -2
  49. package/declarations/addon/plugins/snippet-plugin/nodes/snippet-placeholder.d.ts +1 -1
  50. package/declarations/addon/plugins/variable-plugin/recreateUuidsOnPaste.d.ts +3 -0
  51. package/declarations/addon/utils/constants.d.ts +1 -0
  52. package/package.json +9 -4
  53. package/pnpm-lock.yaml +171 -4
  54. package/translations/en-US.yaml +42 -1
  55. package/translations/nl-BE.yaml +43 -1
  56. package/types/ember-leaflet.d.ts +78 -0
  57. package/addon/components/location-plugin/insert-variable.gts +0 -67
  58. package/addon/components/location-plugin/nodeview.hbs +0 -20
  59. package/addon/components/location-plugin/nodeview.ts +0 -49
  60. package/addon/plugins/location-plugin/address.ts +0 -405
  61. package/declarations/addon/components/location-plugin/insert-variable.d.ts +0 -17
  62. package/declarations/addon/plugins/location-plugin/address.d.ts +0 -2
@@ -6,6 +6,7 @@ import { tracked } from '@glimmer/tracking';
6
6
  import not from 'ember-truth-helpers/helpers/not';
7
7
  import IntlService from 'ember-intl/services/intl';
8
8
  import t from 'ember-intl/helpers/t';
9
+ import { trackedReset } from 'tracked-toolbox';
9
10
  import AuButton from '@appuniversum/ember-appuniversum/components/au-button';
10
11
  import AuModal from '@appuniversum/ember-appuniversum/components/au-modal';
11
12
  import AuLoader from '@appuniversum/ember-appuniversum/components/au-loader';
@@ -14,56 +15,142 @@ import { NodeSelection, SayController } from '@lblod/ember-rdfa-editor';
14
15
  import { ResolvedPNode } from '@lblod/ember-rdfa-editor/utils/_private/types';
15
16
 
16
17
  import { Address } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/location-plugin/utils/address-helpers';
18
+ import {
19
+ convertWGS84CoordsToLambert,
20
+ GeoPos,
21
+ type GlobalCoordinates,
22
+ Place,
23
+ Point,
24
+ } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/location-plugin/utils/geo-helpers';
17
25
  import { replaceSelectionWithAddress } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/location-plugin/utils/node-utils';
26
+ import { type LocationPluginConfig } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/location-plugin/node';
27
+ import { NodeContentsUtils } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/location-plugin/node-contents';
18
28
  import Edit from './edit';
29
+ import LocationMap, { type LocationType } from './map';
30
+
31
+ export type CurrentLocation = Address | GlobalCoordinates | undefined;
19
32
 
20
33
  interface Signature {
21
34
  Args: {
22
35
  controller: SayController;
36
+ config: LocationPluginConfig;
23
37
  defaultMunicipality?: string;
24
38
  };
25
39
  Element: HTMLLIElement;
26
40
  }
27
41
 
28
- export default class InsertAddressComponent extends Component<Signature> {
42
+ export default class LocationPluginInsertComponent extends Component<Signature> {
29
43
  @service declare intl: IntlService;
30
44
  @tracked modalOpen = false;
31
- @tracked addressToInsert?: Address;
45
+ @tracked chosenPoint: GeoPos | undefined;
32
46
  @tracked isLoading = false;
33
47
 
48
+ @trackedReset({
49
+ memo: 'selectedLocationNode',
50
+ update(component: LocationPluginInsertComponent) {
51
+ const currentLocation = component.selectedLocationNode?.value.attrs
52
+ .value as Address | Place | null;
53
+ return currentLocation instanceof Address ? currentLocation : undefined;
54
+ },
55
+ })
56
+ addressToInsert?: Address;
57
+
58
+ @trackedReset({
59
+ memo: 'selectedLocationNode',
60
+ update(component: LocationPluginInsertComponent) {
61
+ const currentLocation = component.selectedLocationNode?.value.attrs
62
+ .value as Address | Place | null;
63
+ return currentLocation instanceof Place
64
+ ? currentLocation.location.location
65
+ : undefined;
66
+ },
67
+ })
68
+ savedLocation: GeoPos | undefined;
69
+
70
+ @trackedReset({
71
+ memo: 'selectedLocationNode',
72
+ update(component: LocationPluginInsertComponent) {
73
+ const currentLocation = component.selectedLocationNode?.value.attrs
74
+ .value as Address | Place | null;
75
+ return currentLocation instanceof Place ? currentLocation.name : '';
76
+ },
77
+ })
78
+ placeName: string = '';
79
+
80
+ @trackedReset({
81
+ memo: 'selectedLocationNode',
82
+ update(component: LocationPluginInsertComponent) {
83
+ const currentLocation = component.selectedLocationNode?.value.attrs
84
+ .value as Address | Place | null;
85
+ return currentLocation instanceof Place ? 'place' : 'address';
86
+ },
87
+ })
88
+ locationType: LocationType = 'address';
89
+
90
+ @trackedReset({
91
+ memo: 'controller.activeEditorState',
92
+ update(component: LocationPluginInsertComponent) {
93
+ const { selection, schema } = component.controller.activeEditorState;
94
+ if (
95
+ selection instanceof NodeSelection &&
96
+ selection.node.type === schema.nodes.oslo_location
97
+ ) {
98
+ return { value: selection.node, pos: selection.from };
99
+ }
100
+ return null;
101
+ },
102
+ })
103
+ selectedLocationNode: ResolvedPNode | null = null;
104
+
34
105
  get controller() {
35
106
  return this.args.controller;
36
107
  }
37
108
 
109
+ get nodeContentsUtils() {
110
+ return new NodeContentsUtils(this.args.config);
111
+ }
112
+
38
113
  get documentLanguage() {
39
114
  return this.controller.documentLanguage;
40
115
  }
41
116
 
42
117
  get modalTitle() {
43
- return this.selectedAddressVariable
118
+ return this.selectedLocationNode
44
119
  ? this.intl.t('location-plugin.modal.edit')
45
120
  : this.intl.t('location-plugin.modal.insert');
46
121
  }
47
122
 
48
- get selectedAddressVariable(): ResolvedPNode | null {
49
- const { selection, schema } = this.controller.activeEditorState;
50
- if (
51
- selection instanceof NodeSelection &&
52
- selection.node.type === schema.nodes.address
53
- ) {
54
- return { value: selection.node, pos: selection.from };
55
- }
56
- return null;
123
+ get canInsert() {
124
+ return !!this.controller.activeEditorView.props.nodeViews?.oslo_location;
57
125
  }
58
126
 
59
- get canInsertAddress() {
60
- if (this.controller.activeEditorView.props.nodeViews?.address) {
61
- return true;
127
+ get disableConfirm() {
128
+ if (this.locationType === 'place') {
129
+ return !this.selectedLocationNode || !this.placeName || !this.chosenPoint;
62
130
  } else {
63
- return false;
131
+ return !this.selectedLocationNode || !this.addressToInsert;
64
132
  }
65
133
  }
66
134
 
135
+ @action
136
+ setLocationType(type: LocationType) {
137
+ this.locationType = type;
138
+ }
139
+
140
+ @action
141
+ setChosenPoint(point: GlobalCoordinates) {
142
+ // Since we only use the global coordinates, we don't have to do a conversion to lambert here
143
+ this.chosenPoint = {
144
+ lambert: { x: 0, y: 0 },
145
+ global: point,
146
+ };
147
+ }
148
+
149
+ @action
150
+ setPlaceName(name: string) {
151
+ this.placeName = name;
152
+ }
153
+
67
154
  @action
68
155
  closeModal() {
69
156
  this.modalOpen = false;
@@ -71,7 +158,7 @@ export default class InsertAddressComponent extends Component<Signature> {
71
158
 
72
159
  @action
73
160
  insertOrEditAddress() {
74
- if (!this.selectedAddressVariable) {
161
+ if (!this.selectedLocationNode) {
75
162
  replaceSelectionWithAddress(
76
163
  this.controller,
77
164
  this.intl.t('location-plugin.default-label', {
@@ -93,13 +180,40 @@ export default class InsertAddressComponent extends Component<Signature> {
93
180
  }
94
181
 
95
182
  @action
96
- setAddress() {
97
- if (this.selectedAddressVariable && this.addressToInsert) {
98
- const { pos } = this.selectedAddressVariable;
99
- this.controller.withTransaction((tr) => {
100
- return tr.setNodeAttribute(pos, 'value', this.addressToInsert);
101
- });
102
- this.modalOpen = false;
183
+ confirmLocation() {
184
+ if (this.selectedLocationNode) {
185
+ let toInsert: Address | Place | undefined;
186
+ const { pos } = this.selectedLocationNode;
187
+ if (this.locationType === 'address' && this.addressToInsert) {
188
+ toInsert = this.addressToInsert;
189
+ this.controller.withTransaction((tr) => {
190
+ return tr.setNodeAttribute(pos, 'value', toInsert);
191
+ });
192
+ this.modalOpen = false;
193
+ } else if (
194
+ this.locationType === 'place' &&
195
+ this.chosenPoint?.global &&
196
+ this.placeName
197
+ ) {
198
+ convertWGS84CoordsToLambert(this.chosenPoint.global).then((lambert) => {
199
+ toInsert = new Place({
200
+ uri: this.nodeContentsUtils.fallbackPlaceUri(),
201
+ name: this.placeName,
202
+ location: new Point({
203
+ uri: this.nodeContentsUtils.fallbackPointUri(),
204
+ location: {
205
+ lambert,
206
+ global: this.chosenPoint?.global,
207
+ },
208
+ }),
209
+ });
210
+ this.controller.withTransaction((tr) => {
211
+ return tr.setNodeAttribute(pos, 'value', toInsert);
212
+ });
213
+ this.modalOpen = false;
214
+ this.chosenPoint = undefined;
215
+ });
216
+ }
103
217
  }
104
218
  }
105
219
 
@@ -110,9 +224,9 @@ export default class InsertAddressComponent extends Component<Signature> {
110
224
  @iconAlignment='left'
111
225
  @skin='link'
112
226
  {{on 'click' this.insertOrEditAddress}}
113
- @disabled={{not this.canInsertAddress}}
227
+ @disabled={{not this.canInsert}}
114
228
  >
115
- {{#if this.selectedAddressVariable}}
229
+ {{#if this.selectedLocationNode}}
116
230
  {{t 'location-plugin.modal.edit'}}
117
231
  {{else}}
118
232
  {{t 'location-plugin.modal.insert'}}
@@ -120,24 +234,42 @@ export default class InsertAddressComponent extends Component<Signature> {
120
234
  </AuButton>
121
235
  </li>
122
236
  <AuModal
237
+ class='location-modal'
123
238
  @modalOpen={{this.modalOpen}}
124
239
  @closeModal={{this.closeModal}}
125
240
  @title={{this.modalTitle}}
241
+ @size='large'
126
242
  as |modal|
127
243
  >
128
244
  <modal.Body>
129
- <Edit
130
- @controller={{@controller}}
131
- @selectedAddressVariable={{this.selectedAddressVariable}}
132
- @setAddressToInsert={{this.setAddressToInsert}}
133
- @setIsLoading={{this.setIsLoading}}
134
- @defaultMunicipality={{@defaultMunicipality}}
135
- />
245
+ <div class='au-o-grid au-o-grid--tiny'>
246
+ <div class='edit-form au-o-grid__item au-u-1-2@small'>
247
+ <Edit
248
+ @locationType={{this.locationType}}
249
+ @setLocationType={{this.setLocationType}}
250
+ @selectedLocationNode={{this.selectedLocationNode}}
251
+ @setAddressToInsert={{this.setAddressToInsert}}
252
+ @setIsLoading={{this.setIsLoading}}
253
+ @defaultMunicipality={{@defaultMunicipality}}
254
+ @placeName={{this.placeName}}
255
+ @setPlaceName={{this.setPlaceName}}
256
+ @nodeContentsUtils={{this.nodeContentsUtils}}
257
+ />
258
+ </div>
259
+ <LocationMap
260
+ class='au-o-grid__item au-u-1-2@small au-o-box-large'
261
+ @address={{this.addressToInsert}}
262
+ @locationType={{this.locationType}}
263
+ @location={{this.chosenPoint}}
264
+ @existingLocation={{this.savedLocation}}
265
+ @setLocation={{this.setChosenPoint}}
266
+ />
267
+ </div>
136
268
  </modal.Body>
137
269
  <modal.Footer>
138
270
  <AuButton
139
- @disabled={{(not this.addressToInsert)}}
140
- {{on 'click' this.setAddress}}
271
+ @disabled={{this.disableConfirm}}
272
+ {{on 'click' this.confirmLocation}}
141
273
  >
142
274
  {{#if this.isLoading}}
143
275
  <AuLoader @hideMessage={{true}} @inline={{true}}>
@@ -0,0 +1,131 @@
1
+ import Component from '@glimmer/component';
2
+ import { action } from '@ember/object';
3
+ import { tracked } from '@glimmer/tracking';
4
+ import and from 'ember-truth-helpers/helpers/and';
5
+ import eq from 'ember-truth-helpers/helpers/eq';
6
+ import t from 'ember-intl/helpers/t';
7
+ import { LeafletMap } from 'ember-leaflet';
8
+ import { type LeafletMouseEvent } from 'leaflet';
9
+ import { restartableTask } from 'ember-concurrency';
10
+ import { task as trackedTask } from 'ember-resources/util/ember-concurrency';
11
+ import AuLoader from '@appuniversum/ember-appuniversum/components/au-loader';
12
+ import { Address } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/location-plugin/utils/address-helpers';
13
+ import {
14
+ convertLambertCoordsToWGS84,
15
+ GeoPos,
16
+ type GlobalCoordinates,
17
+ } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/location-plugin/utils/geo-helpers';
18
+
19
+ export type LocationType = 'address' | 'place';
20
+
21
+ const COORD_SYSTEM_CENTER: GlobalCoordinates = {
22
+ lng: 4.450822554431,
23
+ lat: 50.50526730529,
24
+ };
25
+
26
+ function displayLocation(location: GeoPos | undefined) {
27
+ const { lambert } = location ?? {};
28
+ return lambert
29
+ ? `[x: ${lambert.x.toFixed(2)}, y: ${lambert.y.toFixed(2)}]`
30
+ : '';
31
+ }
32
+
33
+ interface Signature {
34
+ Args: {
35
+ address: Address | undefined;
36
+ locationType: LocationType;
37
+ location?: GeoPos;
38
+ setLocation: (loc: GlobalCoordinates) => void;
39
+ existingLocation?: GeoPos;
40
+ };
41
+ Element: HTMLElement;
42
+ }
43
+
44
+ async function ensureGlobalCoordinates(geoPos: GeoPos) {
45
+ if (geoPos.global) {
46
+ return geoPos.global;
47
+ }
48
+ return await convertLambertCoordsToWGS84(geoPos.lambert);
49
+ }
50
+
51
+ export default class LocationPluginMapComponent extends Component<Signature> {
52
+ @tracked mapCenter = COORD_SYSTEM_CENTER;
53
+ @tracked zoom = 7;
54
+ @tracked existingLocationCoords: GlobalCoordinates | undefined;
55
+
56
+ addressLatLngLookup = restartableTask(
57
+ async (): Promise<GlobalCoordinates | undefined> => {
58
+ const { address, existingLocation } = this.args;
59
+ if (address) {
60
+ this.mapCenter = await ensureGlobalCoordinates(
61
+ address.location.location,
62
+ );
63
+ this.zoom = 19;
64
+ } else if (existingLocation) {
65
+ this.mapCenter = await ensureGlobalCoordinates(existingLocation);
66
+ this.existingLocationCoords = this.mapCenter;
67
+ this.zoom = 19;
68
+ }
69
+ return COORD_SYSTEM_CENTER;
70
+ },
71
+ );
72
+ addressLatLng = trackedTask<GlobalCoordinates | undefined>(
73
+ this,
74
+ this.addressLatLngLookup,
75
+ () => [this.args.address, this.args.existingLocation],
76
+ );
77
+
78
+ get doRenderMap() {
79
+ return this.addressLatLng.value && this.zoom;
80
+ }
81
+
82
+ @action
83
+ onMapClick(event: LeafletMouseEvent) {
84
+ if (this.args.locationType === 'place') {
85
+ this.args.setLocation(event.latlng);
86
+ }
87
+ }
88
+
89
+ <template>
90
+ <div class='map-wrapper' ...attributes>
91
+ {{#if this.addressLatLng.isRunning}}
92
+ <AuLoader @hideMessage={{true}}>
93
+ {{t 'common.initialBounds.loading'}}
94
+ </AuLoader>
95
+ {{else if this.addressLatLng.value}}
96
+ <LeafletMap
97
+ @center={{this.mapCenter}}
98
+ @zoom={{this.zoom}}
99
+ @onClick={{this.onMapClick}}
100
+ as |layers|
101
+ >
102
+ <layers.tile
103
+ @url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'
104
+ @attribution='&copy; <a target="_blank" href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
105
+ />
106
+ {{#if (and @address (eq @locationType 'address'))}}
107
+ <layers.marker @location={{this.mapCenter}} as |marker|>
108
+ <marker.popup>
109
+ {{@address.formatted}}
110
+ </marker.popup>
111
+ </layers.marker>
112
+ {{/if}}
113
+ {{#if this.existingLocationCoords}}
114
+ <layers.marker
115
+ @opacity={{if @location 0.3 1}}
116
+ @location={{this.existingLocationCoords}}
117
+ as |marker|
118
+ >
119
+ <marker.popup>
120
+ {{displayLocation @existingLocation}}
121
+ </marker.popup>
122
+ </layers.marker>
123
+ {{/if}}
124
+ {{#if (and @location (eq @locationType 'place'))}}
125
+ <layers.marker @location={{@location.global}} />
126
+ {{/if}}
127
+ </LeafletMap>
128
+ {{/if}}
129
+ </div>
130
+ </template>
131
+ }
@@ -0,0 +1,67 @@
1
+ import Component from '@glimmer/component';
2
+ import { service } from '@ember/service';
3
+ import { on } from '@ember/modifier';
4
+ import IntlService from 'ember-intl/services/intl';
5
+ import { PencilIcon } from '@appuniversum/ember-appuniversum/components/icons/pencil';
6
+ import AuPill, {
7
+ type AuPillSignature,
8
+ } from '@appuniversum/ember-appuniversum/components/au-pill';
9
+
10
+ import { PNode, SayController } from '@lblod/ember-rdfa-editor';
11
+ import { Address } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/location-plugin/utils/address-helpers';
12
+ import { getOutgoingTriple } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/namespace';
13
+ import { EXT } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
14
+
15
+ type Signature = {
16
+ Args: {
17
+ selectNode: () => void;
18
+ getPos: () => number | undefined;
19
+ node: PNode;
20
+ controller: SayController;
21
+ };
22
+ Element: AuPillSignature['Element'];
23
+ };
24
+
25
+ export default class AddressNodeviewComponent extends Component<Signature> {
26
+ @service declare intl: IntlService;
27
+
28
+ get translations() {
29
+ return {
30
+ placeholder: this.intl.t('editor-plugins.address.nodeview.placeholder', {
31
+ locale: this.args.controller.documentLanguage,
32
+ }),
33
+ };
34
+ }
35
+
36
+ get address() {
37
+ return this.args.node.attrs.value as Address | null;
38
+ }
39
+
40
+ get label() {
41
+ if (this.address) return '';
42
+ return getOutgoingTriple(this.args.node.attrs, EXT('label'))?.object.value;
43
+ }
44
+
45
+ <template>
46
+ <AuPill
47
+ class='variable atomic'
48
+ @icon={{PencilIcon}}
49
+ @iconAlignment='right'
50
+ ...attributes
51
+ {{on 'click' @selectNode}}
52
+ >
53
+ {{#if this.address}}
54
+ {{this.address.formatted}}
55
+ {{else}}
56
+ <span class='mark-highlight-manual'>
57
+ {{this.translations.placeholder}}
58
+ </span>
59
+ {{/if}}
60
+ {{#if this.label}}
61
+ <span class='label'>
62
+ ({{this.label}})
63
+ </span>
64
+ {{/if}}
65
+ </AuPill>
66
+ </template>
67
+ }
@@ -4,6 +4,8 @@ import t from 'ember-intl/helpers/t';
4
4
  import AuAlert from '@appuniversum/ember-appuniversum/components/au-alert';
5
5
  import { PlusTextIcon } from '@appuniversum/ember-appuniversum/components/icons/plus-text';
6
6
  import { type EmberNodeArgs } from '@lblod/ember-rdfa-editor/utils/_private/ember-node';
7
+ import { service } from '@ember/service';
8
+ import IntlService from 'ember-intl/services/intl';
7
9
 
8
10
  interface Signature {
9
11
  Args: EmberNodeArgs;
@@ -13,15 +15,39 @@ interface Signature {
13
15
  // class to allow for type checking
14
16
  // eslint-disable-next-line ember/no-empty-glimmer-component-classes
15
17
  export default class SnippetPluginPlaceholder extends Component<Signature> {
18
+ @service declare intl: IntlService;
19
+ get listNames() {
20
+ return this.args.node.attrs.listNames;
21
+ }
22
+ get isSingleList() {
23
+ return this.listNames.length === 1;
24
+ }
25
+ get alertTitle() {
26
+ if (this.isSingleList) {
27
+ return this.intl.t('snippet-plugin.placeholder.title-single', {
28
+ listName: this.listNames[0],
29
+ });
30
+ } else {
31
+ return this.intl.t('snippet-plugin.placeholder.title-multiple');
32
+ }
33
+ }
16
34
  <template>
17
35
  <AuAlert
18
- @title={{t 'snippet-plugin.placeholder.title'}}
36
+ @title={{this.alertTitle}}
19
37
  @skin='warning'
20
38
  @icon={{PlusTextIcon}}
21
39
  @size='small'
22
40
  class='say-snippet-placeholder'
23
41
  {{on 'click' @selectNode}}
24
42
  >
43
+ {{#unless this.isSingleList}}
44
+ {{t 'snippet-plugin.placeholder.active-lists'}}
45
+ <ul>
46
+ {{#each this.listNames as |listName|}}
47
+ <li>{{listName}}</li>
48
+ {{/each}}
49
+ </ul>
50
+ {{/unless}}
25
51
  {{t 'snippet-plugin.placeholder.text'}}
26
52
  </AuAlert>
27
53
  </template>
@@ -35,8 +35,12 @@ export default class SnippetPluginSnippetInsertPlaceholder extends Component<Sig
35
35
  }
36
36
 
37
37
  @action
38
- insertPlaceholder(listIds: string[]) {
39
- const node = createSnippetPlaceholder(listIds, this.args.controller.schema);
38
+ insertPlaceholder(listIds: string[], listNames: string[]) {
39
+ const node = createSnippetPlaceholder(
40
+ listIds,
41
+ listNames,
42
+ this.args.controller.schema,
43
+ );
40
44
 
41
45
  this.args.controller.withTransaction(
42
46
  (tr) => {
@@ -19,7 +19,7 @@ import { trackedReset } from 'tracked-toolbox';
19
19
  interface Signature {
20
20
  Args: {
21
21
  config: SnippetPluginConfig;
22
- onSaveSnippetListIds: (listIds: string[]) => void;
22
+ onSaveSnippetListIds: (listIds: string[], listNames: string[]) => void;
23
23
  assignedSnippetListsIds: string[];
24
24
  closeModal: () => void;
25
25
  open: boolean;
@@ -50,7 +50,15 @@ export default class SnippetListModalComponent extends Component<Signature> {
50
50
 
51
51
  @action
52
52
  saveAndClose() {
53
- this.args.onSaveSnippetListIds(this.assignedSnippetListsIds);
53
+ const snippetListNames: string[] = this.snippetListResource.value
54
+ ?.filter((snippetList) =>
55
+ this.assignedSnippetListsIds.includes(snippetList.id as string),
56
+ )
57
+ .map((snippetList) => snippetList.label) as string[];
58
+ this.args.onSaveSnippetListIds(
59
+ this.assignedSnippetListsIds,
60
+ snippetListNames,
61
+ );
54
62
  this.args.closeModal();
55
63
  // Clear selection for next time
56
64
  this.assignedSnippetListsIds = [];
@@ -7,7 +7,7 @@ import {
7
7
  getAssignedSnippetListsIdsFromProperties,
8
8
  getSnippetListIdsProperties,
9
9
  } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/snippet-plugin/utils/rdfa-predicate';
10
- import { updateSnippetIds } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/snippet-plugin/commands';
10
+ import { updateSnippetPlaceholder } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/snippet-plugin/commands';
11
11
  import { ResolvedPNode } from '@lblod/ember-rdfa-editor/utils/_private/types';
12
12
  import { SayController } from '@lblod/ember-rdfa-editor';
13
13
  import { OutgoingTriple } from '@lblod/ember-rdfa-editor/core/rdfa-processor';
@@ -49,13 +49,15 @@ export default class SnippetListSelectRdfaComponent extends Component<Args> {
49
49
  );
50
50
  }
51
51
 
52
- saveChanges = (snippetIds: string[]) => {
52
+ saveChanges = (snippetIds: string[], snippetNames: string[]) => {
53
53
  if (this.currentResource) {
54
54
  this.args.controller?.doCommand(
55
- updateSnippetIds({
55
+ updateSnippetPlaceholder({
56
56
  resource: this.currentResource,
57
57
  oldSnippetProperties: this.snippetListIdsProperties ?? [],
58
58
  newSnippetIds: snippetIds,
59
+ node: this.node,
60
+ snippetNames,
59
61
  }),
60
62
  {
61
63
  view: this.args.controller.mainEditorView,
@@ -44,6 +44,7 @@ export default class AddressNodeviewComponent extends Component<Args> {
44
44
  }
45
45
 
46
46
  get label() {
47
+ if (this.address) return '';
47
48
  return getOutgoingTriple(this.node.attrs, EXT('label'))?.object.value;
48
49
  }
49
50
  }
@@ -60,6 +60,9 @@ export default class DateNodeviewComponent extends Component<Args> {
60
60
  }
61
61
 
62
62
  get label() {
63
+ const value = getOutgoingTriple(this.args.node.attrs, EXT('content'))
64
+ ?.object.value;
65
+ if (value) return '';
63
66
  return getOutgoingTriple(this.args.node.attrs, EXT('label'))?.object.value;
64
67
  }
65
68
  }
@@ -38,6 +38,9 @@ export default class LocationNodeViewComponent extends Component<EmberNodeArgs>
38
38
  }
39
39
 
40
40
  get label() {
41
+ if (this.innerView?.state.doc.firstChild?.type.name !== 'placeholder') {
42
+ return '';
43
+ }
41
44
  return this.args.node.attrs.label as string;
42
45
  }
43
46
  }
@@ -93,6 +93,7 @@ export default class NumberNodeviewComponent extends Component<Args> {
93
93
  }
94
94
 
95
95
  get label(): string | undefined {
96
+ if (this.inputNumber) return '';
96
97
  return getOutgoingTriple(this.args.node.attrs, EXT('label'))?.object.value;
97
98
  }
98
99
 
@@ -77,7 +77,9 @@ export default class TextVariableInsertComponent extends Component<Args> {
77
77
  },
78
78
  ],
79
79
  },
80
- this.schema.text('text'),
80
+ this.schema.node('placeholder', {
81
+ placeholderText: 'text',
82
+ }),
81
83
  );
82
84
 
83
85
  this.label = undefined;
@@ -41,6 +41,9 @@ export default class VariableNodeViewComponent extends Component<EmberNodeArgs>
41
41
  }
42
42
 
43
43
  get label() {
44
+ if (this.innerView?.state.doc.firstChild?.type.name !== 'placeholder') {
45
+ return '';
46
+ }
44
47
  return getOutgoingTriple(this.args.node.attrs, EXT('label'))?.object.value;
45
48
  }
46
49
  }