From 8965cea1008669f7df8828e5fca6d20df86c8faf Mon Sep 17 00:00:00 2001 From: Deniss Kozickis Date: Fri, 17 May 2024 16:12:20 +0300 Subject: [PATCH] GN-4693: WIP --- addon/components/lpdc-plugin/lpdc-card.hbs | 66 +++++++++ addon/components/lpdc-plugin/lpdc-card.ts | 127 ++++++++++++++++++ addon/components/lpdc-plugin/lpdc-list.hbs | 18 +++ addon/components/lpdc-plugin/lpdc-list.ts | 9 ++ addon/components/lpdc-plugin/lpdc-preview.hbs | 19 +++ addon/components/lpdc-plugin/lpdc-preview.ts | 12 ++ addon/plugins/lpdc-plugin/api.ts | 63 +++++++++ addon/plugins/lpdc-plugin/index.ts | 2 + addon/plugins/lpdc-plugin/types.ts | 5 + addon/utils/constants.ts | 4 + app/components/lpdc-plugin/lpdc-card.ts | 1 + app/components/lpdc-plugin/lpdc-list.ts | 1 + app/components/lpdc-plugin/lpdc-preview.ts | 1 + tests/dummy/app/controllers/besluit-sample.ts | 5 +- tests/dummy/app/templates/besluit-sample.hbs | 24 ++-- translations/en-US.yaml | 9 ++ 16 files changed, 354 insertions(+), 12 deletions(-) create mode 100644 addon/components/lpdc-plugin/lpdc-card.hbs create mode 100644 addon/components/lpdc-plugin/lpdc-card.ts create mode 100644 addon/components/lpdc-plugin/lpdc-list.hbs create mode 100644 addon/components/lpdc-plugin/lpdc-list.ts create mode 100644 addon/components/lpdc-plugin/lpdc-preview.hbs create mode 100644 addon/components/lpdc-plugin/lpdc-preview.ts create mode 100644 addon/plugins/lpdc-plugin/api.ts create mode 100644 addon/plugins/lpdc-plugin/index.ts create mode 100644 addon/plugins/lpdc-plugin/types.ts create mode 100644 app/components/lpdc-plugin/lpdc-card.ts create mode 100644 app/components/lpdc-plugin/lpdc-list.ts create mode 100644 app/components/lpdc-plugin/lpdc-preview.ts diff --git a/addon/components/lpdc-plugin/lpdc-card.hbs b/addon/components/lpdc-plugin/lpdc-card.hbs new file mode 100644 index 000000000..838ee378d --- /dev/null +++ b/addon/components/lpdc-plugin/lpdc-card.hbs @@ -0,0 +1,66 @@ +{{! @glint-nocheck: not typesafe yet }} + + + {{t 'lpdc-plugin.card.title'}} + + +
+ + {{t 'lpdc-plugin.search.term'}} + + +
+
+ + {{#if this.lpdcResource.isRunning}} + + {{t + 'lpdc-plugin.alert.loading' + }} + {{else}} + {{#if this.error}} + + {{else}} + + {{t + 'lpdc-plugin.card.suggestions' + }} + +
+ +
+ {{/if}} + {{/if}} +
+
\ No newline at end of file diff --git a/addon/components/lpdc-plugin/lpdc-card.ts b/addon/components/lpdc-plugin/lpdc-card.ts new file mode 100644 index 000000000..700f3361c --- /dev/null +++ b/addon/components/lpdc-plugin/lpdc-card.ts @@ -0,0 +1,127 @@ +import { SearchIcon } from '@appuniversum/ember-appuniversum/components/icons/search'; +import Component from '@glimmer/component'; +import { task as trackedTask } from 'ember-resources/util/ember-concurrency'; +import { restartableTask, timeout } from 'ember-concurrency'; +import { tracked } from '@glimmer/tracking'; +import { + fetchLpdcs, + LPDC, + type LpdcPluginConfig, +} from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/lpdc-plugin'; +import { v4 as uuidv4 } from 'uuid'; +import { action } from '@ember/object'; +import { SayController } from '@lblod/ember-rdfa-editor'; +import { getCurrentBesluitRange } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/besluit-topic-plugin/utils/helpers'; +import { sayDataFactory } from '@lblod/ember-rdfa-editor/core/say-data-factory'; +import { addProperty } from '@lblod/ember-rdfa-editor/commands'; +import { + RDF, + SRO, +} from '@lblod/ember-rdfa-editor-lblod-plugins/utils/constants'; + +interface Args { + config: LpdcPluginConfig; + controller: SayController; +} + +export default class LpdcCardComponent extends Component { + SearchIcon = SearchIcon; + + @tracked error: unknown; + + @tracked searchText = ''; + + /** + * Paginating the search results + */ + @tracked pageNumber = 0; + @tracked pageSize = 5; + @tracked totalSize = 0; + @tracked totalCount = 0; + + get controller(): SayController { + return this.args.controller; + } + + lpdcSearch = restartableTask(async () => { + await timeout(100); + this.error = null; + const abortController = new AbortController(); + try { + const results = await fetchLpdcs({ + filter: { + name: this.searchText, + }, + pageNumber: this.pageNumber, + pageSize: this.pageSize, + config: this.args.config, + }); + this.totalCount = results.totalCount; + return results.lpdc; + } catch (error) { + this.totalCount = 0; + this.error = error; + return []; + } finally { + //Abort all requests now that this task has either successfully finished or has been cancelled + abortController.abort(); + } + }); + + lpdcResource = trackedTask(this, this.lpdcSearch, () => [ + this.searchText, + this.pageNumber, + this.pageSize, + ]); + + @action onSearchTextChange(event: InputEvent): void { + this.searchText = (event.target as HTMLInputElement).value; + } + + @action + onLpdcInsert(lpdc: LPDC) { + const rdfaId = uuidv4(); + + const uri = lpdc.uri; + const name = lpdc.name; + + const currentBesluitRange = getCurrentBesluitRange(this.controller); + + const resource = + (currentBesluitRange && + 'node' in currentBesluitRange && + (currentBesluitRange.node.attrs.subject as string)) || + undefined; + + if (!resource) { + throw new Error('No besluit found in selection'); + } + + this.controller.withTransaction( + (tr) => { + const node = this.controller.schema.node( + 'inline_rdfa', + { + rdfaNodeType: 'literal', + __rdfaId: rdfaId, + subject: uri, + }, + [this.controller.schema.text(name)], + ); + + return tr.replaceSelectionWith(node); + }, + { view: this.controller.mainEditorView }, + ); + + this.controller.doCommand( + addProperty({ + resource, + property: { + predicate: SRO('bekrachtigt').full, + object: sayDataFactory.literalNode(rdfaId), + }, + }), + ); + } +} diff --git a/addon/components/lpdc-plugin/lpdc-list.hbs b/addon/components/lpdc-plugin/lpdc-list.hbs new file mode 100644 index 000000000..0c438dcfa --- /dev/null +++ b/addon/components/lpdc-plugin/lpdc-list.hbs @@ -0,0 +1,18 @@ +{{! @glint-nocheck: not typesafe yet }} +{{#if @lpdc.length}} + + {{#each @lpdc as |lpdc|}} + + + + {{/each}} + +{{else}} + +{{/if}} \ No newline at end of file diff --git a/addon/components/lpdc-plugin/lpdc-list.ts b/addon/components/lpdc-plugin/lpdc-list.ts new file mode 100644 index 000000000..4cec819a1 --- /dev/null +++ b/addon/components/lpdc-plugin/lpdc-list.ts @@ -0,0 +1,9 @@ +import Component from '@glimmer/component'; + +import { LPDC } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/lpdc-plugin'; + +interface Args { + onLpdcInsert: (lpdc: LPDC) => void; +} + +export default class LpdcListComponent extends Component {} diff --git a/addon/components/lpdc-plugin/lpdc-preview.hbs b/addon/components/lpdc-plugin/lpdc-preview.hbs new file mode 100644 index 000000000..217326c9a --- /dev/null +++ b/addon/components/lpdc-plugin/lpdc-preview.hbs @@ -0,0 +1,19 @@ +{{! @glint-nocheck: not typesafe yet }} +
+

+ {{@lpdc.name}} +

+
+ + {{t 'lpdc-plugin.card.insert'}} + +
+
\ No newline at end of file diff --git a/addon/components/lpdc-plugin/lpdc-preview.ts b/addon/components/lpdc-plugin/lpdc-preview.ts new file mode 100644 index 000000000..a89076b29 --- /dev/null +++ b/addon/components/lpdc-plugin/lpdc-preview.ts @@ -0,0 +1,12 @@ +import Component from '@glimmer/component'; +import { PlusTextIcon } from '@appuniversum/ember-appuniversum/components/icons/plus-text'; + +import { LPDC } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/lpdc-plugin'; + +interface Args { + onLpdcInsert: (lpdc: LPDC) => void; +} + +export default class LpdcPreviewComponent extends Component { + PlusTextIcon = PlusTextIcon; +} diff --git a/addon/plugins/lpdc-plugin/api.ts b/addon/plugins/lpdc-plugin/api.ts new file mode 100644 index 000000000..b1f87e5e4 --- /dev/null +++ b/addon/plugins/lpdc-plugin/api.ts @@ -0,0 +1,63 @@ +import { LPDC } from '@lblod/ember-rdfa-editor-lblod-plugins/plugins/lpdc-plugin/types'; + +import { LpdcPluginConfig } from './index'; + +type LPDCInstance = { + id: string; // UUID + '@id': string; // URI + naam: { + nl: string; + }; + linkedConcept: string; // URI of linked concept + linkedConceptId: string; // UUID of linked concept + linkedConceptProductnummer: string; +}; + +type FetchResults = { + hydraPageIndex: number; + hydraLimit: number; + hydraTotalItems: number; + hydraMember: Array; +}; + +export const fetchLpdcs = async ({ + config, + filter, + pageNumber, + pageSize, +}: { + pageNumber: number; + pageSize: number; + config: LpdcPluginConfig; + filter?: { + name?: string; + }; +}): Promise<{ + lpdc: Array; + totalCount: number; +}> => { + const endpoint = config?.endpoint; + + const url = new URL(`${endpoint}/doc/instantie`); + + if (filter?.name) { + url.searchParams.append('zoekterm', filter.name); + } + + const results = await fetch(url.toString(), { + method: 'GET', + headers: { + Accept: 'application/json', + }, + }); + + const resultJson = (await results.json()) as FetchResults; + + return { + lpdc: resultJson.hydraMember.map((lpdc) => ({ + uri: lpdc['@id'], + name: lpdc.naam.nl, + })), + totalCount: resultJson.hydraTotalItems, + }; +}; diff --git a/addon/plugins/lpdc-plugin/index.ts b/addon/plugins/lpdc-plugin/index.ts new file mode 100644 index 000000000..35829bc3b --- /dev/null +++ b/addon/plugins/lpdc-plugin/index.ts @@ -0,0 +1,2 @@ +export { type LpdcPluginConfig, LPDC } from './types'; +export { fetchLpdcs } from './api'; diff --git a/addon/plugins/lpdc-plugin/types.ts b/addon/plugins/lpdc-plugin/types.ts new file mode 100644 index 000000000..c1567f41c --- /dev/null +++ b/addon/plugins/lpdc-plugin/types.ts @@ -0,0 +1,5 @@ +export type LpdcPluginConfig = { + endpoint: string; +}; + +export type LPDC = { uri: string; name: string }; diff --git a/addon/utils/constants.ts b/addon/utils/constants.ts index c67dd45a2..92567979b 100644 --- a/addon/utils/constants.ts +++ b/addon/utils/constants.ts @@ -31,3 +31,7 @@ export const GEOSPARQL = namespace( 'http://www.opengis.net/ont/geosparql#', 'geosparql', ); +export const SRO = namespace( + 'https://data.vlaanderen.be/ns/slimmeraadpleegomgeving#', + 'sro', +); diff --git a/app/components/lpdc-plugin/lpdc-card.ts b/app/components/lpdc-plugin/lpdc-card.ts new file mode 100644 index 000000000..b975f5f5f --- /dev/null +++ b/app/components/lpdc-plugin/lpdc-card.ts @@ -0,0 +1 @@ +export { default } from '@lblod/ember-rdfa-editor-lblod-plugins/components/lpdc-plugin/lpdc-card'; diff --git a/app/components/lpdc-plugin/lpdc-list.ts b/app/components/lpdc-plugin/lpdc-list.ts new file mode 100644 index 000000000..c1053d316 --- /dev/null +++ b/app/components/lpdc-plugin/lpdc-list.ts @@ -0,0 +1 @@ +export { default } from '@lblod/ember-rdfa-editor-lblod-plugins/components/lpdc-plugin/lpdc-list'; diff --git a/app/components/lpdc-plugin/lpdc-preview.ts b/app/components/lpdc-plugin/lpdc-preview.ts new file mode 100644 index 000000000..58ec477ac --- /dev/null +++ b/app/components/lpdc-plugin/lpdc-preview.ts @@ -0,0 +1 @@ +export { default } from '@lblod/ember-rdfa-editor-lblod-plugins/components/lpdc-plugin/lpdc-preview'; diff --git a/tests/dummy/app/controllers/besluit-sample.ts b/tests/dummy/app/controllers/besluit-sample.ts index a37703db2..355f86963 100644 --- a/tests/dummy/app/controllers/besluit-sample.ts +++ b/tests/dummy/app/controllers/besluit-sample.ts @@ -269,7 +269,7 @@ export default class BesluitSampleController extends Controller { citation: { type: 'nodes', activeInNodeTypes(schema: Schema): Set { - return new Set([schema.nodes.motivering]); + return new Set([schema.nodes.doc]); }, endpoint: 'https://codex.opendata.api.vlaanderen.be:8888/sparql', decisionsEndpoint: @@ -302,6 +302,9 @@ export default class BesluitSampleController extends Controller { worship: { endpoint: 'https://data.lblod.info/sparql', }, + lpdc: { + endpoint: 'http://localhost/lpdc-service', + }, }; } diff --git a/tests/dummy/app/templates/besluit-sample.hbs b/tests/dummy/app/templates/besluit-sample.hbs index 792ce819a..c38d4905b 100644 --- a/tests/dummy/app/templates/besluit-sample.hbs +++ b/tests/dummy/app/templates/besluit-sample.hbs @@ -149,6 +149,10 @@ @plugin={{this.citationPlugin}} @config={{this.config.citation}} /> + - {{#if (and this.activeNode this.editableNodes)}} - - - - {{/if}} + + + {{/if}} diff --git a/translations/en-US.yaml b/translations/en-US.yaml index eaebef708..1ee427515 100644 --- a/translations/en-US.yaml +++ b/translations/en-US.yaml @@ -416,3 +416,12 @@ worship-plugin: sort: Sort asc: Sort ascending desc: Sort descending + +lpdc-plugin: + card: + title: Insert LPDC + suggestions: Suggestions + insert: Insert + search: + term: Search for LPDC + placeholder: LPDC Name/Description