@lblod/ember-rdfa-editor-lblod-plugins 11.2.0 → 11.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.
- package/.woodpecker/.changelog.yml +9 -0
- package/.woodpecker/.test.yml +0 -8
- package/CHANGELOG.md +9 -1
- package/README.md +14 -12
- package/addon/components/citation-plugin/citation-card.ts +22 -18
- package/addon/components/citation-plugin/citation-insert.hbs +0 -1
- package/addon/components/citation-plugin/citation-insert.ts +5 -7
- package/addon/components/citation-plugin/citations/decision-detail.ts +4 -5
- package/addon/components/citation-plugin/citations/decision-preview.hbs +61 -15
- package/addon/components/citation-plugin/citations/decision-preview.ts +19 -0
- package/addon/components/citation-plugin/citations/search-modal.hbs +49 -47
- package/addon/components/citation-plugin/citations/search-modal.ts +28 -17
- package/addon/plugins/citation-plugin/index.ts +8 -2
- package/addon/plugins/citation-plugin/utils/article.ts +193 -0
- package/addon/plugins/citation-plugin/utils/cache.ts +7 -0
- package/addon/plugins/citation-plugin/utils/legal-documents.ts +133 -0
- package/addon/plugins/citation-plugin/utils/process-match.ts +60 -44
- package/addon/plugins/citation-plugin/utils/public-decisions.ts +228 -0
- package/addon/plugins/citation-plugin/utils/{legislation-types.ts → types.ts} +24 -18
- package/addon/plugins/citation-plugin/utils/utils.ts +14 -0
- package/addon/plugins/citation-plugin/utils/vlaamse-codex.ts +29 -390
- package/components/citation-plugin/citation-card.d.ts +11 -14
- package/components/citation-plugin/citation-insert.d.ts +4 -3
- package/components/citation-plugin/citations/decision-detail.d.ts +3 -3
- package/components/citation-plugin/citations/decision-preview.d.ts +10 -0
- package/components/citation-plugin/citations/search-modal.d.ts +15 -16
- package/package.json +2 -2
- package/plugins/citation-plugin/index.d.ts +2 -1
- package/plugins/citation-plugin/utils/article.d.ts +29 -0
- package/plugins/citation-plugin/utils/cache.d.ts +1 -0
- package/plugins/citation-plugin/utils/legal-documents.d.ts +48 -0
- package/plugins/citation-plugin/utils/public-decisions.d.ts +8 -0
- package/plugins/citation-plugin/utils/types.d.ts +28 -0
- package/plugins/citation-plugin/utils/utils.d.ts +1 -0
- package/plugins/citation-plugin/utils/vlaamse-codex.d.ts +7 -69
- package/translations/en-US.yaml +4 -1
- package/translations/nl-BE.yaml +4 -0
- package/plugins/citation-plugin/utils/legislation-types.d.ts +0 -24
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { capitalize } from '@ember/string';
|
|
2
|
+
|
|
3
|
+
export const LEGISLATION_TYPES = {
|
|
2
4
|
decreet: 'https://data.vlaanderen.be/id/concept/AardWetgeving/Decreet',
|
|
3
5
|
'koninklijk besluit':
|
|
4
6
|
'https://data.vlaanderen.be/id/concept/AardWetgeving/KoninklijkBesluit',
|
|
@@ -24,24 +26,28 @@ const LEGISLATION_TYPES = {
|
|
|
24
26
|
'genummerd koninklijk besluit':
|
|
25
27
|
'https://data.vlaanderen.be/id/concept/AardWetgeving/GenummerdKoninklijkBesluit',
|
|
26
28
|
protocol: 'https://data.vlaanderen.be/id/concept/AardWetgeving/Protocol',
|
|
29
|
+
besluit: 'https://data.vlaanderen.be/doc/concept/AardWetgeving/Besluit',
|
|
27
30
|
};
|
|
28
31
|
|
|
29
|
-
export
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
32
|
+
export const legislationKeysCapitalized = Object.keys(LEGISLATION_TYPES).map(
|
|
33
|
+
capitalize,
|
|
34
|
+
) as [Capitalize<keyof typeof LEGISLATION_TYPES>];
|
|
35
|
+
|
|
36
|
+
export const isLegislationType = (
|
|
37
|
+
type: string,
|
|
38
|
+
): type is keyof typeof LEGISLATION_TYPES =>
|
|
39
|
+
Object.keys(LEGISLATION_TYPES).includes(type);
|
|
40
|
+
|
|
41
|
+
export const isBesluitType = (type: string) =>
|
|
42
|
+
type === LEGISLATION_TYPES['besluit'];
|
|
43
|
+
|
|
44
|
+
export const LEGISLATION_TYPE_CONCEPTS = Object.entries(LEGISLATION_TYPES).map(
|
|
45
|
+
([label, value]) => ({
|
|
46
|
+
label,
|
|
47
|
+
value,
|
|
48
|
+
}),
|
|
45
49
|
);
|
|
46
50
|
|
|
47
|
-
export
|
|
51
|
+
export interface Binding<A> {
|
|
52
|
+
value: A;
|
|
53
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* flemish codex encodes certain characters as a html character, which breaks our search
|
|
3
|
+
* this is an ugly work around
|
|
4
|
+
*/
|
|
5
|
+
export function replaceDiacriticsInWord(word: string): string {
|
|
6
|
+
const characters =
|
|
7
|
+
'Ë À Ì Â Í Ã Î Ä Ï Ç Ò È Ó É Ô Ê Õ Ö ê Ù ë Ú î Û ï Ü ô Ý õ â û ã ÿ ç'.split(
|
|
8
|
+
' ',
|
|
9
|
+
);
|
|
10
|
+
for (const char of characters) {
|
|
11
|
+
word = word.replace(new RegExp(`${char}`, 'g'), `&#${char.charCodeAt(0)};`);
|
|
12
|
+
}
|
|
13
|
+
return word;
|
|
14
|
+
}
|
|
@@ -1,158 +1,28 @@
|
|
|
1
|
-
import { LEGISLATION_TYPE_CONCEPTS } from './legislation-types';
|
|
2
|
-
import {
|
|
3
|
-
Option,
|
|
4
|
-
optionMapOr,
|
|
5
|
-
} from '@lblod/ember-rdfa-editor-lblod-plugins/utils/option';
|
|
6
1
|
import {
|
|
7
2
|
dateValue,
|
|
8
3
|
escapeValue,
|
|
9
4
|
} from '@lblod/ember-rdfa-editor-lblod-plugins/utils/strings';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
legislationTypeUri,
|
|
29
|
-
title,
|
|
30
|
-
publicationDate,
|
|
31
|
-
documentDate,
|
|
32
|
-
}: DecisionArgs) {
|
|
33
|
-
this.uri = uri;
|
|
34
|
-
this.legislationType = LEGISLATION_TYPE_CONCEPTS.find(
|
|
35
|
-
(t) => t.value === legislationTypeUri,
|
|
36
|
-
);
|
|
37
|
-
this.title = title;
|
|
38
|
-
this.publicationDate = publicationDate;
|
|
39
|
-
this.documentDate = documentDate;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
get fullTitle() {
|
|
43
|
-
return `${this.legislationType?.label ?? ''} ${this.title ?? ''}`;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
interface ArticleArgs {
|
|
48
|
-
uri: string;
|
|
49
|
-
number?: number;
|
|
50
|
-
content: string | null;
|
|
51
|
-
dateInForce: string | null;
|
|
52
|
-
dateNoLongerInForce: string | null;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export class Article {
|
|
56
|
-
uri: string;
|
|
57
|
-
number?: number;
|
|
58
|
-
content: string | null;
|
|
59
|
-
dateInForce: string | null;
|
|
60
|
-
dateNoLongerInForce: string | null;
|
|
61
|
-
|
|
62
|
-
constructor({
|
|
63
|
-
uri,
|
|
64
|
-
number,
|
|
65
|
-
content,
|
|
66
|
-
dateInForce,
|
|
67
|
-
dateNoLongerInForce,
|
|
68
|
-
}: ArticleArgs) {
|
|
69
|
-
this.uri = uri;
|
|
70
|
-
this.number = number;
|
|
71
|
-
this.content = content;
|
|
72
|
-
this.dateInForce = dateInForce;
|
|
73
|
-
this.dateNoLongerInForce = dateNoLongerInForce;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/*
|
|
78
|
-
* flemish codex encodes certain characters as a html character, which breaks our search
|
|
79
|
-
* this is an ugly work around
|
|
80
|
-
*/
|
|
81
|
-
function replaceDiacriticsInWord(word: string): string {
|
|
82
|
-
const characters =
|
|
83
|
-
'Ë À Ì Â Í Ã Î Ä Ï Ç Ò È Ó É Ô Ê Õ Ö ê Ù ë Ú î Û ï Ü ô Ý õ â û ã ÿ ç'.split(
|
|
84
|
-
' ',
|
|
85
|
-
);
|
|
86
|
-
for (const char of characters) {
|
|
87
|
-
word = word.replace(new RegExp(`${char}`, 'g'), `&#${char.charCodeAt(0)};`);
|
|
88
|
-
}
|
|
89
|
-
return word;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
//Attempt to memoise on the fetching by stringifying the arguments. This could spare a few fetches.
|
|
93
|
-
//If memoising fails, at least a normal fetch is performed.
|
|
94
|
-
|
|
95
|
-
const fetchDecisionsMemory = new Map<string, DecisionCollection>();
|
|
96
|
-
|
|
97
|
-
export interface QueryFilter {
|
|
98
|
-
type: string;
|
|
99
|
-
documentDateFrom?: Option<string>;
|
|
100
|
-
documentDateTo?: Option<string>;
|
|
101
|
-
publicationDateFrom?: Option<string>;
|
|
102
|
-
publicationDateTo?: Option<string>;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async function fetchDecisions({
|
|
106
|
-
words,
|
|
107
|
-
filter,
|
|
108
|
-
pageNumber = 0,
|
|
109
|
-
pageSize = 5,
|
|
110
|
-
config,
|
|
111
|
-
}: {
|
|
112
|
-
words: string[];
|
|
113
|
-
filter: QueryFilter;
|
|
114
|
-
pageNumber: number;
|
|
115
|
-
pageSize: number;
|
|
116
|
-
config: CodexQueryConfig;
|
|
117
|
-
}) {
|
|
118
|
-
/*abortSignal*/
|
|
119
|
-
//This is silly, but null != undefined, so we have to be careful and include the correct value here
|
|
120
|
-
//Also, reconstruct the whole filter object to always have the same ordering, hopefully.
|
|
121
|
-
filter = {
|
|
122
|
-
type: filter.type,
|
|
123
|
-
documentDateFrom: filter.documentDateFrom || null,
|
|
124
|
-
documentDateTo: filter.documentDateTo || null,
|
|
125
|
-
publicationDateFrom: filter.publicationDateFrom || null,
|
|
126
|
-
publicationDateTo: filter.publicationDateTo || null,
|
|
127
|
-
};
|
|
128
|
-
const stringArguments = JSON.stringify({
|
|
129
|
-
words,
|
|
130
|
-
filter,
|
|
131
|
-
pageNumber,
|
|
132
|
-
pageSize,
|
|
133
|
-
});
|
|
134
|
-
const results = fetchDecisionsMemory.get(stringArguments);
|
|
135
|
-
if (results) {
|
|
136
|
-
return results;
|
|
137
|
-
} else {
|
|
138
|
-
const newResults = await fetchDecisionsMemo({
|
|
139
|
-
words,
|
|
140
|
-
filter,
|
|
141
|
-
pageNumber,
|
|
142
|
-
pageSize,
|
|
143
|
-
config,
|
|
144
|
-
});
|
|
145
|
-
fetchDecisionsMemory.set(stringArguments, newResults);
|
|
146
|
-
return newResults;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
interface DecisionCollection {
|
|
151
|
-
totalCount: number;
|
|
152
|
-
decisions: Decision[];
|
|
5
|
+
import {
|
|
6
|
+
executeCountQuery,
|
|
7
|
+
executeQuery,
|
|
8
|
+
} from '@lblod/ember-rdfa-editor-lblod-plugins/utils/sparql-helpers';
|
|
9
|
+
import {
|
|
10
|
+
LegalDocument,
|
|
11
|
+
LegalDocumentsCollection,
|
|
12
|
+
LegalDocumentsQueryConfig,
|
|
13
|
+
LegalDocumentsQueryFilter,
|
|
14
|
+
} from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/legal-documents';
|
|
15
|
+
import { Binding } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/types';
|
|
16
|
+
import { replaceDiacriticsInWord } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/utils';
|
|
17
|
+
|
|
18
|
+
interface VlaamseCodexLegalDocumentBinding {
|
|
19
|
+
uri: Binding<string>;
|
|
20
|
+
title: Binding<string>;
|
|
21
|
+
publicationDate: Binding<string>;
|
|
22
|
+
documentDate: Binding<string>;
|
|
153
23
|
}
|
|
154
24
|
|
|
155
|
-
async function
|
|
25
|
+
export async function fetchVlaamseCodexLegalDocuments({
|
|
156
26
|
words,
|
|
157
27
|
filter,
|
|
158
28
|
pageNumber = 0,
|
|
@@ -160,11 +30,11 @@ async function fetchDecisionsMemo({
|
|
|
160
30
|
config,
|
|
161
31
|
}: {
|
|
162
32
|
words: string[];
|
|
163
|
-
filter:
|
|
164
|
-
config:
|
|
33
|
+
filter: LegalDocumentsQueryFilter;
|
|
34
|
+
config: LegalDocumentsQueryConfig;
|
|
165
35
|
pageNumber?: number;
|
|
166
36
|
pageSize?: number;
|
|
167
|
-
}): Promise<
|
|
37
|
+
}): Promise<LegalDocumentsCollection> {
|
|
168
38
|
// TBD/NOTE: in the context of a <http://data.europa.eu/eli/ontology#LegalResource>
|
|
169
39
|
// the eli:cites can have either a <http://xmlns.com/foaf/0.1/Document> or <http://data.europa.eu/eli/ontology#LegalResource>
|
|
170
40
|
// as range (see AP https://data.vlaanderen.be/doc/applicatieprofiel/besluit-publicatie/#Rechtsgrond),
|
|
@@ -230,11 +100,11 @@ async function fetchDecisionsMemo({
|
|
|
230
100
|
${documentDateFilter}
|
|
231
101
|
${publicationDateFilter}
|
|
232
102
|
}`,
|
|
233
|
-
config,
|
|
103
|
+
...config,
|
|
234
104
|
});
|
|
235
105
|
|
|
236
106
|
if (totalCount > 0) {
|
|
237
|
-
const response = await executeQuery<
|
|
107
|
+
const response = await executeQuery<VlaamseCodexLegalDocumentBinding>({
|
|
238
108
|
query: `PREFIX eli: <http://data.europa.eu/eli/ontology#>
|
|
239
109
|
|
|
240
110
|
SELECT DISTINCT ?expressionUri as ?uri ?title ?publicationDate ?documentDate
|
|
@@ -256,10 +126,10 @@ async function fetchDecisionsMemo({
|
|
|
256
126
|
${documentDateFilter}
|
|
257
127
|
${publicationDateFilter}
|
|
258
128
|
} ORDER BY ?title LIMIT ${pageSize} OFFSET ${pageNumber * pageSize}`,
|
|
259
|
-
config,
|
|
129
|
+
...config,
|
|
260
130
|
});
|
|
261
131
|
|
|
262
|
-
const
|
|
132
|
+
const legalDocuments = response.results.bindings.map((binding) => {
|
|
263
133
|
const escapedTitle = escapeValue(binding.title.value);
|
|
264
134
|
const publicationDate = dateValue(
|
|
265
135
|
binding.publicationDate && binding.publicationDate.value,
|
|
@@ -267,7 +137,7 @@ async function fetchDecisionsMemo({
|
|
|
267
137
|
const documentDate = dateValue(
|
|
268
138
|
binding.documentDate && binding.documentDate.value,
|
|
269
139
|
);
|
|
270
|
-
return new
|
|
140
|
+
return new LegalDocument({
|
|
271
141
|
uri: binding.uri.value,
|
|
272
142
|
title: escapedTitle,
|
|
273
143
|
legislationTypeUri: type,
|
|
@@ -278,243 +148,12 @@ async function fetchDecisionsMemo({
|
|
|
278
148
|
|
|
279
149
|
return {
|
|
280
150
|
totalCount,
|
|
281
|
-
|
|
282
|
-
};
|
|
283
|
-
} else {
|
|
284
|
-
return {
|
|
285
|
-
totalCount,
|
|
286
|
-
decisions: [],
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
interface Binding<A> {
|
|
292
|
-
value: A;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
interface DecisionBinding {
|
|
296
|
-
uri: Binding<string>;
|
|
297
|
-
title: Binding<string>;
|
|
298
|
-
publicationDate: Binding<string>;
|
|
299
|
-
documentDate: Binding<string>;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
const fetchArticlesMemory = new Map<string, ArticleCollection>();
|
|
303
|
-
|
|
304
|
-
async function fetchArticles({
|
|
305
|
-
legalExpression,
|
|
306
|
-
pageNumber,
|
|
307
|
-
pageSize,
|
|
308
|
-
articleFilter,
|
|
309
|
-
config,
|
|
310
|
-
}: {
|
|
311
|
-
legalExpression: string;
|
|
312
|
-
pageNumber: number;
|
|
313
|
-
pageSize: number;
|
|
314
|
-
articleFilter: string;
|
|
315
|
-
config: CodexQueryConfig;
|
|
316
|
-
}): Promise<ArticleCollection> {
|
|
317
|
-
//Simpler here, only one way arguments are set up
|
|
318
|
-
const stringArguments = JSON.stringify({
|
|
319
|
-
legalExpression,
|
|
320
|
-
pageNumber,
|
|
321
|
-
pageSize,
|
|
322
|
-
articleFilter,
|
|
323
|
-
});
|
|
324
|
-
const results = fetchArticlesMemory.get(stringArguments);
|
|
325
|
-
if (results) {
|
|
326
|
-
return results;
|
|
327
|
-
} else {
|
|
328
|
-
const newResults = await fetchArticlesMemo({
|
|
329
|
-
legalExpression,
|
|
330
|
-
pageNumber,
|
|
331
|
-
pageSize,
|
|
332
|
-
articleFilter,
|
|
333
|
-
config,
|
|
334
|
-
});
|
|
335
|
-
fetchArticlesMemory.set(stringArguments, newResults);
|
|
336
|
-
return newResults;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
interface ArticleBinding {
|
|
341
|
-
count: {
|
|
342
|
-
value: string;
|
|
343
|
-
};
|
|
344
|
-
content?: {
|
|
345
|
-
value: string;
|
|
346
|
-
};
|
|
347
|
-
dateInForce?: {
|
|
348
|
-
value: string;
|
|
349
|
-
};
|
|
350
|
-
dateNoLongerInForce?: {
|
|
351
|
-
value: string;
|
|
352
|
-
};
|
|
353
|
-
article: {
|
|
354
|
-
value: string;
|
|
355
|
-
};
|
|
356
|
-
number?: {
|
|
357
|
-
value: number;
|
|
358
|
-
};
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
interface QueryResponse<B> {
|
|
362
|
-
results: {
|
|
363
|
-
bindings: B[];
|
|
364
|
-
};
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
interface ArticleCollection {
|
|
368
|
-
totalCount: number;
|
|
369
|
-
articles: Article[];
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
async function fetchArticlesMemo({
|
|
373
|
-
legalExpression,
|
|
374
|
-
pageNumber = 0,
|
|
375
|
-
pageSize = 10,
|
|
376
|
-
articleFilter,
|
|
377
|
-
config,
|
|
378
|
-
}: {
|
|
379
|
-
legalExpression: string;
|
|
380
|
-
pageNumber: number;
|
|
381
|
-
pageSize: number;
|
|
382
|
-
articleFilter: string;
|
|
383
|
-
config: CodexQueryConfig;
|
|
384
|
-
}): Promise<ArticleCollection> {
|
|
385
|
-
const numberFilter = articleFilter
|
|
386
|
-
? `FILTER( !BOUND(?number) || CONTAINS(?number, "${articleFilter}"))`
|
|
387
|
-
: '';
|
|
388
|
-
const totalCount = await executeCountQuery({
|
|
389
|
-
query: `PREFIX eli: <http://data.europa.eu/eli/ontology#>
|
|
390
|
-
PREFIX dct: <http://purl.org/dc/terms/>
|
|
391
|
-
|
|
392
|
-
SELECT COUNT(DISTINCT(?article)) as ?count
|
|
393
|
-
WHERE {
|
|
394
|
-
?legalResource eli:is_realized_by <${legalExpression}> ;
|
|
395
|
-
eli:has_part ?articleResource .
|
|
396
|
-
?articleResource eli:is_realized_by ?article ;
|
|
397
|
-
dct:type <https://data.vlaanderen.be/id/concept/TypeRechtsbrononderdeel/Artikel>.
|
|
398
|
-
OPTIONAL {
|
|
399
|
-
?article eli:first_date_entry_in_force ?dateInForce .
|
|
400
|
-
FILTER (?dateInForce <= NOW() )
|
|
401
|
-
}
|
|
402
|
-
OPTIONAL { ?article eli:date_no_longer_in_force ?dateNoLongerInForce }
|
|
403
|
-
FILTER( !BOUND(?dateNoLongerInForce) || ?dateNoLongerInForce > NOW() )
|
|
404
|
-
OPTIONAL { ?article eli:number ?number . }
|
|
405
|
-
${numberFilter}
|
|
406
|
-
}`,
|
|
407
|
-
config,
|
|
408
|
-
});
|
|
409
|
-
|
|
410
|
-
if (totalCount > 0) {
|
|
411
|
-
// ?number has format like "Artikel 12." We parse the number from the string for ordering
|
|
412
|
-
// Second degree ordering on ?numberStr to make sure "Artikel 3/1." comes after "Artikel 3."
|
|
413
|
-
const response = await executeQuery<ArticleBinding>({
|
|
414
|
-
query: `PREFIX eli: <http://data.europa.eu/eli/ontology#>
|
|
415
|
-
PREFIX prov: <http://www.w3.org/ns/prov#>
|
|
416
|
-
PREFIX dct: <http://purl.org/dc/terms/>
|
|
417
|
-
|
|
418
|
-
SELECT DISTINCT ?article ?dateInForce ?dateNoLongerInForce ?number ?content WHERE {
|
|
419
|
-
?legalResource eli:is_realized_by <${legalExpression}> ;
|
|
420
|
-
eli:has_part ?articleResource .
|
|
421
|
-
?articleResource eli:is_realized_by ?article ;
|
|
422
|
-
dct:type <https://data.vlaanderen.be/id/concept/TypeRechtsbrononderdeel/Artikel>.
|
|
423
|
-
OPTIONAL {
|
|
424
|
-
?article eli:first_date_entry_in_force ?dateInForce .
|
|
425
|
-
FILTER (?dateInForce <= NOW() )
|
|
426
|
-
}
|
|
427
|
-
OPTIONAL { ?article eli:date_no_longer_in_force ?dateNoLongerInForce }
|
|
428
|
-
FILTER( !BOUND(?dateNoLongerInForce) || ?dateNoLongerInForce > NOW() )
|
|
429
|
-
OPTIONAL { ?article prov:value ?content . }
|
|
430
|
-
OPTIONAL { ?article eli:number ?number . }
|
|
431
|
-
${numberFilter}
|
|
432
|
-
BIND(REPLACE(?number, "Artikel ", "") as ?numberStr)
|
|
433
|
-
BIND(STRDT(?numberStr, xsd:integer) as ?numberInt)
|
|
434
|
-
} ORDER BY ?numberInt ?numberStr LIMIT ${pageSize} OFFSET ${
|
|
435
|
-
pageNumber * pageSize
|
|
436
|
-
}`,
|
|
437
|
-
config,
|
|
438
|
-
});
|
|
439
|
-
|
|
440
|
-
const articles = response.results.bindings.map((binding) => {
|
|
441
|
-
const escapedContent = escapeValue(
|
|
442
|
-
binding.content && binding.content.value,
|
|
443
|
-
);
|
|
444
|
-
const dateInForce = dateValue(
|
|
445
|
-
binding.dateInForce && binding.dateInForce.value,
|
|
446
|
-
);
|
|
447
|
-
const dateNoLongerInForce = dateValue(
|
|
448
|
-
binding.dateNoLongerInForce && binding.dateNoLongerInForce.value,
|
|
449
|
-
);
|
|
450
|
-
return new Article({
|
|
451
|
-
uri: binding.article.value,
|
|
452
|
-
number: binding.number && binding.number.value,
|
|
453
|
-
content: escapedContent,
|
|
454
|
-
dateInForce,
|
|
455
|
-
dateNoLongerInForce,
|
|
456
|
-
});
|
|
457
|
-
});
|
|
458
|
-
|
|
459
|
-
return {
|
|
460
|
-
totalCount,
|
|
461
|
-
articles,
|
|
151
|
+
legalDocuments,
|
|
462
152
|
};
|
|
463
153
|
} else {
|
|
464
154
|
return {
|
|
465
155
|
totalCount,
|
|
466
|
-
|
|
156
|
+
legalDocuments: [],
|
|
467
157
|
};
|
|
468
158
|
}
|
|
469
159
|
}
|
|
470
|
-
|
|
471
|
-
function cleanCaches() {
|
|
472
|
-
fetchDecisionsMemory.clear();
|
|
473
|
-
fetchArticlesMemory.clear();
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
async function executeCountQuery({
|
|
477
|
-
query,
|
|
478
|
-
config,
|
|
479
|
-
}: {
|
|
480
|
-
query: string;
|
|
481
|
-
config: CodexQueryConfig;
|
|
482
|
-
}) {
|
|
483
|
-
const response = await executeQuery<{ count: { value: string } }>({
|
|
484
|
-
query,
|
|
485
|
-
config,
|
|
486
|
-
});
|
|
487
|
-
return optionMapOr(0, parseInt, response.results.bindings[0]?.count.value);
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
type CodexQueryConfig = { endpoint: string; abortSignal?: AbortSignal };
|
|
491
|
-
|
|
492
|
-
async function executeQuery<A>({
|
|
493
|
-
query,
|
|
494
|
-
config,
|
|
495
|
-
}: {
|
|
496
|
-
query: string;
|
|
497
|
-
config: CodexQueryConfig;
|
|
498
|
-
}): Promise<QueryResponse<A>> {
|
|
499
|
-
const encodedQuery = encodeURIComponent(query.trim());
|
|
500
|
-
|
|
501
|
-
const response = await fetch(config.endpoint, {
|
|
502
|
-
method: 'POST',
|
|
503
|
-
headers: {
|
|
504
|
-
Accept: 'application/sparql-results+json',
|
|
505
|
-
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
|
506
|
-
},
|
|
507
|
-
body: `query=${encodedQuery}`,
|
|
508
|
-
signal: config.abortSignal,
|
|
509
|
-
});
|
|
510
|
-
|
|
511
|
-
if (response.ok) {
|
|
512
|
-
return response.json() as Promise<QueryResponse<A>>;
|
|
513
|
-
} else {
|
|
514
|
-
throw new Error(
|
|
515
|
-
`Request to Vlaamse Codex was unsuccessful: [${response.status}] ${response.statusText}`,
|
|
516
|
-
);
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
export { fetchDecisions, fetchArticles, cleanCaches };
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import Component from '@glimmer/component';
|
|
2
|
-
import { Article, Decision } from '../../plugins/citation-plugin/utils/vlaamse-codex';
|
|
3
2
|
import { Option } from '@lblod/ember-rdfa-editor-lblod-plugins/utils/option';
|
|
4
|
-
import { CitationDecoration, CitationPlugin } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin';
|
|
3
|
+
import { CitationDecoration, CitationPlugin, CitationPluginEmberComponentConfig } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin';
|
|
5
4
|
import { SayController } from '@lblod/ember-rdfa-editor';
|
|
5
|
+
import { Article } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/article';
|
|
6
|
+
import { LegalDocument } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/legal-documents';
|
|
6
7
|
interface Args {
|
|
7
8
|
controller: SayController;
|
|
8
9
|
plugin: CitationPlugin;
|
|
9
|
-
config:
|
|
10
|
-
endpoint: string;
|
|
11
|
-
};
|
|
10
|
+
config: CitationPluginEmberComponentConfig;
|
|
12
11
|
}
|
|
13
12
|
export default class CitationCardComponent extends Component<Args> {
|
|
14
13
|
pageNumber: number;
|
|
@@ -18,7 +17,7 @@ export default class CitationCardComponent extends Component<Args> {
|
|
|
18
17
|
decisions: never[];
|
|
19
18
|
error: unknown;
|
|
20
19
|
showModal: boolean;
|
|
21
|
-
decision:
|
|
20
|
+
decision: LegalDocument | null;
|
|
22
21
|
cardText: string | null;
|
|
23
22
|
cardLegislationType: string | null;
|
|
24
23
|
documentLegislationType: Option<string>;
|
|
@@ -27,13 +26,11 @@ export default class CitationCardComponent extends Component<Args> {
|
|
|
27
26
|
get controller(): SayController;
|
|
28
27
|
get showCard(): false | Option<CitationDecoration>;
|
|
29
28
|
get plugin(): CitationPlugin;
|
|
30
|
-
get config():
|
|
31
|
-
endpoint: string;
|
|
32
|
-
};
|
|
29
|
+
get config(): CitationPluginEmberComponentConfig;
|
|
33
30
|
get decorations(): import("prosemirror-view").DecorationSet | undefined;
|
|
34
31
|
get activeDecoration(): Option<CitationDecoration>;
|
|
35
32
|
get searchText(): string;
|
|
36
|
-
get legislationTypes():
|
|
33
|
+
get legislationTypes(): ("Besluit" | "Decreet" | "Koninklijk besluit" | "Wet" | "Ministerieel besluit" | "Besluit van de vlaamse regering" | "Omzendbrief" | "Verdrag" | "Grondwet" | "Grondwetswijziging" | "Samenwerkingsakkoord" | "Wetboek" | "Gecoördineerde wetten" | "Bijzondere wet" | "Genummerd koninklijk besluit" | "Protocol")[];
|
|
37
34
|
get selectedLegislationType(): {
|
|
38
35
|
label: string;
|
|
39
36
|
value: string;
|
|
@@ -42,14 +39,14 @@ export default class CitationCardComponent extends Component<Args> {
|
|
|
42
39
|
get selectedLegislationTypeUri(): string;
|
|
43
40
|
resetToDocumentState(): void;
|
|
44
41
|
onCardTextChange(event: InputEvent): void;
|
|
45
|
-
resourceSearch: import("ember-concurrency").TaskForAsyncTaskFunction<unknown, () => Promise<
|
|
42
|
+
resourceSearch: import("ember-concurrency").TaskForAsyncTaskFunction<unknown, () => Promise<LegalDocument[]>>;
|
|
46
43
|
decisionResource: import("ember-resources/util/ember-concurrency").TaskInstance<unknown>;
|
|
47
44
|
selectLegislationType(type: string): void;
|
|
48
|
-
openDecisionDetailModal(decision:
|
|
45
|
+
openDecisionDetailModal(decision: LegalDocument): void;
|
|
49
46
|
openSearchModal(): Promise<void>;
|
|
50
47
|
closeModal(lastSearchType: string, lastSearchTerm: string): void;
|
|
51
|
-
insertDecisionCitation(decision:
|
|
52
|
-
insertArticleCitation(decision:
|
|
48
|
+
insertDecisionCitation(decision: LegalDocument): void;
|
|
49
|
+
insertArticleCitation(decision: LegalDocument, article: Article): void;
|
|
53
50
|
focus(): void;
|
|
54
51
|
willDestroy(): void;
|
|
55
52
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import Component from '@glimmer/component';
|
|
2
2
|
import { SayController } from '@lblod/ember-rdfa-editor';
|
|
3
|
-
import { Article, Decision } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/vlaamse-codex';
|
|
4
3
|
import { CitationPluginEmberComponentConfig } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin';
|
|
4
|
+
import { Article } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/article';
|
|
5
|
+
import { LegalDocument } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/legal-documents';
|
|
5
6
|
interface Args {
|
|
6
7
|
controller: SayController;
|
|
7
8
|
config: CitationPluginEmberComponentConfig;
|
|
@@ -22,7 +23,7 @@ export default class EditorPluginsCitationInsertComponent extends Component<Args
|
|
|
22
23
|
get controller(): SayController;
|
|
23
24
|
openModal(): void;
|
|
24
25
|
closeModal(): void;
|
|
25
|
-
insertDecisionCitation(decision:
|
|
26
|
-
insertArticleCitation(decision:
|
|
26
|
+
insertDecisionCitation(decision: LegalDocument): void;
|
|
27
|
+
insertArticleCitation(decision: LegalDocument, article: Article): void;
|
|
27
28
|
}
|
|
28
29
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Component from '@glimmer/component';
|
|
2
|
-
import {
|
|
2
|
+
import { LegalDocument } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/legal-documents';
|
|
3
3
|
interface Args {
|
|
4
|
-
decision:
|
|
4
|
+
decision: LegalDocument;
|
|
5
5
|
close: () => void;
|
|
6
6
|
config: {
|
|
7
7
|
endpoint: string;
|
|
@@ -16,7 +16,7 @@ export default class EditorPluginsCitationsDecisionDetailComponent extends Compo
|
|
|
16
16
|
articleFilter: string;
|
|
17
17
|
articleFilterAfterTimeout: string;
|
|
18
18
|
updateArticleFilter: import("ember-concurrency").TaskForAsyncTaskFunction<unknown, () => Promise<void>>;
|
|
19
|
-
resourceSearch: import("ember-concurrency").TaskForAsyncTaskFunction<unknown, () => Promise<import("
|
|
19
|
+
resourceSearch: import("ember-concurrency").TaskForAsyncTaskFunction<unknown, () => Promise<import("@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/article").Article[]>>;
|
|
20
20
|
articleResource: import("ember-resources/util/ember-concurrency").TaskInstance<unknown>;
|
|
21
21
|
close(): Promise<void>;
|
|
22
22
|
previousPage(): void;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import Component from '@glimmer/component';
|
|
2
|
+
import { LegalDocument } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/citation-plugin/utils/legal-documents';
|
|
3
|
+
interface Args {
|
|
4
|
+
decision: LegalDocument;
|
|
5
|
+
}
|
|
6
|
+
export default class DecisionPreviewComponent extends Component<Args> {
|
|
7
|
+
get isBesluit(): boolean;
|
|
8
|
+
get hasPublicationLink(): unknown;
|
|
9
|
+
}
|
|
10
|
+
export {};
|