@lblod/ember-rdfa-editor-lblod-plugins 24.3.2 → 25.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.
Files changed (52) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/addon/components/lmb-plugin/list.hbs +10 -2
  3. package/addon/components/lmb-plugin/search-modal.hbs +28 -2
  4. package/addon/components/lmb-plugin/search-modal.ts +109 -71
  5. package/addon/components/mandatee-table-plugin/node.gts +1 -1
  6. package/addon/components/snippet-plugin/nodes/placeholder.gts +2 -2
  7. package/addon/components/snippet-plugin/nodes/snippet.gts +54 -11
  8. package/addon/components/snippet-plugin/search-modal.ts +3 -4
  9. package/addon/components/snippet-plugin/snippet-insert-placeholder.gts +4 -4
  10. package/addon/components/snippet-plugin/snippet-insert-rdfa.gts +7 -10
  11. package/addon/components/snippet-plugin/snippet-insert.gts +16 -19
  12. package/addon/components/snippet-plugin/snippet-list/snippet-list-modal.hbs +1 -1
  13. package/addon/components/snippet-plugin/snippet-list/snippet-list-modal.ts +7 -9
  14. package/addon/components/snippet-plugin/snippet-list/snippet-list-view.hbs +1 -1
  15. package/addon/components/snippet-plugin/snippet-list/snippet-list-view.ts +5 -9
  16. package/addon/components/snippet-plugin/snippet-list-select.gts +2 -2
  17. package/addon/components/variable-plugin/date/date-time-picker.ts +2 -2
  18. package/addon/plugins/lmb-plugin/index.ts +3 -0
  19. package/addon/plugins/lmb-plugin/utils/fetchMandatees.ts +107 -8
  20. package/addon/plugins/snippet-plugin/commands/insert-snippet.ts +5 -8
  21. package/addon/plugins/snippet-plugin/commands/update-snippet-placeholder.ts +2 -2
  22. package/addon/plugins/snippet-plugin/index.ts +8 -7
  23. package/addon/plugins/snippet-plugin/nodes/snippet-placeholder.ts +59 -16
  24. package/addon/plugins/snippet-plugin/nodes/snippet.ts +29 -11
  25. package/addon/plugins/snippet-plugin/utils/fetch-data.ts +8 -8
  26. package/addon/plugins/snippet-plugin/utils/rdfa-predicate.ts +17 -3
  27. package/addon/utils/constants.ts +11 -0
  28. package/addon/utils/has-descendant.ts +19 -0
  29. package/app/styles/mandatee-table-plugin.scss +5 -0
  30. package/declarations/addon/components/lmb-plugin/search-modal.d.ts +16 -4
  31. package/declarations/addon/components/snippet-plugin/nodes/placeholder.d.ts +1 -1
  32. package/declarations/addon/components/snippet-plugin/nodes/snippet.d.ts +2 -0
  33. package/declarations/addon/components/snippet-plugin/search-modal.d.ts +1 -1
  34. package/declarations/addon/components/snippet-plugin/snippet-insert-rdfa.d.ts +2 -6
  35. package/declarations/addon/components/snippet-plugin/snippet-insert.d.ts +3 -7
  36. package/declarations/addon/components/snippet-plugin/snippet-list/snippet-list-modal.d.ts +3 -3
  37. package/declarations/addon/components/snippet-plugin/snippet-list/snippet-list-view.d.ts +2 -2
  38. package/declarations/addon/components/snippet-plugin/snippet-list-select.d.ts +1 -1
  39. package/declarations/addon/plugins/lmb-plugin/index.d.ts +3 -0
  40. package/declarations/addon/plugins/lmb-plugin/utils/fetchMandatees.d.ts +14 -3
  41. package/declarations/addon/plugins/snippet-plugin/commands/insert-snippet.d.ts +3 -4
  42. package/declarations/addon/plugins/snippet-plugin/index.d.ts +6 -2
  43. package/declarations/addon/plugins/snippet-plugin/nodes/snippet-placeholder.d.ts +11 -2
  44. package/declarations/addon/plugins/snippet-plugin/nodes/snippet.d.ts +4 -5
  45. package/declarations/addon/plugins/snippet-plugin/utils/fetch-data.d.ts +1 -1
  46. package/declarations/addon/plugins/snippet-plugin/utils/rdfa-predicate.d.ts +8 -2
  47. package/declarations/addon/utils/constants.d.ts +7 -0
  48. package/declarations/addon/utils/has-descendant.d.ts +2 -0
  49. package/package.json +3 -3
  50. package/pnpm-lock.yaml +6 -6
  51. package/translations/en-US.yaml +6 -0
  52. package/translations/nl-BE.yaml +7 -1
@@ -23,7 +23,7 @@ interface Signature {
23
23
  lists: SnippetList[],
24
24
  allowMultipleSnippets: boolean,
25
25
  ) => void;
26
- assignedSnippetListsIds: string[] | undefined;
26
+ snippetListIds: string[] | undefined;
27
27
  closeModal: () => void;
28
28
  open: boolean;
29
29
  allowMultipleSnippets?: boolean;
@@ -40,10 +40,8 @@ export default class SnippetListModalComponent extends Component<Signature> {
40
40
  // Display
41
41
  @tracked error: unknown;
42
42
 
43
- @trackedReset('args.assignedSnippetListsIds')
44
- assignedSnippetListsIds: string[] = [
45
- ...(this.args.assignedSnippetListsIds ?? []),
46
- ];
43
+ @trackedReset('args.snippetListIds')
44
+ snippetListIds: string[] = [...(this.args.snippetListIds ?? [])];
47
45
 
48
46
  @localCopy('args.allowMultipleSnippets') allowMultipleSnippets = false;
49
47
 
@@ -65,7 +63,7 @@ export default class SnippetListModalComponent extends Component<Signature> {
65
63
  @action
66
64
  saveAndClose() {
67
65
  const snippetLists = this.snippetListResource.value?.filter((snippetList) =>
68
- this.assignedSnippetListsIds.includes(snippetList.id),
66
+ this.snippetListIds.includes(snippetList.id),
69
67
  );
70
68
  this.args.onSaveSnippetLists(
71
69
  snippetLists || [],
@@ -73,7 +71,7 @@ export default class SnippetListModalComponent extends Component<Signature> {
73
71
  );
74
72
  this.args.closeModal();
75
73
  // Clear selection for next time
76
- this.assignedSnippetListsIds = [];
74
+ this.snippetListIds = [];
77
75
  }
78
76
 
79
77
  snippetListSearch = restartableTask(async () => {
@@ -107,7 +105,7 @@ export default class SnippetListModalComponent extends Component<Signature> {
107
105
  );
108
106
 
109
107
  @action
110
- onChange(assignedSnippetListsIds: string[]) {
111
- this.assignedSnippetListsIds = assignedSnippetListsIds;
108
+ onChange(snippetListIds: string[]) {
109
+ this.snippetListIds = snippetListIds;
112
110
  }
113
111
  }
@@ -53,7 +53,7 @@
53
53
  <AuCheckbox
54
54
  id={{row.label}}
55
55
  @onChange={{fn this.onChange row.id}}
56
- @checked={{in-array @assignedSnippetListsIds row.id}}
56
+ @checked={{in-array @snippetListIds row.id}}
57
57
  />
58
58
  </td>
59
59
  <td>{{row.label}}</td>
@@ -4,25 +4,22 @@ import { SnippetList } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/snip
4
4
 
5
5
  interface Args {
6
6
  snippetLists: SnippetList[];
7
- assignedSnippetListsIds: string[];
7
+ snippetListIds: string[];
8
8
  listNameFilter: string | null;
9
9
  isLoading: boolean;
10
- onChange: (assignedSnippetListsIds: string[]) => void;
10
+ onChange: (snippetListIds: string[]) => void;
11
11
  }
12
12
 
13
13
  export default class SnippetListViewComponent extends Component<Args> {
14
14
  @action
15
15
  onChange(snippetId: string, isSelected: boolean) {
16
16
  if (isSelected) {
17
- const newSnippetListIds = [
18
- ...this.args.assignedSnippetListsIds,
19
- snippetId,
20
- ];
17
+ const newSnippetListIds = [...this.args.snippetListIds, snippetId];
21
18
 
22
19
  return this.args.onChange(newSnippetListIds);
23
20
  }
24
21
 
25
- const newSnippetListIds = this.args.assignedSnippetListsIds.filter(
22
+ const newSnippetListIds = this.args.snippetListIds.filter(
26
23
  (id) => id !== snippetId,
27
24
  );
28
25
 
@@ -49,8 +46,7 @@ export default class SnippetListViewComponent extends Component<Args> {
49
46
  return;
50
47
  }
51
48
 
52
- const isSelected =
53
- this.args.assignedSnippetListsIds.includes(snippetListId);
49
+ const isSelected = this.args.snippetListIds.includes(snippetListId);
54
50
 
55
51
  this.onChange(snippetListId, !isSelected);
56
52
  }
@@ -53,7 +53,7 @@ export default class SnippetListSelect extends Component<Signature> {
53
53
  return getSnippetListIdsProperties(this.args.node.value);
54
54
  }
55
55
 
56
- get assignedSnippetListsIds(): string[] {
56
+ get snippetListIds(): string[] {
57
57
  return getAssignedSnippetListsIdsFromProperties(
58
58
  this.snippetListIdsProperties,
59
59
  );
@@ -99,7 +99,7 @@ export default class SnippetListSelect extends Component<Signature> {
99
99
 
100
100
  <SnippetListModal
101
101
  @config={{@config}}
102
- @assignedSnippetListsIds={{this.assignedSnippetListsIds}}
102
+ @snippetListIds={{this.snippetListIds}}
103
103
  @onSaveSnippetLists={{this.onSaveSnippetLists}}
104
104
  @allowMultipleSnippets={{this.allowMultipleSnippets}}
105
105
  @open={{this.showModal}}
@@ -51,9 +51,9 @@ export default class DateTimePickerComponent extends Component<Args> {
51
51
  this.date = new Date();
52
52
  this.date.setHours(0, 0, 0, 0);
53
53
  }
54
- this.date.setDate(date.getDate());
55
- this.date.setMonth(date.getMonth());
56
54
  this.date.setFullYear(date.getFullYear());
55
+ this.date.setMonth(date.getMonth());
56
+ this.date.setDate(date.getDate());
57
57
  this.args.onChange(this.date);
58
58
  }
59
59
  }
@@ -1,8 +1,11 @@
1
1
  import { SayController } from '@lblod/ember-rdfa-editor';
2
2
  import Mandatee from '@lblod/ember-rdfa-editor-lblod-plugins/models/mandatee';
3
+ import { BestuursperiodeLabel } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
3
4
 
4
5
  export type LmbPluginConfig = {
5
6
  endpoint: string;
7
+ defaultPeriod?: BestuursperiodeLabel;
8
+ defaultAdminUnit?: string;
6
9
  };
7
10
 
8
11
  export function createMandateeNode(
@@ -1,11 +1,30 @@
1
+ import { SearchSort } from '@lblod/ember-rdfa-editor-lblod-plugins/components/lmb-plugin/search-modal';
1
2
  import Mandatee from '@lblod/ember-rdfa-editor-lblod-plugins/models/mandatee';
2
- import { executeQuery } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/sparql-helpers';
3
+ import { BESTUURSPERIODES } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants';
4
+ import {
5
+ executeQuery,
6
+ sparqlEscapeString,
7
+ } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/sparql-helpers';
3
8
 
4
- type FetchMandateesArgs = {
9
+ export type FetchMandateesArgs = {
5
10
  endpoint: string;
11
+ searchString: string;
12
+ adminUnitSearch: string;
13
+ page: number;
14
+ pageSize: number;
15
+ sort: SearchSort;
16
+ period: (typeof BESTUURSPERIODES)[keyof typeof BESTUURSPERIODES];
6
17
  };
7
18
 
8
- export async function fetchMandatees({ endpoint }: FetchMandateesArgs) {
19
+ export async function countMandatees({
20
+ endpoint,
21
+ searchString,
22
+ adminUnitSearch,
23
+ period,
24
+ }: Pick<
25
+ FetchMandateesArgs,
26
+ 'searchString' | 'endpoint' | 'period' | 'adminUnitSearch'
27
+ >) {
9
28
  const query = `
10
29
  PREFIX besluit: <http://data.vlaanderen.be/ns/besluit#>
11
30
  PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
@@ -14,7 +33,8 @@ export async function fetchMandatees({ endpoint }: FetchMandateesArgs) {
14
33
  PREFIX persoon: <http://data.vlaanderen.be/ns/persoon#>
15
34
  PREFIX org: <http://www.w3.org/ns/org#>
16
35
  PREFIX regorg: <https://www.w3.org/ns/regorg#>
17
- SELECT DISTINCT ?mandatee ?person ?firstName ?lastName ?statusLabel ?fractieLabel ?roleLabel WHERE {
36
+ PREFIX lmb: <http://lblod.data.gift/vocabularies/lmb/>
37
+ SELECT DISTINCT (count(distinct ?mandatee) as ?count) WHERE {
18
38
  ?mandatee a mandaat:Mandataris;
19
39
  org:holds ?mandaat;
20
40
  mandaat:status ?status;
@@ -24,21 +44,100 @@ export async function fetchMandatees({ endpoint }: FetchMandateesArgs) {
24
44
  ?status skos:prefLabel ?statusLabel.
25
45
  ?mandaat org:role ?role.
26
46
  ?role skos:prefLabel ?roleLabel.
27
- OPTIONAL {
28
- ?mandatee mandaat:einde ?endDate
47
+ ?bestuursorgaanIT org:hasPost ?mandaat.
48
+ ?bestuursorgaanIT lmb:heeftBestuursperiode <${period}>.
49
+ ?bestuursorgaanIT mandaat:isTijdspecialisatieVan/besluit:bestuurt/skos:prefLabel ?adminUnitName.
50
+
51
+ ${adminUnitSearch.length ? `FILTER(contains(lcase(?adminUnitName), lcase(${sparqlEscapeString(adminUnitSearch)}) )).` : ''}
52
+ ${searchString.length ? `FILTER(contains(lcase(concat(?firstName, " ", ?lastName)), lcase(${sparqlEscapeString(searchString)}) )).` : ''}
53
+ }
54
+ `;
55
+ const response = await executeQuery({
56
+ query,
57
+ endpoint,
58
+ });
59
+ console.log(response);
60
+ return Number(response.results.bindings[0].count.value);
61
+ }
62
+
63
+ export async function fetchMandatees({
64
+ endpoint,
65
+ page,
66
+ pageSize,
67
+ searchString,
68
+ adminUnitSearch,
69
+ sort,
70
+ period,
71
+ }: FetchMandateesArgs) {
72
+ const count = await countMandatees({
73
+ endpoint,
74
+ searchString,
75
+ period,
76
+ adminUnitSearch,
77
+ });
78
+ let sortString = '?lastName ?firstName';
79
+ if (sort) {
80
+ const [key, direction] = sort;
81
+ switch (key) {
82
+ case 'fullName':
83
+ sortString = `${direction}(?lastName) ?firstName`;
84
+ break;
85
+ case 'status':
86
+ sortString = `${direction}(?statusLabel) ?lastName ?firstName`;
87
+ break;
88
+ case 'fractie':
89
+ sortString = `${direction}(?fractieLabel) ?lastName ?firstName`;
90
+ break;
91
+ case 'role':
92
+ sortString = `${direction}(?roleLabel) ?lastName ?firstName`;
93
+ break;
94
+
95
+ default:
96
+ break;
97
+ }
98
+ }
99
+
100
+ const query = `
101
+ PREFIX besluit: <http://data.vlaanderen.be/ns/besluit#>
102
+ PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
103
+ PREFIX mandaat: <http://data.vlaanderen.be/ns/mandaat#>
104
+ PREFIX foaf: <http://xmlns.com/foaf/0.1/>
105
+ PREFIX persoon: <http://data.vlaanderen.be/ns/persoon#>
106
+ PREFIX org: <http://www.w3.org/ns/org#>
107
+ PREFIX regorg: <https://www.w3.org/ns/regorg#>
108
+ PREFIX lmb: <http://lblod.data.gift/vocabularies/lmb/>
109
+ SELECT DISTINCT ?mandatee ?person ?firstName ?lastName ?statusLabel ?fractieLabel ?roleLabel WHERE {
110
+ {
111
+ ?mandatee a mandaat:Mandataris;
112
+ org:holds ?mandaat;
113
+ mandaat:status ?status;
114
+ mandaat:isBestuurlijkeAliasVan ?person.
115
+ ?person foaf:familyName ?lastName;
116
+ persoon:gebruikteVoornaam ?firstName.
117
+ ?status skos:prefLabel ?statusLabel.
118
+ ?mandaat org:role ?role.
119
+ ?role skos:prefLabel ?roleLabel.
120
+ ?bestuursorgaanIT org:hasPost ?mandaat.
121
+ ?bestuursorgaanIT lmb:heeftBestuursperiode <${period}>.
122
+ ?bestuursorgaanIT mandaat:isTijdspecialisatieVan/besluit:bestuurt/skos:prefLabel ?adminUnitName.
29
123
  }
30
124
  OPTIONAL {
31
125
  ?mandatee org:hasMembership ?membership.
32
126
  ?membership org:organisation ?fractie.
33
127
  ?fractie regorg:legalName ?fractieLabel.
34
128
  }
35
- filter (!bound(?endDate) || ?endDate > now()).
129
+
130
+ ${adminUnitSearch.length ? `FILTER(contains(lcase(?adminUnitName), lcase(${sparqlEscapeString(adminUnitSearch)}) )).` : ''}
131
+ ${searchString.length ? `FILTER(contains(lcase(concat(?firstName, "", ?lastName)), lcase(${sparqlEscapeString(searchString)}) )).` : ''}
36
132
  }
133
+ ORDER BY ${sortString}
134
+ LIMIT ${pageSize} OFFSET ${page * pageSize}
37
135
  `;
38
136
  const response = await executeQuery({
39
137
  query,
40
138
  endpoint,
41
139
  });
140
+ console.log(response.results.bindings);
42
141
  const mandatees = response.results.bindings.map(Mandatee.fromBinding);
43
- return mandatees;
142
+ return { mandatees, count };
44
143
  }
@@ -3,7 +3,7 @@ import { transactionCombinator } from '@lblod/ember-rdfa-editor/utils/transactio
3
3
  import { addPropertyToNode } from '@lblod/ember-rdfa-editor/utils/rdfa-utils';
4
4
  import { recalculateNumbers } from '../../structure-plugin/recalculate-structure-numbers';
5
5
  import { createSnippet } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/snippet-plugin/nodes/snippet';
6
- import { type ImportedResourceMap } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/snippet-plugin';
6
+ import { type SnippetListProperties } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/snippet-plugin';
7
7
  import {
8
8
  isSome,
9
9
  unwrap,
@@ -12,8 +12,7 @@ import {
12
12
  export interface InsertSnippetCommandArgs {
13
13
  content: string;
14
14
  title: string;
15
- assignedSnippetListsIds: string[];
16
- importedResources?: ImportedResourceMap;
15
+ listProperties: SnippetListProperties;
17
16
  range?: { start: number; end: number };
18
17
  allowMultipleSnippets?: boolean;
19
18
  }
@@ -21,8 +20,7 @@ export interface InsertSnippetCommandArgs {
21
20
  const insertSnippet = ({
22
21
  content,
23
22
  title,
24
- assignedSnippetListsIds,
25
- importedResources,
23
+ listProperties,
26
24
  range,
27
25
  allowMultipleSnippets,
28
26
  }: InsertSnippetCommandArgs): Command => {
@@ -44,13 +42,12 @@ const insertSnippet = ({
44
42
  schema: state.schema,
45
43
  content,
46
44
  title,
47
- snippetListIds: assignedSnippetListsIds,
48
- importedResources,
45
+ listProperties,
49
46
  allowMultipleSnippets,
50
47
  });
51
48
 
52
49
  const addImportedResourceProperties = Object.values(
53
- importedResources ?? {},
50
+ listProperties.importedResources ?? {},
54
51
  )
55
52
  .map((linked) => {
56
53
  const newProperties =
@@ -2,7 +2,7 @@ import { Command } from '@lblod/ember-rdfa-editor';
2
2
  import { addProperty, removeProperty } from '@lblod/ember-rdfa-editor/commands';
3
3
  import { sayDataFactory } from '@lblod/ember-rdfa-editor/core/say-data-factory';
4
4
  import { SNIPPET_LIST_RDFA_PREDICATE } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/snippet-plugin/utils/rdfa-predicate';
5
- import { getSnippetUriFromId } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/snippet-plugin';
5
+ import { getSnippetUriFromId } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/snippet-plugin/utils/rdfa-predicate';
6
6
  import { type OutgoingTriple } from '@lblod/ember-rdfa-editor/core/rdfa-processor';
7
7
  import { type ResolvedPNode } from '@lblod/ember-rdfa-editor/utils/_private/types';
8
8
  import {
@@ -59,7 +59,7 @@ export const updateSnippetPlaceholder = ({
59
59
  });
60
60
  transaction = transaction.setNodeAttribute(
61
61
  node.pos,
62
- 'listNames',
62
+ 'snippetListNames',
63
63
  newSnippetLists.map((list) => list.label),
64
64
  );
65
65
  transaction = transaction.setNodeAttribute(
@@ -6,6 +6,7 @@ import {
6
6
  } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/option';
7
7
  import { dateValue } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/strings';
8
8
  import { SafeString } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/types';
9
+ import { getSnippetIdFromUri } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/snippet-plugin/utils/rdfa-predicate';
9
10
 
10
11
  export const DEFAULT_CONTENT_STRING = 'block+';
11
12
 
@@ -34,6 +35,13 @@ export class Snippet {
34
35
 
35
36
  export type ImportedResourceMap = Record<string, Option<string>>;
36
37
 
38
+ export type SnippetListProperties = {
39
+ placeholderId: string;
40
+ listIds: string[];
41
+ names: string[];
42
+ importedResources: ImportedResourceMap;
43
+ };
44
+
37
45
  export type SnippetListArgs = {
38
46
  id: string;
39
47
  label: string;
@@ -41,13 +49,6 @@ export type SnippetListArgs = {
41
49
  importedResources: string[];
42
50
  };
43
51
 
44
- const snippetListBase = 'http://lblod.data.gift/snippet-lists/';
45
-
46
- export const getSnippetUriFromId = (id: string) => `${snippetListBase}${id}`;
47
-
48
- export const getSnippetIdFromUri = (uri: string) =>
49
- uri.replace(snippetListBase, '');
50
-
51
52
  export class SnippetList {
52
53
  id: string;
53
54
  label: string;
@@ -20,11 +20,12 @@ import { hasOutgoingNamedNodeTriple } from '@lblod/ember-rdfa-editor-lblod-plugi
20
20
  import { getTranslationFunction } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/translation';
21
21
  import { jsonParse } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/strings';
22
22
  import {
23
- getSnippetUriFromId,
23
+ type SnippetListProperties,
24
24
  type ImportedResourceMap,
25
25
  type SnippetList,
26
26
  } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/snippet-plugin';
27
- import { SNIPPET_LIST_RDFA_PREDICATE } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/snippet-plugin/utils/rdfa-predicate';
27
+ import { tripleForSnippetListId } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/snippet-plugin/utils/rdfa-predicate';
28
+ import { OutgoingTriple } from '@lblod/ember-rdfa-editor/core/rdfa-processor';
28
29
 
29
30
  export function importedResourcesFromSnippetLists(
30
31
  lists: SnippetList[],
@@ -38,27 +39,56 @@ export function importedResourcesFromSnippetLists(
38
39
  );
39
40
  }
40
41
 
41
- export function createSnippetPlaceholder(
42
- lists: SnippetList[],
43
- schema: Schema,
44
- allowMultipleSnippets?: boolean,
45
- ) {
42
+ type CreateSnippetPlaceholderArgs = {
43
+ schema: Schema;
44
+ allowMultipleSnippets?: boolean;
45
+ } & (
46
+ | {
47
+ listProperties: SnippetListProperties;
48
+ }
49
+ | {
50
+ lists: SnippetList[];
51
+ }
52
+ );
53
+
54
+ export function createSnippetPlaceholder({
55
+ schema,
56
+ allowMultipleSnippets,
57
+ ...args
58
+ }: CreateSnippetPlaceholderArgs) {
59
+ let additionalProperties: OutgoingTriple[];
60
+ let listProps: Omit<SnippetListProperties, 'listIds'>;
61
+ if ('lists' in args) {
62
+ listProps = {
63
+ // This is a completely new placeholder, so new id
64
+ placeholderId: uuidv4(),
65
+ names: args.lists.map((list) => list.label),
66
+ importedResources: importedResourcesFromSnippetLists(args.lists),
67
+ };
68
+ additionalProperties = args.lists.map((list) =>
69
+ tripleForSnippetListId(list.id),
70
+ );
71
+ } else {
72
+ // Replacing the last snippet, so keep the id
73
+ listProps = args.listProperties;
74
+ additionalProperties = args.listProperties.listIds.map(
75
+ tripleForSnippetListId,
76
+ );
77
+ }
46
78
  const mappingResource = `http://example.net/lblod-snippet-placeholder/${uuidv4()}`;
47
79
  return schema.nodes.snippet_placeholder.create({
48
80
  rdfaNodeType: 'resource',
49
- listNames: lists.map((list) => list.label),
81
+ placeholderId: listProps.placeholderId,
82
+ snippetListNames: listProps.names,
50
83
  subject: mappingResource,
51
84
  properties: [
52
85
  {
53
86
  predicate: RDF('type').full,
54
87
  object: sayDataFactory.namedNode(EXT('SnippetPlaceholder').full),
55
88
  },
56
- ...lists.map((list) => ({
57
- predicate: SNIPPET_LIST_RDFA_PREDICATE.full,
58
- object: sayDataFactory.namedNode(getSnippetUriFromId(list.id)),
59
- })),
89
+ ...additionalProperties,
60
90
  ],
61
- importedResources: importedResourcesFromSnippetLists(lists),
91
+ importedResources: listProps.importedResources,
62
92
  allowMultipleSnippets,
63
93
  });
64
94
  }
@@ -73,20 +103,22 @@ const emberNodeConfig: EmberNodeConfig = {
73
103
  attrs: {
74
104
  ...rdfaAttrSpec({ rdfaAware: true }),
75
105
  typeof: { default: EXT('SnippetPlaceholder') },
76
- listNames: { default: [] },
106
+ placeholderId: { default: '' },
107
+ snippetListNames: { default: [] },
77
108
  importedResources: { default: {} },
78
109
  allowMultipleSnippets: { default: false },
79
110
  },
80
111
  component: SnippetPlaceholderComponent,
81
112
  serialize(node, editorState) {
82
113
  const t = getTranslationFunction(editorState);
114
+ const listNames = node.attrs.snippetListNames as string[];
83
115
  return renderRdfaAware({
84
116
  renderable: node,
85
117
  tag: 'div',
86
118
  attrs: {
87
119
  ...node.attrs,
88
120
  class: 'say-snippet-placeholder-node',
89
- 'data-list-names': (node.attrs.listNames as string[]).join(','),
121
+ 'data-list-names': listNames && JSON.stringify(listNames),
90
122
  'data-imported-resources': JSON.stringify(node.attrs.importedResources),
91
123
  'data-allow-multiple-snippets': node.attrs.allowMultipleSnippets,
92
124
  },
@@ -112,9 +144,20 @@ const emberNodeConfig: EmberNodeConfig = {
112
144
  EXT('SnippetPlaceholder'),
113
145
  )
114
146
  ) {
147
+ let snippetListNames = jsonParse(
148
+ node.getAttribute('data-list-names'),
149
+ );
150
+ if (!snippetListNames) {
151
+ // We might have an older version which is comma separated
152
+ snippetListNames = node.getAttribute('data-list-names')?.split(',');
153
+ }
115
154
  return {
116
155
  ...rdfaAttrs,
117
- listNames: node.getAttribute('data-list-names')?.split(','),
156
+ // Generate a placeholderId any time we deserialise, this way we don't need to handle
157
+ // generating new ids whenever we re-use parts of a document (e.g. copy-paste or
158
+ // placeholders inside snippets)
159
+ placeholderId: uuidv4(),
160
+ snippetListNames,
118
161
  importedResources: jsonParse(
119
162
  node.getAttribute('data-imported-resources'),
120
163
  ),
@@ -32,7 +32,7 @@ import { hasOutgoingNamedNodeTriple } from '@lblod/ember-rdfa-editor-lblod-plugi
32
32
  import { jsonParse } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/strings';
33
33
  import {
34
34
  DEFAULT_CONTENT_STRING,
35
- type ImportedResourceMap,
35
+ SnippetListProperties,
36
36
  type SnippetPluginConfig,
37
37
  } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/snippet-plugin';
38
38
 
@@ -60,11 +60,10 @@ function outgoingFromBacklink(
60
60
 
61
61
  interface CreateSnippetArgs {
62
62
  schema: Schema;
63
+ allowMultipleSnippets?: boolean;
63
64
  content: string;
64
65
  title: string;
65
- snippetListIds: string[];
66
- importedResources?: ImportedResourceMap;
67
- allowMultipleSnippets?: boolean;
66
+ listProperties: SnippetListProperties;
68
67
  }
69
68
 
70
69
  /**
@@ -77,9 +76,13 @@ export function createSnippet({
77
76
  schema,
78
77
  content,
79
78
  title,
80
- snippetListIds,
81
- importedResources,
82
79
  allowMultipleSnippets,
80
+ listProperties: {
81
+ listIds: snippetListIds,
82
+ names: snippetListNames,
83
+ importedResources,
84
+ placeholderId,
85
+ },
83
86
  }: CreateSnippetArgs): [PNode, Map<string, OutgoingTriple[]>] {
84
87
  // Replace instances of linked to uris with the resources that exist in the outer document.
85
88
  let replacedContent = content;
@@ -100,7 +103,9 @@ export function createSnippet({
100
103
  const node = schema.node(
101
104
  'snippet',
102
105
  {
103
- assignedSnippetListsIds: snippetListIds,
106
+ placeholderId,
107
+ snippetListIds,
108
+ snippetListNames,
104
109
  title,
105
110
  subject: `http://data.lblod.info/snippets/${uuidv4()}`,
106
111
  importedResources,
@@ -153,7 +158,9 @@ const emberNodeConfig = (options: SnippetPluginConfig): EmberNodeConfig => ({
153
158
  ],
154
159
  },
155
160
  rdfaNodeType: { default: 'resource' },
156
- assignedSnippetListsIds: { default: [] },
161
+ placeholderId: { default: '' },
162
+ snippetListNames: { default: [] },
163
+ snippetListIds: { default: [] },
157
164
  importedResources: { default: {} },
158
165
  title: { default: '' },
159
166
  config: { default: options },
@@ -162,14 +169,17 @@ const emberNodeConfig = (options: SnippetPluginConfig): EmberNodeConfig => ({
162
169
  component: SnippetComponent,
163
170
  content: options.allowedContent || DEFAULT_CONTENT_STRING,
164
171
  serialize(node) {
172
+ const listNames = node.attrs.snippetListNames as string[];
165
173
  return renderRdfaAware({
166
174
  renderable: node,
167
175
  tag: 'div',
168
176
  attrs: {
169
177
  ...node.attrs,
178
+ 'data-snippet-placeholder-id': node.attrs.placeholderId,
170
179
  'data-assigned-snippet-ids': (
171
- node.attrs.assignedSnippetListsIds as string[]
172
- ).join(','),
180
+ node.attrs.snippetListIds as string[]
181
+ )?.join(','),
182
+ 'data-list-names': listNames && JSON.stringify(listNames),
173
183
  'data-imported-resources': JSON.stringify(node.attrs.importedResources),
174
184
  'data-snippet-title': node.attrs.title,
175
185
  'data-allow-multiple-snippets': node.attrs.allowMultipleSnippets,
@@ -186,11 +196,19 @@ const emberNodeConfig = (options: SnippetPluginConfig): EmberNodeConfig => ({
186
196
  if (
187
197
  hasOutgoingNamedNodeTriple(rdfaAttrs, RDF('type'), EXT('Snippet'))
188
198
  ) {
199
+ // For older documents without placeholder ids, treat each inserted snippet separately.
200
+ // This means that pressing 'remove snippet' will add a placeholder in it's place, which
201
+ // is not expected, but simple to remove (hitting backspace). This is better than
202
+ // risking having no ability to insert another snippet.
203
+ const placeholderId =
204
+ node.getAttribute('data-snippet-placeholder-id') || uuidv4();
189
205
  return {
190
206
  ...rdfaAttrs,
191
- assignedSnippetListsIds: node
207
+ placeholderId,
208
+ snippetListIds: node
192
209
  .getAttribute('data-assigned-snippet-ids')
193
210
  ?.split(','),
211
+ snippetListNames: jsonParse(node.getAttribute('data-list-names')),
194
212
  importedResources: jsonParse(
195
213
  node.getAttribute('data-imported-resources'),
196
214
  ),