diff --git a/cypress/e2e/graphwise-reactodia/graphwise-reactodia.cy.js b/cypress/e2e/graphwise-reactodia/graphwise-reactodia.cy.js index 6966c97..1020c67 100644 --- a/cypress/e2e/graphwise-reactodia/graphwise-reactodia.cy.js +++ b/cypress/e2e/graphwise-reactodia/graphwise-reactodia.cy.js @@ -55,4 +55,27 @@ describe('graphwise-reactodia', () => { // Then the @Watch handler re-renders in place - the workspace is rebuilt, not torn down GraphwiseReactodiaSteps.getWorkspace().should('exist'); }); + + it('Should seed the canvas only from the seed present when the workspace mounts', () => { + // Given a workspace mounted without a seed + GraphwiseReactodiaSteps.provideRequiredProps(); + GraphwiseReactodiaSteps.getCanvas().should('exist'); + // Then nothing should be placed on the canvas + GraphwiseReactodiaSteps.getElements().should('not.exist'); + + // When, I re-visit the page with a seed + GraphwiseReactodiaSteps.visit(); + GraphwiseReactodiaSteps.setSeed(); + GraphwiseReactodiaSteps.provideRequiredProps(); + + // Then each seeded IRI should be placed on the canvas as an element + GraphwiseReactodiaSteps.getElements().should('have.length', 2); + + // When, I switch the language to French (effectively reloading the workspace) + GraphwiseReactodiaSteps.switchToFrench(); + + // Then, the language should be switched, and the number of nodes should be the same, because the layout should be + // preserved before switching + GraphwiseReactodiaSteps.getElements().should('have.length', 2); + }); }); diff --git a/cypress/steps/graphwise-reactodia-steps.js b/cypress/steps/graphwise-reactodia-steps.js index c9898bb..caf7823 100644 --- a/cypress/steps/graphwise-reactodia-steps.js +++ b/cypress/steps/graphwise-reactodia-steps.js @@ -19,6 +19,10 @@ export class GraphwiseReactodiaSteps { return this.getComponent().find('.reactodia-unified-search__search-input'); } + static getElements() { + return this.getCanvas().find('[data-element-id]'); + } + static setQueryFunction() { cy.getByTestId('set-query-function').click(); } @@ -36,6 +40,10 @@ export class GraphwiseReactodiaSteps { cy.getByTestId('switch-repository').click(); } + static setSeed() { + cy.getByTestId('set-seed').click(); + } + static switchToFrench() { cy.getByTestId('set-language-fr').click(); } diff --git a/package-lock.json b/package-lock.json index b6e0efa..0a324e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "graphwise-reactodia", - "version": "0.0.1-TR5", + "version": "0.0.1-TR6", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "graphwise-reactodia", - "version": "0.0.1-TR5", + "version": "0.0.1-TR6", "license": "Apache-2.0", "devDependencies": { "@rdfjs/types": "^2.0.1", diff --git a/package.json b/package.json index bcb0943..d3f1c37 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,23 @@ { "name": "graphwise-reactodia", - "version": "0.0.1-TR5", + "version": "0.0.1-TR6", "description": "Graphwise wrapper around the Reactodia graph explorer.", "license": "Apache-2.0", "author": "Ontotext AD", "main": "dist/index.cjs.js", + "module": "dist/esm/index.js", "collection": "dist/collection/collection-manifest.json", + "exports": { + ".": { + "import": "./dist/graphwise-reactodia/graphwise-reactodia.esm.js", + "require": "./dist/index.cjs.js" + }, + "./loader": { + "import": "./loader/index.js", + "require": "./loader/index.cjs.js", + "types": "./loader/index.d.ts" + } + }, "files": [ "dist/", "loader/" diff --git a/src/components.d.ts b/src/components.d.ts index 99e29cf..142564a 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -5,45 +5,49 @@ * It contains typing information for all components that exist in this project. */ import { HTMLStencilElement, JSXBase } from "@stencil/core/internal"; -import { SparqlDataProviderSettings, SparqlQueryFunction } from "@reactodia/workspace"; -export { SparqlDataProviderSettings, SparqlQueryFunction } from "@reactodia/workspace"; +import { ReactodiaConfig } from "./components/graphwise-reactodia/models/reactodia-config"; +import { LanguageKey } from "./components/graphwise-reactodia/i18n/language-key"; +import { SparqlDataProviderSettings } from "@reactodia/workspace"; +export { ReactodiaConfig } from "./components/graphwise-reactodia/models/reactodia-config"; +export { LanguageKey } from "./components/graphwise-reactodia/i18n/language-key"; +export { SparqlDataProviderSettings } from "@reactodia/workspace"; export namespace Components { /** * A web component that renders a graph with the Reactodia workspace. * The component is backed by a SPARQL endpoint but is endpoint-agnostic: the host passes - * the active repository's endpoint via `current-repository` and a `queryFunction` that - * performs the actual HTTP request. Reactodia fetches all node, link and type data lazily - * through them; the canvas starts empty and the user populates it via the search bar. + * the active repository's endpoint via `current-repository` and a `config.queryFunction` + * that performs the actual HTTP request. Reactodia fetches all node, link and type data + * lazily through them; the canvas starts empty and the user populates it via the search bar. * The component is a thin wrapper around Reactodia: query configuration lives outside the * wrapper and is supplied through the `providerSettings` prop. */ interface GraphwiseReactodia { /** - * The active repository id. Appended to {@link queryFunction} as the request `url`; changing it re-points the graph at the new repository (and resets the canvas), which is how runtime repository changes are handled. + * Host-supplied configuration: the SPARQL `queryFunction` transport and an optional `seed` set of entities to pre-populate the canvas with. A DOM property (an object, not an attribute) passed in from outside the wrapper. Read once on mount; not watched, as it only sets up the data source and initial canvas. */ - "currentRepository": string; + "config"?: ReactodiaConfig; + /** + * The active repository id. Appended to {@link queryFunction } as the request `url`; changing it re-points the graph at the new repository (and resets the canvas), which is how runtime repository changes are handled. + */ + "currentRepository"?: string; /** * UI language code (e.g. `en`, `fr`) for the Reactodia interface. Defaults to English. - * @default 'en' + * @default LanguageKey.EN */ - "language": string; + "language": LanguageKey; /** * Query preset for the SPARQL data provider, owned and configured by the host. A DOM property (an object, not an attribute) passed in from outside the wrapper. When omitted, the data provider falls back to Reactodia's generic OWL/RDFS preset. Changing it rebuilds the data provider and resets the canvas. */ "providerSettings"?: SparqlDataProviderSettings; - /** - * HTTP transport for the SPARQL requests. Set by the host so requests go through the host's HTTP layer (auth, interceptors) instead of a built-in `fetch`. - */ - "queryFunction": SparqlQueryFunction; } } declare global { /** * A web component that renders a graph with the Reactodia workspace. * The component is backed by a SPARQL endpoint but is endpoint-agnostic: the host passes - * the active repository's endpoint via `current-repository` and a `queryFunction` that - * performs the actual HTTP request. Reactodia fetches all node, link and type data lazily - * through them; the canvas starts empty and the user populates it via the search bar. + * the active repository's endpoint via `current-repository` and a `config.queryFunction` + * that performs the actual HTTP request. Reactodia fetches all node, link and type data + * lazily through them; the canvas starts empty and the user populates it via the search bar. * The component is a thin wrapper around Reactodia: query configuration lives outside the * wrapper and is supplied through the `providerSettings` prop. */ @@ -61,30 +65,30 @@ declare namespace LocalJSX { /** * A web component that renders a graph with the Reactodia workspace. * The component is backed by a SPARQL endpoint but is endpoint-agnostic: the host passes - * the active repository's endpoint via `current-repository` and a `queryFunction` that - * performs the actual HTTP request. Reactodia fetches all node, link and type data lazily - * through them; the canvas starts empty and the user populates it via the search bar. + * the active repository's endpoint via `current-repository` and a `config.queryFunction` + * that performs the actual HTTP request. Reactodia fetches all node, link and type data + * lazily through them; the canvas starts empty and the user populates it via the search bar. * The component is a thin wrapper around Reactodia: query configuration lives outside the * wrapper and is supplied through the `providerSettings` prop. */ interface GraphwiseReactodia { /** - * The active repository id. Appended to {@link queryFunction} as the request `url`; changing it re-points the graph at the new repository (and resets the canvas), which is how runtime repository changes are handled. + * Host-supplied configuration: the SPARQL `queryFunction` transport and an optional `seed` set of entities to pre-populate the canvas with. A DOM property (an object, not an attribute) passed in from outside the wrapper. Read once on mount; not watched, as it only sets up the data source and initial canvas. + */ + "config"?: ReactodiaConfig; + /** + * The active repository id. Appended to {@link queryFunction } as the request `url`; changing it re-points the graph at the new repository (and resets the canvas), which is how runtime repository changes are handled. */ "currentRepository"?: string; /** * UI language code (e.g. `en`, `fr`) for the Reactodia interface. Defaults to English. - * @default 'en' + * @default LanguageKey.EN */ - "language"?: string; + "language"?: LanguageKey; /** * Query preset for the SPARQL data provider, owned and configured by the host. A DOM property (an object, not an attribute) passed in from outside the wrapper. When omitted, the data provider falls back to Reactodia's generic OWL/RDFS preset. Changing it rebuilds the data provider and resets the canvas. */ "providerSettings"?: SparqlDataProviderSettings; - /** - * HTTP transport for the SPARQL requests. Set by the host so requests go through the host's HTTP layer (auth, interceptors) instead of a built-in `fetch`. - */ - "queryFunction"?: SparqlQueryFunction; } interface IntrinsicElements { "graphwise-reactodia": GraphwiseReactodia; @@ -97,9 +101,9 @@ declare module "@stencil/core" { /** * A web component that renders a graph with the Reactodia workspace. * The component is backed by a SPARQL endpoint but is endpoint-agnostic: the host passes - * the active repository's endpoint via `current-repository` and a `queryFunction` that - * performs the actual HTTP request. Reactodia fetches all node, link and type data lazily - * through them; the canvas starts empty and the user populates it via the search bar. + * the active repository's endpoint via `current-repository` and a `config.queryFunction` + * that performs the actual HTTP request. Reactodia fetches all node, link and type data + * lazily through them; the canvas starts empty and the user populates it via the search bar. * The component is a thin wrapper around Reactodia: query configuration lives outside the * wrapper and is supplied through the `providerSettings` prop. */ diff --git a/src/components/graphwise-reactodia/graphwise-reactodia.tsx b/src/components/graphwise-reactodia/graphwise-reactodia.tsx index 6af2491..5b1600e 100644 --- a/src/components/graphwise-reactodia/graphwise-reactodia.tsx +++ b/src/components/graphwise-reactodia/graphwise-reactodia.tsx @@ -1,15 +1,17 @@ import {Component, Element, h, Host, Prop, Watch} from '@stencil/core'; import {Root} from 'react-dom/client'; -import {SerializedDiagram, SparqlDataProviderSettings, SparqlQueryFunction} from '@reactodia/workspace'; +import {SerializedDiagram, SparqlDataProviderSettings} from '@reactodia/workspace'; import {exportReactodiaLayout, mountReactodia, unmountReactodia, updateReactodia} from './reactodia-app'; +import {LanguageKey} from './i18n/language-key'; +import {ReactodiaConfig} from './models/reactodia-config'; /** * A web component that renders a graph with the Reactodia workspace. * * The component is backed by a SPARQL endpoint but is endpoint-agnostic: the host passes - * the active repository's endpoint via `current-repository` and a `queryFunction` that - * performs the actual HTTP request. Reactodia fetches all node, link and type data lazily - * through them; the canvas starts empty and the user populates it via the search bar. + * the active repository's endpoint via `current-repository` and a `config.queryFunction` + * that performs the actual HTTP request. Reactodia fetches all node, link and type data + * lazily through them; the canvas starts empty and the user populates it via the search bar. * * The component is a thin wrapper around Reactodia: query configuration lives outside the * wrapper and is supplied through the `providerSettings` prop. @@ -19,25 +21,28 @@ import {exportReactodiaLayout, mountReactodia, unmountReactodia, updateReactodia styleUrl: 'graphwise-reactodia.scss', }) export class GraphwiseReactodia { - @Element() private readonly hostElement: HTMLElement; + @Element() private readonly hostElement?: HTMLElement; /** * The active repository id. Appended to {@link queryFunction} as the request `url`; * changing it re-points the graph at the new repository (and resets the canvas), * which is how runtime repository changes are handled. */ - @Prop() currentRepository: string; + @Prop() currentRepository?: string; /** - * HTTP transport for the SPARQL requests. Set by the host so requests go through the host's HTTP layer (auth, - * interceptors) instead of a built-in `fetch`. + * Host-supplied configuration: the SPARQL `queryFunction` transport and an optional `seed` + * set of entities to pre-populate the canvas with. A DOM property (an object, not an + * attribute) passed in from outside the wrapper. + * + * Read once on mount; not watched, as it only sets up the data source and initial canvas. */ - @Prop() queryFunction: SparqlQueryFunction; + @Prop() config?: ReactodiaConfig; /** * UI language code (e.g. `en`, `fr`) for the Reactodia interface. Defaults to English. */ - @Prop() language = 'en'; + @Prop() language = LanguageKey.EN; /** * Query preset for the SPARQL data provider, owned and configured by the host. A DOM @@ -47,7 +52,7 @@ export class GraphwiseReactodia { */ @Prop() providerSettings?: SparqlDataProviderSettings; - private reactRoot: Root; + private reactRoot?: Root; @Watch('currentRepository') @Watch('providerSettings') @@ -86,8 +91,8 @@ export class GraphwiseReactodia { throw new Error('currentRepository is required'); } - if (!this.queryFunction) { - throw new Error('queryFunction is required'); + if (!this.config?.queryFunction) { + throw new Error('config.queryFunction is required'); } if (!this.hostElement) { @@ -97,7 +102,7 @@ export class GraphwiseReactodia { const props = { initialDiagram, currentRepository: this.currentRepository, - queryFunction: this.queryFunction, + config: this.config, language: this.language, providerSettings: this.providerSettings, }; diff --git a/src/components/graphwise-reactodia/i18n/language-key.ts b/src/components/graphwise-reactodia/i18n/language-key.ts new file mode 100644 index 0000000..977753d --- /dev/null +++ b/src/components/graphwise-reactodia/i18n/language-key.ts @@ -0,0 +1,4 @@ +export enum LanguageKey { + EN = 'en', + FR = 'fr' +} diff --git a/src/components/graphwise-reactodia/i18n/translations.ts b/src/components/graphwise-reactodia/i18n/translations.ts index eb09e39..dd70386 100644 --- a/src/components/graphwise-reactodia/i18n/translations.ts +++ b/src/components/graphwise-reactodia/i18n/translations.ts @@ -1,5 +1,11 @@ import frTranslation from './fr.reactodia.translation.json'; +import {LanguageKey} from './language-key'; -export const TRANSLATIONS = { - 'fr': frTranslation +type TranslationBundle = { + [language: string]: Record; +}; + +// English is provided by default from reactodia so we don't need to include it here, unless we override it +export const TRANSLATIONS: Partial> = { + [LanguageKey.FR]: frTranslation } diff --git a/src/components/graphwise-reactodia/models/reactodia-app-props.ts b/src/components/graphwise-reactodia/models/reactodia-app-props.ts index ad71676..9b09cc8 100644 --- a/src/components/graphwise-reactodia/models/reactodia-app-props.ts +++ b/src/components/graphwise-reactodia/models/reactodia-app-props.ts @@ -1,4 +1,6 @@ -import {SerializedDiagram, SparqlDataProviderSettings, SparqlQueryFunction} from '@reactodia/workspace'; +import {SerializedDiagram, SparqlDataProviderSettings} from '@reactodia/workspace'; +import {LanguageKey} from '../i18n/language-key'; +import {ReactodiaConfig} from './reactodia-config'; /** * Props for the internal Reactodia React application. @@ -6,21 +8,21 @@ import {SerializedDiagram, SparqlDataProviderSettings, SparqlQueryFunction} from export interface ReactodiaAppProps { /** * The active repository id. Passed to the SPARQL data provider as its `endpointUrl` and - * surfaced to {@link queryFunction} as the request `url`, which the host transport uses to - * target the repository. Changing it re-points the diagram at a different repository. + * surfaced to the {@link ReactodiaConfig.queryFunction} as the request `url`, which the host + * transport uses to target the repository. Changing it re-points the diagram at a different + * repository. */ currentRepository: string; /** - * Transport for the SPARQL requests. The host owns the connection (auth, interceptors, - * base URL) inside this function; Reactodia delegates every SPARQL call to it instead - * of using the built-in `fetch`. + * Host-supplied configuration read once on mount: the SPARQL transport and the optional + * set of entities to pre-populate the canvas with. */ - queryFunction: SparqlQueryFunction; + config: ReactodiaConfig; /** * UI language code (e.g. `en`, `fr`); selects the Reactodia translation bundle * and is also used as the initial graph-data language. */ - language: string; + language: LanguageKey; /** * A previously exported diagram to restore on mount. Used to carry the user's current * canvas across a remount (e.g. forced by a language change). When omitted, the canvas diff --git a/src/components/graphwise-reactodia/models/reactodia-config.ts b/src/components/graphwise-reactodia/models/reactodia-config.ts new file mode 100644 index 0000000..787a970 --- /dev/null +++ b/src/components/graphwise-reactodia/models/reactodia-config.ts @@ -0,0 +1,24 @@ +import {SparqlQueryFunction} from '@reactodia/workspace'; + +/** + * Host-supplied configuration read once when the workspace mounts (not reactive). + * + * Groups the inputs the host wires up before the graph is created: the SPARQL transport + * and the optional set of entities to pre-populate the canvas with. Passed to the + * `graphwise-reactodia` component as a single DOM property (an object, not an attribute). + */ +export interface ReactodiaConfig { + /** + * HTTP transport for the SPARQL requests. Set by the host so requests go through the host's + * HTTP layer (auth, interceptors) instead of a built-in `fetch`. + */ + queryFunction: SparqlQueryFunction; + /** + * IRIs of the entities to place on the canvas on startup. When provided, each IRI is added + * as an element and its data (labels, types, properties) and links are resolved from the + * SPARQL provider, then the workspace lays them out. Note that when using this seed method reactodia will request data + * from the connected sparql endpoint, so if the resources are not in the DB, then this approach will not work. + * (e.g. in the case of a construct query) + */ + seedIris?: string[]; +} diff --git a/src/components/graphwise-reactodia/reactodia-app.ts b/src/components/graphwise-reactodia/reactodia-app.ts index 9e30934..35e3253 100644 --- a/src/components/graphwise-reactodia/reactodia-app.ts +++ b/src/components/graphwise-reactodia/reactodia-app.ts @@ -5,8 +5,6 @@ import { OwlRdfsSettings, SerializedDiagram, SparqlDataProvider, - SparqlDataProviderSettings, - SparqlQueryFunction, useLoadedWorkspace, Workspace, WorkspaceContext, @@ -14,6 +12,7 @@ import { import {blockingDefaultLayout} from '@reactodia/workspace/layout-sync'; import {ReactodiaAppProps} from './models/reactodia-app-props'; import {TRANSLATIONS} from './i18n/translations'; +import {LanguageKey} from './i18n/language-key'; /** @@ -23,7 +22,7 @@ import {TRANSLATIONS} from './i18n/translations'; * Reactodia never re-reads the translations, so the component must be remounted * to switch the UI language (handled in `graphwise-reactodia.tsx`). */ -function translationsForLanguage(language: string): readonly object[] { +function translationsForLanguage(language: LanguageKey): readonly object[] { const translation = TRANSLATIONS[language] return translation ? [translation] : []; } @@ -40,16 +39,26 @@ let workspaceContext: WorkspaceContext | null = null; * query preset. The host owns the query configuration and passes it in via props; when none * is provided we fall back to Reactodia's generic {@link OwlRdfsSettings} OWL/RDFS preset. */ -function createDataProvider( - currentRepository: string, - queryFunction: SparqlQueryFunction, - settings?: SparqlDataProviderSettings -): SparqlDataProvider { +function createDataProvider(props: ReactodiaAppProps): SparqlDataProvider { + const {currentRepository, config, providerSettings} = props; return new SparqlDataProvider({ endpointUrl: currentRepository, queryMethod: 'POST', - queryFunction, - }, settings); + queryFunction: config.queryFunction, + }, providerSettings); +} + +/** + * Places the seed entities on the canvas. Each IRI is added as a placeholder element, and data is then loaded for the + * respective nodes using the {@link DataDiagramModel.requestData} method. + */ +async function seedCanvas(context: WorkspaceContext, seed: string[], signal: AbortSignal): Promise { + const {model, performLayout} = context; + for (const iri of seed) { + model.createElement(iri); + } + await model.requestData(); + await performLayout({signal}); } /** @@ -57,17 +66,17 @@ function createDataProvider( * * Authored with `React.createElement` (no TSX) on purpose, since there are differences in stencil and react * - * The canvas starts empty; the user populates it through the workspace search bar - * (Reactodia's `DefaultWorkspace` unified search), which is backed by the SPARQL - * data provider's lookup. + * Without a seed the canvas starts empty and the user populates it through the workspace + * search bar (Reactodia's `DefaultWorkspace` unified search), backed by the SPARQL data + * provider's lookup. With a seed, the seeded nodes are placed on the canvas on startup. */ function ReactodiaApp(props: ReactodiaAppProps) { - const {currentRepository, queryFunction, language, initialDiagram, providerSettings} = props; + const {language, initialDiagram, config} = props; const {onMount} = useLoadedWorkspace(async ({context, signal}) => { workspaceContext = context; const {model} = context; - const dataProvider = createDataProvider(currentRepository, queryFunction, providerSettings); + const dataProvider = createDataProvider(props); // A language change remounts this component to rebuild the workspace with the new // translation bundle; restoring the exported diagram keeps the user's canvas intact. // This is done because there is no existing mechanism to re-translate the UI at runtime (not for the UI labels at least) @@ -75,6 +84,9 @@ function ReactodiaApp(props: ReactodiaAppProps) { await model.importLayout({dataProvider, diagram: initialDiagram, signal}); } else { await model.createNewDiagram({dataProvider, signal}); + if (config.seedIris) { + await seedCanvas(context, config.seedIris, signal); + } } }, [language]); @@ -118,7 +130,7 @@ export async function updateReactodia(props: ReactodiaAppProps): Promise { return; } const {model} = workspaceContext; - const dataProvider = createDataProvider(props.currentRepository, props.queryFunction, props.providerSettings); + const dataProvider = createDataProvider(props); await model.createNewDiagram({dataProvider}); } diff --git a/src/components/graphwise-reactodia/readme.md b/src/components/graphwise-reactodia/readme.md index 947313f..1209e29 100644 --- a/src/components/graphwise-reactodia/readme.md +++ b/src/components/graphwise-reactodia/readme.md @@ -10,21 +10,21 @@ A web component that renders a graph with the Reactodia workspace. The component is backed by a SPARQL endpoint but is endpoint-agnostic: the host passes -the active repository's endpoint via `current-repository` and a `queryFunction` that -performs the actual HTTP request. Reactodia fetches all node, link and type data lazily -through them; the canvas starts empty and the user populates it via the search bar. +the active repository's endpoint via `current-repository` and a `config.queryFunction` +that performs the actual HTTP request. Reactodia fetches all node, link and type data +lazily through them; the canvas starts empty and the user populates it via the search bar. The component is a thin wrapper around Reactodia: query configuration lives outside the wrapper and is supplied through the `providerSettings` prop. ## Properties -| Property | Attribute | Description | Type | Default | -| ------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | -| `currentRepository` | `current-repository` | The active repository id. Appended to {@link queryFunction} as the request `url`; changing it re-points the graph at the new repository (and resets the canvas), which is how runtime repository changes are handled. | `string` | `undefined` | -| `language` | `language` | UI language code (e.g. `en`, `fr`) for the Reactodia interface. Defaults to English. | `string` | `'en'` | -| `providerSettings` | `provider-settings` | Query preset for the SPARQL data provider, owned and configured by the host. A DOM property (an object, not an attribute) passed in from outside the wrapper. When omitted, the data provider falls back to Reactodia's generic OWL/RDFS preset. Changing it rebuilds the data provider and resets the canvas. | `SparqlDataProviderSettings` | `undefined` | -| `queryFunction` | `query-function` | HTTP transport for the SPARQL requests. Set by the host so requests go through the host's HTTP layer (auth, interceptors) instead of a built-in `fetch`. | `(params: { url: string; body?: string; headers: { [header: string]: string; }; method: string; signal?: AbortSignal; }) => Promise` | `undefined` | +| Property | Attribute | Description | Type | Default | +| ------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- | ---------------- | +| `config` | `config` | Host-supplied configuration: the SPARQL `queryFunction` transport and an optional `seed` set of entities to pre-populate the canvas with. A DOM property (an object, not an attribute) passed in from outside the wrapper. Read once on mount; not watched, as it only sets up the data source and initial canvas. | `ReactodiaConfig` | `undefined` | +| `currentRepository` | `current-repository` | The active repository id. Appended to {@link queryFunction } as the request `url`; changing it re-points the graph at the new repository (and resets the canvas), which is how runtime repository changes are handled. | `string` | `undefined` | +| `language` | `language` | UI language code (e.g. `en`, `fr`) for the Reactodia interface. Defaults to English. | `LanguageKey.EN \| LanguageKey.FR` | `LanguageKey.EN` | +| `providerSettings` | `provider-settings` | Query preset for the SPARQL data provider, owned and configured by the host. A DOM property (an object, not an attribute) passed in from outside the wrapper. When omitted, the data provider falls back to Reactodia's generic OWL/RDFS preset. Changing it rebuilds the data provider and resets the canvas. | `SparqlDataProviderSettings` | `undefined` | ---------------------------------------------- diff --git a/src/pages/graphwise-reactodia/index.html b/src/pages/graphwise-reactodia/index.html index 2d0983f..9798a8e 100644 --- a/src/pages/graphwise-reactodia/index.html +++ b/src/pages/graphwise-reactodia/index.html @@ -34,6 +34,7 @@ + diff --git a/src/pages/graphwise-reactodia/main.js b/src/pages/graphwise-reactodia/main.js index b30abe0..11e47e8 100644 --- a/src/pages/graphwise-reactodia/main.js +++ b/src/pages/graphwise-reactodia/main.js @@ -1,21 +1,19 @@ -const EMPTY_SPARQL_RESULT = { - head: {vars: []}, - results: {bindings: []}, -}; - -function stubQueryFunction() { - return Promise.resolve( - new Response(JSON.stringify(EMPTY_SPARQL_RESULT), { - status: 200, - headers: {'Content-Type': 'application/sparql-results+json'}, - }) - ); +// Mock all responses as turtle, as we won't be making any SPARQL requests in the dev server. +async function stubQueryFunction(_params) { + return (new Response('', {headers: {'Content-Type': 'text/turtle'}})); } +// IRIs of the entities the host asks to pre-populate the canvas with on startup. +const SEED_NODES = ['http://example.com/alice', 'http://example.com/bob']; + const reactodia = document.querySelector('graphwise-reactodia'); function setQueryFunction() { - reactodia.queryFunction = stubQueryFunction; + reactodia.config = {...reactodia.config, queryFunction: stubQueryFunction}; +} + +function setSeed() { + reactodia.config = {...reactodia.config, seedIris: SEED_NODES}; } function setRepository(repository) {