@lblod/ember-rdfa-editor-lblod-plugins 37.0.3 → 37.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @lblod/ember-rdfa-editor-lblod-plugins
2
2
 
3
+ ## 37.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#658](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/pull/658) [`e45764c`](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/commit/e45764c5f10e590963307a00b93501ec99b5b8ac) Thanks [@kobemertens](https://github.com/kobemertens)! - Integrate location suggestions in context menu
8
+
9
+ ### Patch Changes
10
+
11
+ - [#660](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/pull/660) [`062a3f9`](https://github.com/lblod/ember-rdfa-editor-lblod-plugins/commit/062a3f92528e0db450aaa51853197759650d85ed) Thanks [@lagartoverde](https://github.com/lagartoverde)! - Fetch document content before passing it up on the document template component in order to solve race condition on GN
12
+
3
13
  ## 37.0.3
4
14
 
5
15
  ### Patch Changes
@@ -14,6 +14,7 @@ import t from 'ember-intl/helpers/t';
14
14
  import { SayController } from '@lblod/ember-rdfa-editor';
15
15
  import { PreviewableDocument } from './types';
16
16
  import { VoteStarUnfilledIcon } from '../vote-star-unfilled-icon';
17
+ import perform from 'ember-concurrency/helpers/perform';
17
18
 
18
19
  interface Signature<Doc extends PreviewableDocument> {
19
20
  Args: {
@@ -31,10 +32,10 @@ export default class DocumentPreview<
31
32
  @tracked controller?: SayController;
32
33
  @tracked isExpanded = false;
33
34
 
34
- @action
35
- onInsert() {
35
+ onInsert = task(async () => {
36
+ await this.contentTask.perform();
36
37
  this.args.onInsert(this.args.doc);
37
- }
38
+ });
38
39
 
39
40
  @action
40
41
  togglePreview() {
@@ -101,7 +102,7 @@ export default class DocumentPreview<
101
102
  <div
102
103
  role='button'
103
104
  title={{t 'common.preview-list.select-button.title'}}
104
- {{on 'click' this.onInsert}}
105
+ {{on 'click' (perform this.onInsert)}}
105
106
  {{! template-lint-disable require-presentational-children}}
106
107
  >
107
108
  <AuButton class='snippet-preview__insert-button' @skin='naked'>
@@ -31,18 +31,14 @@ import LocationMap, {
31
31
  SUPPORTED_LOCATION_TYPES,
32
32
  type LocationType,
33
33
  } from './map';
34
- import { transactionCombinator } from '@lblod/ember-rdfa-editor/utils/transaction-utils';
35
- import { updateSubject } from '@lblod/ember-rdfa-editor/plugins/rdfa-info/utils';
36
34
  import { replaceSelectionWithLocation } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/location-plugin/_private/utils/node-utils';
37
35
  import type { Option } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/option';
38
- import type { FullTriple } from '@lblod/ember-rdfa-editor/core/rdfa-processor';
39
- import { PROV } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
40
- import { SayDataFactory } from '@lblod/ember-rdfa-editor/core/say-data-factory';
41
36
  import {
42
37
  closeLocationModal,
43
38
  getLocationModalsPluginState,
44
39
  openLocationModal,
45
40
  } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/location-plugin';
41
+ import { replaceLocationCommand } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/location-plugin/utils/replace-location';
46
42
 
47
43
  export type CurrentLocation = Address | GlobalCoordinates | undefined;
48
44
 
@@ -282,51 +278,23 @@ export default class LocationPluginInsertComponent extends Component<Signature>
282
278
  }),
283
279
  });
284
280
  }
285
- if (toInsert) {
286
- closeLocationModal(this.controller.activeEditorView);
287
- if (this.selectedLocationNode) {
288
- const df = new SayDataFactory();
289
- const { pos, value: locNode } = this.selectedLocationNode;
290
- // The location's subject has likely changed, so we should update the external links too
291
- // if they exist
292
- // NOTE: It's VERY important that this is done without mutating the triple objects
293
- // otherwise the attributes will not update as expected when undo-ing
294
- const newExternalTriples: FullTriple[] = (
295
- locNode.attrs.externalTriples as FullTriple[]
296
- ).map((tr) => {
297
- if (PROV('atLocation').matches(tr.predicate)) {
298
- return { ...tr, object: df.namedNode(toInsert.uri) };
299
- } else {
300
- return tr;
301
- }
302
- }); // update the location value and the external triples
303
- this.controller.withTransaction((tr) => {
304
- return transactionCombinator(
305
- this.controller.activeEditorState,
306
- tr
307
- .setNodeAttribute(pos, 'value', toInsert)
308
- .setNodeAttribute(pos, 'externalTriples', newExternalTriples),
309
- )([
310
- // Update the subject uri, while keeping backlinks intact
311
- updateSubject({
312
- pos,
313
- targetSubject: toInsert.uri,
314
- keepBacklinks: true,
315
- keepProperties: false,
316
- keepExternalTriples: true,
317
- }),
318
- ]).transaction;
319
- });
320
- } else {
321
- // Insert
322
- replaceSelectionWithLocation({
323
- controller: this.controller,
324
- subject: toInsert.uri,
325
- toInsert,
326
- subjectTypes: this.args.config.subjectTypesToLinkTo,
327
- explicitSubjectToLinkTo: this.args.config.explicitSubjectToLinkTo,
328
- });
329
- }
281
+ if (!toInsert) return;
282
+
283
+ closeLocationModal(this.controller.activeEditorView);
284
+ if (this.selectedLocationNode) {
285
+ replaceLocationCommand(this.selectedLocationNode, toInsert)(
286
+ this.controller.activeEditorState,
287
+ this.controller.activeEditorView.dispatch,
288
+ );
289
+ } else {
290
+ // Insert
291
+ replaceSelectionWithLocation({
292
+ controller: this.controller,
293
+ subject: toInsert.uri,
294
+ toInsert,
295
+ subjectTypes: this.args.config.subjectTypesToLinkTo,
296
+ explicitSubjectToLinkTo: this.args.config.explicitSubjectToLinkTo,
297
+ });
330
298
  }
331
299
  }
332
300
 
@@ -0,0 +1,7 @@
1
+ import { Address } from './address-helpers';
2
+ import { Area, Place } from './geo-helpers';
3
+
4
+ // For 2 addresses that are the same, the belgianAddressUri will be the same, regardless of how they were created
5
+ export function getLocationUri(location: Address | Place | Area) {
6
+ return (location as Address)?.belgianAddressUri ?? location.uri;
7
+ }
@@ -3,25 +3,57 @@ import { v4 as uuidv4 } from 'uuid';
3
3
  import { getTranslationFunction } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/translation';
4
4
  import { openLocationModalCommand } from '..';
5
5
  import { LocationType } from '@lblod/ember-rdfa-editor-lblod-plugins/components/location-plugin/map';
6
+ import getDocumentLocations from '../utils/get-document-locations';
7
+ import { replaceLocationCommand } from '../utils/replace-location';
8
+ import { Area, Place } from '../utils/geo-helpers';
9
+ import { Address } from '../utils/address-helpers';
10
+ import { getLocationUri } from '../_private/utils/location-helpers';
6
11
 
7
12
  const otherElementsGroupId =
8
13
  'other-elements-e01f46a0-b323-4add-8035-d81dc2e8578d';
14
+ const recentLocationsGroupId =
15
+ 'other-elements-de3e5a9a-40de-4fb5-832e-c22199ec584f';
16
+
17
+ const SUGGESTION_AMOUNT = 15;
9
18
 
10
19
  export function getContextualActions() {
11
20
  return function (state: EditorState, searchQuery?: string) {
12
21
  const t = getTranslationFunction(state);
22
+ const { selection } = state;
23
+ if (!(selection instanceof NodeSelection)) return [];
24
+ const selectedNode = selection.node;
25
+ if (selectedNode.type.name !== 'oslo_location') return [];
26
+
27
+ const selectedLocation = selectedNode.attrs.value as
28
+ | Address
29
+ | Place
30
+ | Area
31
+ | undefined;
32
+
33
+ const locationSuggestionOptions = getDocumentLocations(state)
34
+ .filter(
35
+ (location) =>
36
+ !selectedLocation ||
37
+ getLocationUri(selectedLocation) !== getLocationUri(location),
38
+ )
39
+ .slice(0, SUGGESTION_AMOUNT)
40
+ .map((location) => ({
41
+ label: location.formatted,
42
+ id: uuidv4(),
43
+ group: recentLocationsGroupId,
44
+ command: replaceLocationCommand(
45
+ { value: selection.node, pos: selection.from },
46
+ location,
47
+ ),
48
+ }));
13
49
 
14
- const options: {
15
- label: string;
16
- locationType: LocationType;
17
- icon: string;
18
- }[] = [
50
+ const otherElementsOptions = [
19
51
  {
20
52
  label: t(
21
53
  'location-plugin.context-actions.insert-address',
22
54
  'Adres invoegen',
23
55
  ),
24
- locationType: 'address',
56
+ locationType: 'address' as LocationType,
25
57
  icon: 'location',
26
58
  },
27
59
  {
@@ -29,7 +61,7 @@ export function getContextualActions() {
29
61
  'location-plugin.context-actions.insert-point-on-map',
30
62
  'Punt op de kaart invoegen',
31
63
  ),
32
- locationType: 'place',
64
+ locationType: 'place' as LocationType,
33
65
  icon: 'location-gps',
34
66
  },
35
67
  {
@@ -37,25 +69,25 @@ export function getContextualActions() {
37
69
  'location-plugin.context-actions.insert-area',
38
70
  'Gebied invoegen',
39
71
  ),
40
- locationType: 'area',
72
+ locationType: 'area' as LocationType,
41
73
  icon: 'area',
42
74
  },
43
- ];
75
+ ].map((option) => {
76
+ return {
77
+ ...option,
78
+ id: uuidv4(),
79
+ group: otherElementsGroupId,
80
+ command: openLocationModalCommand(option.locationType),
81
+ };
82
+ });
44
83
 
45
- return options
84
+ return locationSuggestionOptions
85
+ .concat(otherElementsOptions)
46
86
  .filter(
47
87
  (option) =>
48
88
  !searchQuery ||
49
89
  option.label.toLocaleLowerCase().includes(searchQuery.toLowerCase()),
50
- )
51
- .map((option) => {
52
- return {
53
- ...option,
54
- id: uuidv4(),
55
- group: otherElementsGroupId,
56
- command: openLocationModalCommand(option.locationType),
57
- };
58
- });
90
+ );
59
91
  };
60
92
  }
61
93
 
@@ -69,16 +101,23 @@ function contextualGroupIsVisible(state: EditorState) {
69
101
 
70
102
  export function getContextualActionGroups() {
71
103
  return function (state: EditorState) {
72
- return contextualGroupIsVisible(state)
73
- ? [
74
- {
75
- id: otherElementsGroupId,
76
- label: getTranslationFunction(state)(
77
- 'location-plugin.context-actions.other-elements',
78
- 'Andere elementen',
79
- ),
80
- },
81
- ]
82
- : [];
104
+ if (!contextualGroupIsVisible(state)) return [];
105
+ return [
106
+ {
107
+ id: recentLocationsGroupId,
108
+ label: getTranslationFunction(state)(
109
+ 'location-plugin.context-actions.location-suggestions',
110
+ 'Locatiesuggesties',
111
+ ),
112
+ },
113
+ {
114
+ id: otherElementsGroupId,
115
+ label: getTranslationFunction(state)(
116
+ 'location-plugin.context-actions.other-elements',
117
+ 'Andere elementen',
118
+ ),
119
+ sticky: 'bottom',
120
+ },
121
+ ];
83
122
  };
84
123
  }
@@ -3,7 +3,6 @@ import {
3
3
  PluginKey,
4
4
  EditorState,
5
5
  EditorView,
6
- Transaction,
7
6
  Command,
8
7
  } from '@lblod/ember-rdfa-editor';
9
8
  import { LocationType } from '@lblod/ember-rdfa-editor-lblod-plugins/components/location-plugin/map';
@@ -1,6 +1,7 @@
1
1
  import { EditorState } from '@lblod/ember-rdfa-editor';
2
2
  import { Area, Place } from './geo-helpers';
3
3
  import { Address } from './address-helpers';
4
+ import { getLocationUri } from '../_private/utils/location-helpers';
4
5
 
5
6
  type LocationsWithDistanceType = {
6
7
  location: Place | Address | Area;
@@ -8,9 +9,47 @@ type LocationsWithDistanceType = {
8
9
  };
9
10
 
10
11
  type LocationMetadataType = {
11
- [locationUri: string]: { ocurrences: number; distance: number };
12
+ [locationUri: string]: {
13
+ occurrences: number;
14
+ distance: number;
15
+ location: Address | Place | Area;
16
+ };
12
17
  };
13
18
 
19
+ const PROXIMITY_WEIGHT = 0.8;
20
+ const FREQUENCY_WEIGHT = 1 - PROXIMITY_WEIGHT;
21
+ const PROXIMITY_DECAY = 50;
22
+
23
+ /**
24
+ * Returns a frequency score that normalizes logarithmically to avoid domination by a few very large occurences.
25
+ * @param occurences amount of occurences of the location
26
+ * @param maxOccurences max amount of occurences for any location
27
+ */
28
+ function getFrequencyScore(occurences: number, maxOccurences: number) {
29
+ return Math.log(occurences + 1) / Math.log(maxOccurences + 1);
30
+ }
31
+
32
+ /**
33
+ * Uses exponential decay to calculate a proximity score
34
+ * @param distance Distance from the selection
35
+ * @returns proximity score
36
+ */
37
+ function getProximityScore(distance: number) {
38
+ return Math.exp(-distance / PROXIMITY_DECAY);
39
+ }
40
+
41
+ function getSuggestionScore(
42
+ occurrences: number,
43
+ maxOccurences: number,
44
+ distance: number,
45
+ ) {
46
+ const score =
47
+ PROXIMITY_WEIGHT * getProximityScore(distance) +
48
+ FREQUENCY_WEIGHT * getFrequencyScore(occurrences, maxOccurences);
49
+
50
+ return score;
51
+ }
52
+
14
53
  export default function getDocumentLocations(state: EditorState) {
15
54
  const doc = state.doc;
16
55
  const locationsWithDistance: LocationsWithDistanceType[] = [];
@@ -27,37 +66,44 @@ export default function getDocumentLocations(state: EditorState) {
27
66
  return true;
28
67
  });
29
68
  const locationMetadata: LocationMetadataType = {};
30
- const locationsDedup: (Place | Address | Area)[] = [];
31
69
  for (const locationWithDistance of locationsWithDistance) {
32
- const uri =
33
- (locationWithDistance.location as Address).belgianAddressUri ||
34
- locationWithDistance.location.uri;
70
+ const { location, distance } = locationWithDistance;
71
+ if (!location) {
72
+ continue;
73
+ }
74
+ const uri = getLocationUri(location);
35
75
  if (!locationMetadata[uri]) {
36
76
  locationMetadata[uri] = {
37
- ocurrences: 1,
38
- distance: locationWithDistance.distance,
77
+ location,
78
+ occurrences: 1,
79
+ distance,
39
80
  };
40
- locationsDedup.push(locationWithDistance.location);
41
81
  } else {
42
- locationMetadata[uri].ocurrences++;
43
- if (locationWithDistance.distance < locationMetadata[uri].distance) {
44
- locationMetadata[uri].distance = locationWithDistance.distance;
82
+ locationMetadata[uri].occurrences++;
83
+ if (distance < locationMetadata[uri].distance) {
84
+ locationMetadata[uri].distance = distance;
45
85
  }
46
86
  }
47
87
  }
48
88
 
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
- }
89
+ const maxOccurence = Object.values(locationMetadata).reduce(
90
+ (acc, { occurrences: ocurrences }) =>
91
+ acc >= ocurrences ? acc : ocurrences,
92
+ 1,
93
+ );
94
+
95
+ const scoredLocations = Object.values(locationMetadata).map(
96
+ ({ location, occurrences, distance }) => ({
97
+ location,
98
+ score: getSuggestionScore(occurrences, maxOccurence, distance),
99
+ occurrences,
100
+ distance,
101
+ }),
102
+ );
103
+
104
+ scoredLocations.sort(({ score: scoreA }, { score: scoreB }) => {
105
+ return scoreB - scoreA;
61
106
  });
62
- return locations;
107
+
108
+ return scoredLocations.map(({ location }) => location);
63
109
  }
@@ -0,0 +1,83 @@
1
+ import { ResolvedPNode } from '@lblod/ember-rdfa-editor/utils/_private/types';
2
+ import { Address } from './address-helpers';
3
+ import { Area, Place } from './geo-helpers';
4
+ import {
5
+ EditorState,
6
+ Transaction,
7
+ NodeSelection,
8
+ TextSelection,
9
+ PNode,
10
+ Selection,
11
+ } from '@lblod/ember-rdfa-editor';
12
+ import type { FullTriple } from '@lblod/ember-rdfa-editor/core/rdfa-processor';
13
+ import { PROV } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
14
+ import { SayDataFactory } from '@lblod/ember-rdfa-editor/core/say-data-factory';
15
+ import { transactionCombinator } from '@lblod/ember-rdfa-editor/utils/transaction-utils';
16
+ import { updateSubject } from '@lblod/ember-rdfa-editor/plugins/rdfa-info/utils';
17
+
18
+ function moveNodeSelectionForward(selection: Selection, doc: PNode) {
19
+ if (!(selection instanceof NodeSelection)) {
20
+ return selection;
21
+ }
22
+
23
+ const $from = selection.$from;
24
+
25
+ const index = $from.index();
26
+ const parent = $from.parent;
27
+
28
+ if (index + 1 < parent.childCount) {
29
+ const nextPos = selection.from + selection.node.nodeSize;
30
+
31
+ return NodeSelection.create(doc, nextPos);
32
+ } else {
33
+ const posAfter = selection.to;
34
+
35
+ return TextSelection.create(doc, posAfter);
36
+ }
37
+ }
38
+
39
+ export function replaceLocationCommand(
40
+ node: ResolvedPNode,
41
+ location: Address | Place | Area,
42
+ ) {
43
+ return function (state: EditorState, dispatch: (tr: Transaction) => void) {
44
+ const df = new SayDataFactory();
45
+ const { pos, value: locNode } = node;
46
+ // The location's subject has likely changed, so we should update the external links too
47
+ // if they exist
48
+ // NOTE: It's VERY important that this is done without mutating the triple objects
49
+ // otherwise the attributes will not update as expected when undo-ing
50
+ const newExternalTriples: FullTriple[] = (
51
+ locNode.attrs.externalTriples as FullTriple[]
52
+ ).map((tr) => {
53
+ if (PROV('atLocation').matches(tr.predicate)) {
54
+ return { ...tr, object: df.namedNode(location.uri) };
55
+ } else {
56
+ return tr;
57
+ }
58
+ }); // update the location value and the external triples
59
+ const tr = state.tr;
60
+ const setLocationTr = transactionCombinator(
61
+ state,
62
+ tr
63
+ .setNodeAttribute(pos, 'value', location)
64
+ .setNodeAttribute(pos, 'externalTriples', newExternalTriples),
65
+ )([
66
+ // Update the subject uri, while keeping backlinks intact
67
+ updateSubject({
68
+ pos,
69
+ targetSubject: location.uri,
70
+ keepBacklinks: true,
71
+ keepProperties: false,
72
+ keepExternalTriples: true,
73
+ }),
74
+ ]).transaction;
75
+
76
+ const newSelection = moveNodeSelectionForward(
77
+ state.selection.map(setLocationTr.doc, setLocationTr.mapping),
78
+ setLocationTr.doc,
79
+ );
80
+ setLocationTr.setSelection(newSelection);
81
+ dispatch(setLocationTr);
82
+ };
83
+ }
@@ -13,7 +13,7 @@ interface Signature<Doc extends PreviewableDocument> {
13
13
  export default class DocumentPreview<Doc extends PreviewableDocument> extends Component<Signature<Doc>> {
14
14
  controller?: SayController;
15
15
  isExpanded: boolean;
16
- onInsert(): void;
16
+ onInsert: import("ember-concurrency").TaskForAsyncTaskFunction<unknown, () => Promise<void>>;
17
17
  togglePreview(): void;
18
18
  get isFavourite(): boolean | undefined;
19
19
  toggleFavourite: (event: MouseEvent) => void;
@@ -0,0 +1,3 @@
1
+ import { Address } from './address-helpers';
2
+ import { Area, Place } from './geo-helpers';
3
+ export declare function getLocationUri(location: Address | Place | Area): string;
@@ -1,14 +1,16 @@
1
1
  import { EditorState } from '@lblod/ember-rdfa-editor';
2
- import { LocationType } from '@lblod/ember-rdfa-editor-lblod-plugins/components/location-plugin/map';
3
2
  export declare function getContextualActions(): (state: EditorState, searchQuery?: string) => {
3
+ label: string;
4
4
  id: string;
5
5
  group: string;
6
- command: import("@lblod/ember-rdfa-editor").Command;
7
- label: string;
8
- locationType: LocationType;
9
- icon: string;
6
+ command: (state: EditorState, dispatch: (tr: import("@lblod/ember-rdfa-editor").Transaction) => void) => void;
10
7
  }[];
11
- export declare function getContextualActionGroups(): (state: EditorState) => {
8
+ export declare function getContextualActionGroups(): (state: EditorState) => ({
12
9
  id: string;
13
10
  label: string;
14
- }[];
11
+ sticky?: undefined;
12
+ } | {
13
+ id: string;
14
+ label: string;
15
+ sticky: string;
16
+ })[];
@@ -0,0 +1,5 @@
1
+ import { ResolvedPNode } from '@lblod/ember-rdfa-editor/utils/_private/types';
2
+ import { Address } from './address-helpers';
3
+ import { Area, Place } from './geo-helpers';
4
+ import { EditorState, Transaction } from '@lblod/ember-rdfa-editor';
5
+ export declare function replaceLocationCommand(node: ResolvedPNode, location: Address | Place | Area): (state: EditorState, dispatch: (tr: Transaction) => void) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lblod/ember-rdfa-editor-lblod-plugins",
3
- "version": "37.0.3",
3
+ "version": "37.1.0",
4
4
  "description": "Ember addon providing lblod specific plugins for the ember-rdfa-editor",
5
5
  "keywords": [
6
6
  "ember-addon",
@@ -111,7 +111,7 @@
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.8.0",
114
+ "@lblod/ember-rdfa-editor": "13.10.0",
115
115
  "@glint/template": "^1.7.7",
116
116
  "@rdfjs/to-ntriples": "^3.0.1",
117
117
  "@rdfjs/types": "^1.1.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": "^13.8.0",
187
+ "@lblod/ember-rdfa-editor": "^13.10.0",
188
188
  "ember-concurrency": "^4.0.2",
189
189
  "ember-element-helper": "^0.8.6",
190
190
  "ember-intl": "^7.0.0",
@@ -452,6 +452,7 @@ location-plugin:
452
452
  insert-point-on-map: Insert a point on the map
453
453
  insert-area: Insert area
454
454
  other-elements: Other elements
455
+ location-suggestions: Location suggestions
455
456
  types:
456
457
  address: Address
457
458
  place: Place
@@ -449,6 +449,7 @@ location-plugin:
449
449
  insert-point-on-map: Punt op de kaart invoegen
450
450
  insert-area: Gebied invoegen
451
451
  other-elements: Andere elementen
452
+ location-suggestions: Locatiesuggesties
452
453
  types:
453
454
  address: Adres
454
455
  place: Plaats