graphwise-reactodia 0.0.1-TR11 → 0.0.1-TR13
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/dist/cjs/graphwise-reactodia.cjs.entry.js +192 -26
- package/dist/cjs/graphwise-reactodia.cjs.js +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/collection/components/graphwise-reactodia/graphwise-reactodia.css +3 -0
- package/dist/collection/components/graphwise-reactodia/graphwise-reactodia.js +13 -9
- package/dist/collection/components/graphwise-reactodia/i18n/translations.js +4 -1
- package/dist/collection/components/graphwise-reactodia/menu/graphwise-menu.js +37 -0
- package/dist/collection/components/graphwise-reactodia/reactodia-app.js +17 -10
- package/dist/collection/components/graphwise-reactodia/services/diagram/diagram.service.js +14 -0
- package/dist/collection/components/graphwise-reactodia/services/diagram-file/diagram-file.service.js +68 -0
- package/dist/collection/pages/graphwise-reactodia/main.js +6 -0
- package/dist/collection/pages/graphwise-reactodia/owl-rdfs-settings.js +195 -0
- package/dist/esm/graphwise-reactodia.entry.js +192 -26
- package/dist/esm/graphwise-reactodia.js +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/graphwise-reactodia/graphwise-reactodia.esm.js +1 -1
- package/dist/graphwise-reactodia/{p-81eeb4c3.entry.js → p-420b9dce.entry.js} +1 -1
- package/dist/types/components/graphwise-reactodia/graphwise-reactodia.d.ts +5 -5
- package/dist/types/components/graphwise-reactodia/menu/graphwise-menu.d.ts +9 -0
- package/dist/types/components/graphwise-reactodia/models/reactodia-app-props.d.ts +4 -4
- package/dist/types/components/graphwise-reactodia/reactodia-app.d.ts +3 -2
- package/dist/types/components/graphwise-reactodia/services/diagram/diagram.service.d.ts +11 -1
- package/dist/types/components/graphwise-reactodia/services/diagram-file/diagram-file.service.d.ts +24 -0
- package/dist/types/components.d.ts +2 -2
- package/package.json +2 -2
|
@@ -23868,6 +23868,35 @@ function ToolbarAction(props) {
|
|
|
23868
23868
|
});
|
|
23869
23869
|
}
|
|
23870
23870
|
/**
|
|
23871
|
+
* Toolbar action component to open a file selection dialog.
|
|
23872
|
+
*
|
|
23873
|
+
* @category Components
|
|
23874
|
+
*/
|
|
23875
|
+
function ToolbarActionOpen(props) {
|
|
23876
|
+
const { className, fileAccept, onSelect, children, ...otherProps } = props;
|
|
23877
|
+
const inputRef = reactExports.useRef(null);
|
|
23878
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [/* @__PURE__ */ jsxRuntimeExports.jsx(ToolbarAction, {
|
|
23879
|
+
...otherProps,
|
|
23880
|
+
className: clsx(className, `${CLASS_NAME$8}__open`),
|
|
23881
|
+
onSelect: () => {
|
|
23882
|
+
inputRef.current?.click();
|
|
23883
|
+
},
|
|
23884
|
+
children
|
|
23885
|
+
}), /* @__PURE__ */ jsxRuntimeExports.jsx("input", {
|
|
23886
|
+
ref: inputRef,
|
|
23887
|
+
role: "none",
|
|
23888
|
+
type: "file",
|
|
23889
|
+
className: `${CLASS_NAME$8}__open-input`,
|
|
23890
|
+
accept: fileAccept,
|
|
23891
|
+
onChange: (e) => {
|
|
23892
|
+
if (e.currentTarget.files) {
|
|
23893
|
+
const file = e.currentTarget.files[0];
|
|
23894
|
+
onSelect(file);
|
|
23895
|
+
}
|
|
23896
|
+
}
|
|
23897
|
+
})] });
|
|
23898
|
+
}
|
|
23899
|
+
/**
|
|
23871
23900
|
* Toolbar action component to clear diagram content.
|
|
23872
23901
|
*
|
|
23873
23902
|
* Clearing the diagram adds a command to the command history.
|
|
@@ -30846,6 +30875,16 @@ function getContentFittingBoxForLayout(state) {
|
|
|
30846
30875
|
};
|
|
30847
30876
|
}
|
|
30848
30877
|
|
|
30878
|
+
const graphwise_toolbar_action$1 = {
|
|
30879
|
+
"download_diagram.label": "Export to JSON",
|
|
30880
|
+
"download_diagram.title": "Export the diagram to a JSON file",
|
|
30881
|
+
"upload_diagram.label": "Import from JSON",
|
|
30882
|
+
"upload_diagram.title": "Replace the diagram with one from a JSON file"
|
|
30883
|
+
};
|
|
30884
|
+
var enTranslation = {
|
|
30885
|
+
graphwise_toolbar_action: graphwise_toolbar_action$1
|
|
30886
|
+
};
|
|
30887
|
+
|
|
30849
30888
|
const authoring_state = {
|
|
30850
30889
|
"entity_action_delete.label": "supprimer",
|
|
30851
30890
|
"entity_action_delete.title": "Supprimer l'entité",
|
|
@@ -31100,6 +31139,12 @@ const standard_link = {
|
|
|
31100
31139
|
const toolbar = {
|
|
31101
31140
|
"menu_toggle.title": "Ouvrir le menu"
|
|
31102
31141
|
};
|
|
31142
|
+
const graphwise_toolbar_action = {
|
|
31143
|
+
"download_diagram.label": "Exporter en JSON",
|
|
31144
|
+
"download_diagram.title": "Exporter le diagramme en fichier JSON",
|
|
31145
|
+
"upload_diagram.label": "Importer depuis JSON",
|
|
31146
|
+
"upload_diagram.title": "Remplacer le diagramme par celui d'un fichier JSON"
|
|
31147
|
+
};
|
|
31103
31148
|
const toolbar_action = {
|
|
31104
31149
|
"clear_all.command": "Tout effacer",
|
|
31105
31150
|
"clear_all.title": "Supprimer tous les éléments et liens du diagramme",
|
|
@@ -31210,6 +31255,7 @@ var frTranslation = {
|
|
|
31210
31255
|
standard_element: standard_element,
|
|
31211
31256
|
standard_link: standard_link,
|
|
31212
31257
|
toolbar: toolbar,
|
|
31258
|
+
graphwise_toolbar_action: graphwise_toolbar_action,
|
|
31213
31259
|
toolbar_action: toolbar_action,
|
|
31214
31260
|
unified_search: unified_search,
|
|
31215
31261
|
visual_authoring: visual_authoring,
|
|
@@ -31224,8 +31270,10 @@ var LanguageKey;
|
|
|
31224
31270
|
LanguageKey["FR"] = "fr";
|
|
31225
31271
|
})(LanguageKey || (LanguageKey = {}));
|
|
31226
31272
|
|
|
31227
|
-
// English is provided by default from reactodia so
|
|
31273
|
+
// English is provided by default from reactodia, so the English bundle holds only our own keys and overrides. If
|
|
31274
|
+
// A key is missing, reactodia defaults to its own translation.
|
|
31228
31275
|
const TRANSLATIONS = {
|
|
31276
|
+
[LanguageKey.EN]: enTranslation,
|
|
31229
31277
|
[LanguageKey.FR]: frTranslation
|
|
31230
31278
|
};
|
|
31231
31279
|
|
|
@@ -31285,7 +31333,7 @@ function Service(_serviceClass) {
|
|
|
31285
31333
|
// no implementation needed. We only use the type checking of the parameter
|
|
31286
31334
|
}
|
|
31287
31335
|
|
|
31288
|
-
var __decorate$
|
|
31336
|
+
var __decorate$4 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
31289
31337
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
31290
31338
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
31291
31339
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
@@ -31296,6 +31344,20 @@ var DiagramService_1;
|
|
|
31296
31344
|
* Service for diagram related operations and subscriptions
|
|
31297
31345
|
*/
|
|
31298
31346
|
let DiagramService = DiagramService_1 = class DiagramService {
|
|
31347
|
+
/**
|
|
31348
|
+
* Replaces the diagram content with the given serialization. Element data is requested from the data provider and
|
|
31349
|
+
* the links between the imported elements are validated against it.
|
|
31350
|
+
*
|
|
31351
|
+
* @param model The diagram model to import into.
|
|
31352
|
+
* @param dataProvider The data provider to bind to the diagram.
|
|
31353
|
+
* @param diagram The serialization to import. When `undefined`, the diagram is cleared.
|
|
31354
|
+
* @param signal Optional signal to abort the import.
|
|
31355
|
+
*/
|
|
31356
|
+
importDiagram(model, dataProvider, diagram, signal) {
|
|
31357
|
+
// selection is not cleared on import, so we clear it manually to avoid painting the previous selection
|
|
31358
|
+
model.setSelection([]);
|
|
31359
|
+
return model.importLayout({ dataProvider, diagram, signal, validateLinks: true });
|
|
31360
|
+
}
|
|
31299
31361
|
/**
|
|
31300
31362
|
* Subscribes to diagram changes. On every debounced change the current layout is
|
|
31301
31363
|
* exported and passed to the callback.
|
|
@@ -31330,11 +31392,11 @@ let DiagramService = DiagramService_1 = class DiagramService {
|
|
|
31330
31392
|
DiagramService.ID = 'DiagramService';
|
|
31331
31393
|
DiagramService.NOTIFY_DEBOUNCE_MS = 300;
|
|
31332
31394
|
DiagramService.HISTORY_CHANGED_EVENT = 'historyChanged';
|
|
31333
|
-
DiagramService = DiagramService_1 = __decorate$
|
|
31395
|
+
DiagramService = DiagramService_1 = __decorate$4([
|
|
31334
31396
|
Service
|
|
31335
31397
|
], DiagramService);
|
|
31336
31398
|
|
|
31337
|
-
var __decorate$
|
|
31399
|
+
var __decorate$3 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
31338
31400
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
31339
31401
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
31340
31402
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
@@ -31349,11 +31411,11 @@ let WindowService = class WindowService {
|
|
|
31349
31411
|
}
|
|
31350
31412
|
};
|
|
31351
31413
|
WindowService.ID = 'WindowService';
|
|
31352
|
-
WindowService = __decorate$
|
|
31414
|
+
WindowService = __decorate$3([
|
|
31353
31415
|
Service
|
|
31354
31416
|
], WindowService);
|
|
31355
31417
|
|
|
31356
|
-
var __decorate$
|
|
31418
|
+
var __decorate$2 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
31357
31419
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
31358
31420
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
31359
31421
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
@@ -31397,11 +31459,11 @@ let DiagramStorageService = DiagramStorageService_1 = class DiagramStorageServic
|
|
|
31397
31459
|
};
|
|
31398
31460
|
DiagramStorageService.ID = 'DiagramStorageService';
|
|
31399
31461
|
DiagramStorageService.STORAGE_KEY = 'diagram.state';
|
|
31400
|
-
DiagramStorageService = DiagramStorageService_1 = __decorate$
|
|
31462
|
+
DiagramStorageService = DiagramStorageService_1 = __decorate$2([
|
|
31401
31463
|
Service
|
|
31402
31464
|
], DiagramStorageService);
|
|
31403
31465
|
|
|
31404
|
-
var __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
31466
|
+
var __decorate$1 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
31405
31467
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
31406
31468
|
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
31407
31469
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
@@ -31424,7 +31486,7 @@ let EventService = class EventService {
|
|
|
31424
31486
|
}
|
|
31425
31487
|
};
|
|
31426
31488
|
EventService.ID = 'EventService';
|
|
31427
|
-
EventService = __decorate([
|
|
31489
|
+
EventService = __decorate$1([
|
|
31428
31490
|
Service
|
|
31429
31491
|
], EventService);
|
|
31430
31492
|
|
|
@@ -31518,8 +31580,102 @@ const resetColors = () => {
|
|
|
31518
31580
|
typeToIndex.clear();
|
|
31519
31581
|
};
|
|
31520
31582
|
|
|
31583
|
+
var __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
|
|
31584
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
31585
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
31586
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
31587
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
31588
|
+
};
|
|
31589
|
+
var DiagramFileService_1;
|
|
31590
|
+
/**
|
|
31591
|
+
* Service for downloading and uploading the diagram as a file. The file content is the same
|
|
31592
|
+
* {@link SerializedDiagram} that is persisted to the local store.
|
|
31593
|
+
*/
|
|
31594
|
+
let DiagramFileService = DiagramFileService_1 = class DiagramFileService {
|
|
31595
|
+
/**
|
|
31596
|
+
* Downloads the given diagram serialization as a file with the given name.
|
|
31597
|
+
*/
|
|
31598
|
+
download(diagram, fileName) {
|
|
31599
|
+
const window = service(WindowService).getWindow();
|
|
31600
|
+
const blob = new Blob([JSON.stringify(diagram)], { type: DiagramFileService_1.MIME_TYPE });
|
|
31601
|
+
const url = window.URL.createObjectURL(blob);
|
|
31602
|
+
const link = window.document.createElement('a');
|
|
31603
|
+
link.href = url;
|
|
31604
|
+
link.download = fileName;
|
|
31605
|
+
link.click();
|
|
31606
|
+
window.URL.revokeObjectURL(url);
|
|
31607
|
+
}
|
|
31608
|
+
/**
|
|
31609
|
+
* Reads a diagram serialization from the given file.
|
|
31610
|
+
*
|
|
31611
|
+
* @throws Error when the file is not valid JSON or is not a serialized diagram.
|
|
31612
|
+
*/
|
|
31613
|
+
async read(file) {
|
|
31614
|
+
let diagram;
|
|
31615
|
+
try {
|
|
31616
|
+
diagram = JSON.parse(await file.text());
|
|
31617
|
+
}
|
|
31618
|
+
catch (error) {
|
|
31619
|
+
throw new Error(`File "${file.name}" is not valid JSON: ${error.message}`);
|
|
31620
|
+
}
|
|
31621
|
+
if (!this.isSerializedDiagram(diagram)) {
|
|
31622
|
+
throw new Error(`File "${file.name}" is not a serialized diagram`);
|
|
31623
|
+
}
|
|
31624
|
+
return diagram;
|
|
31625
|
+
}
|
|
31626
|
+
/**
|
|
31627
|
+
* Checks if the provided value is a serialized diagram
|
|
31628
|
+
*/
|
|
31629
|
+
isSerializedDiagram(value) {
|
|
31630
|
+
var _a, _b;
|
|
31631
|
+
const diagram = value;
|
|
31632
|
+
return (diagram === null || diagram === void 0 ? void 0 : diagram['@type']) === 'Diagram'
|
|
31633
|
+
&& Array.isArray((_a = diagram.layoutData) === null || _a === void 0 ? void 0 : _a.elements)
|
|
31634
|
+
&& Array.isArray((_b = diagram.layoutData) === null || _b === void 0 ? void 0 : _b.links);
|
|
31635
|
+
}
|
|
31636
|
+
};
|
|
31637
|
+
DiagramFileService.ID = 'DiagramFileService';
|
|
31638
|
+
DiagramFileService.FILE_EXTENSION = '.json';
|
|
31639
|
+
DiagramFileService.MIME_TYPE = 'application/json';
|
|
31640
|
+
DiagramFileService = DiagramFileService_1 = __decorate([
|
|
31641
|
+
Service
|
|
31642
|
+
], DiagramFileService);
|
|
31643
|
+
|
|
31644
|
+
/**
|
|
31645
|
+
* The workspace main menu: Reactodia's default actions, followed by the diagram download and upload.
|
|
31646
|
+
*
|
|
31647
|
+
* Passing a `menu` to the `DefaultWorkspace` replaces its default actions, so they are listed here again.
|
|
31648
|
+
* Rendered inside the workspace, so the actions can use the workspace hooks.
|
|
31649
|
+
*/
|
|
31650
|
+
function GraphwiseMenu() {
|
|
31651
|
+
const { model } = useWorkspace();
|
|
31652
|
+
const t = useTranslation();
|
|
31653
|
+
const diagramFileService = service(DiagramFileService);
|
|
31654
|
+
const diagramService = service(DiagramService);
|
|
31655
|
+
const downloadDiagram = () => {
|
|
31656
|
+
const timestamp = new Date().toISOString().replace(/[-:]|\.\d+Z$/g, '');
|
|
31657
|
+
diagramFileService.download(model.exportLayout(), `diagram-${timestamp}${DiagramFileService.FILE_EXTENSION}`);
|
|
31658
|
+
};
|
|
31659
|
+
const uploadDiagram = async (file) => {
|
|
31660
|
+
try {
|
|
31661
|
+
const diagram = await diagramFileService.read(file);
|
|
31662
|
+
await diagramService.importDiagram(model, model.dataProvider, diagram);
|
|
31663
|
+
}
|
|
31664
|
+
catch (error) {
|
|
31665
|
+
console.error('Failed to upload the diagram', error);
|
|
31666
|
+
}
|
|
31667
|
+
};
|
|
31668
|
+
return reactExports.createElement(reactExports.Fragment, null, reactExports.createElement(ToolbarActionClearAll, {}), reactExports.createElement(ToolbarActionExport, { kind: 'exportRaster' }), reactExports.createElement(ToolbarActionExport, { kind: 'exportSvg' }), reactExports.createElement(ToolbarActionExport, { kind: 'print' }), reactExports.createElement(ToolbarAction,
|
|
31669
|
+
// The same icon as ToolbarActionSave. We dont use that action, since it disables saving on refresh
|
|
31670
|
+
{ className: 'reactodia-toolbar-action__save', title: t.text('graphwise_toolbar_action.download_diagram.title'), onSelect: downloadDiagram }, t.text('graphwise_toolbar_action.download_diagram.label')), reactExports.createElement(ToolbarActionOpen, {
|
|
31671
|
+
title: t.text('graphwise_toolbar_action.upload_diagram.title'),
|
|
31672
|
+
fileAccept: DiagramFileService.FILE_EXTENSION,
|
|
31673
|
+
onSelect: (file) => void uploadDiagram(file)
|
|
31674
|
+
}, t.text('graphwise_toolbar_action.upload_diagram.label')));
|
|
31675
|
+
}
|
|
31676
|
+
|
|
31521
31677
|
/**
|
|
31522
|
-
* Reactodia ships English as its built-in default bundle, so English
|
|
31678
|
+
* Reactodia ships English as its built-in default bundle, so the English bundle only adds our own keys.
|
|
31523
31679
|
* Other languages are layered on top as partial bundles; unknown codes fall back to English.
|
|
31524
31680
|
*
|
|
31525
31681
|
* Reactodia never re-reads the translations, so the component must be remounted
|
|
@@ -31543,8 +31699,7 @@ let workspaceContext = null;
|
|
|
31543
31699
|
const subscriptions = new SubscriptionList();
|
|
31544
31700
|
/**
|
|
31545
31701
|
* Builds a Reactodia {@link SparqlDataProvider} for the given endpoint using the supplied
|
|
31546
|
-
* query preset. The host owns the query configuration and passes it in via props
|
|
31547
|
-
* is provided we fall back to Reactodia's generic {@link OwlRdfsSettings} OWL/RDFS preset.
|
|
31702
|
+
* query preset. The host owns the query configuration and always passes it in via props.
|
|
31548
31703
|
*/
|
|
31549
31704
|
function createDataProvider(props) {
|
|
31550
31705
|
const { currentRepository, config, providerSettings } = props;
|
|
@@ -31637,10 +31792,12 @@ function ReactodiaApp(props) {
|
|
|
31637
31792
|
const dataProvider = createDataProvider(props);
|
|
31638
31793
|
const isReload = props.isReload;
|
|
31639
31794
|
const savedDiagram = service(DiagramStorageService).load();
|
|
31795
|
+
const diagramService = service(DiagramService);
|
|
31640
31796
|
if (isReload) {
|
|
31641
|
-
//
|
|
31642
|
-
//
|
|
31643
|
-
|
|
31797
|
+
// Reload the diagram that is currently on the canvas. This may happen when the host changes the provider
|
|
31798
|
+
// settings, or when the user switches the language at runtime, since there is no existing mechanism to
|
|
31799
|
+
// re-translate the UI at runtime (not for the UI labels at least)
|
|
31800
|
+
await diagramService.importDiagram(model, dataProvider, currentDiagram, signal);
|
|
31644
31801
|
}
|
|
31645
31802
|
else if ((_a = config.seedIris) === null || _a === void 0 ? void 0 : _a.length) {
|
|
31646
31803
|
await seedIrisToCanvas(context, dataProvider, config.seedIris, signal);
|
|
@@ -31651,7 +31808,7 @@ function ReactodiaApp(props) {
|
|
|
31651
31808
|
else {
|
|
31652
31809
|
// Restore the previously saved layout when present, otherwise start empty. Either way this binds the
|
|
31653
31810
|
// data provider (savedDiagram is undefined -> empty diagram), so the unified search/lookup works.
|
|
31654
|
-
await
|
|
31811
|
+
await diagramService.importDiagram(model, dataProvider, savedDiagram, signal);
|
|
31655
31812
|
}
|
|
31656
31813
|
}, [language]);
|
|
31657
31814
|
/**
|
|
@@ -31670,7 +31827,11 @@ function ReactodiaApp(props) {
|
|
|
31670
31827
|
defaultLanguage: language,
|
|
31671
31828
|
translations: translationsForLanguage(language),
|
|
31672
31829
|
typeStyleResolver: resolveTypeStyle
|
|
31673
|
-
}, reactExports.createElement(DefaultWorkspace, {
|
|
31830
|
+
}, reactExports.createElement(DefaultWorkspace, {
|
|
31831
|
+
menu: reactExports.createElement(GraphwiseMenu),
|
|
31832
|
+
// place Undo/redo/layout actions in top right corner.
|
|
31833
|
+
actionsToolbar: { dock: 'ne' }
|
|
31834
|
+
}));
|
|
31674
31835
|
}
|
|
31675
31836
|
/**
|
|
31676
31837
|
* Mounts the Reactodia application into the given container and returns the React root.
|
|
@@ -31681,8 +31842,9 @@ function mountReactodia(container, props) {
|
|
|
31681
31842
|
return root;
|
|
31682
31843
|
}
|
|
31683
31844
|
/**
|
|
31684
|
-
* Re-points the diagram at a new SPARQL endpoint
|
|
31685
|
-
*
|
|
31845
|
+
* Re-points the diagram at a new SPARQL endpoint by recreating it with a fresh data provider.
|
|
31846
|
+
* The canvas is reset to empty, matching the initial mount, since the data of another repository
|
|
31847
|
+
* has nothing to do with the current graph.
|
|
31686
31848
|
*/
|
|
31687
31849
|
async function updateReactodia(props) {
|
|
31688
31850
|
if (!workspaceContext) {
|
|
@@ -31707,7 +31869,7 @@ function unmountReactodia(root) {
|
|
|
31707
31869
|
root.unmount();
|
|
31708
31870
|
}
|
|
31709
31871
|
|
|
31710
|
-
const graphwiseReactodiaCss = "graphwise-reactodia{display:block;width:100%;height:75vh}graphwise-reactodia .reactodia-container{position:relative;width:100%;height:100%}";
|
|
31872
|
+
const graphwiseReactodiaCss = "graphwise-reactodia{display:block;width:100%;height:75vh}graphwise-reactodia .reactodia-container{position:relative;width:100%;height:100%}graphwise-reactodia .reactodia-selection-action__link{display:none}";
|
|
31711
31873
|
|
|
31712
31874
|
const GraphwiseReactodia = class {
|
|
31713
31875
|
constructor(hostRef) {
|
|
@@ -31717,12 +31879,13 @@ const GraphwiseReactodia = class {
|
|
|
31717
31879
|
*/
|
|
31718
31880
|
this.language = LanguageKey.EN;
|
|
31719
31881
|
}
|
|
31720
|
-
|
|
31882
|
+
onCurrentRepositoryChange() {
|
|
31721
31883
|
this.renderGraph();
|
|
31722
31884
|
}
|
|
31723
|
-
|
|
31885
|
+
onLanguageOrSettingsChange() {
|
|
31724
31886
|
// The translations are evaluated by the workspace at construction, so the only way
|
|
31725
31887
|
// to re-translate the UI is to re-create the graph.
|
|
31888
|
+
// Setting changes should keep the current diagram despite possible
|
|
31726
31889
|
this.renderGraph(true);
|
|
31727
31890
|
}
|
|
31728
31891
|
onThemeChange() {
|
|
@@ -31741,7 +31904,7 @@ const GraphwiseReactodia = class {
|
|
|
31741
31904
|
}
|
|
31742
31905
|
}
|
|
31743
31906
|
render() {
|
|
31744
|
-
return (index$1.h(index$1.Host, { key: '
|
|
31907
|
+
return (index$1.h(index$1.Host, { key: '6f1115b91eac308ef155978dfe1482f152c38b1b' }));
|
|
31745
31908
|
}
|
|
31746
31909
|
renderGraph(isReloading) {
|
|
31747
31910
|
var _a;
|
|
@@ -31751,6 +31914,9 @@ const GraphwiseReactodia = class {
|
|
|
31751
31914
|
if (!((_a = this.config) === null || _a === void 0 ? void 0 : _a.queryFunction)) {
|
|
31752
31915
|
throw new Error('config.queryFunction is required');
|
|
31753
31916
|
}
|
|
31917
|
+
if (!this.providerSettings) {
|
|
31918
|
+
throw new Error('providerSettings is required');
|
|
31919
|
+
}
|
|
31754
31920
|
if (!this.hostElement) {
|
|
31755
31921
|
return;
|
|
31756
31922
|
}
|
|
@@ -31770,9 +31936,9 @@ const GraphwiseReactodia = class {
|
|
|
31770
31936
|
}
|
|
31771
31937
|
get hostElement() { return index$1.getElement(this); }
|
|
31772
31938
|
static get watchers() { return {
|
|
31773
|
-
"currentRepository": ["
|
|
31774
|
-
"
|
|
31775
|
-
"
|
|
31939
|
+
"currentRepository": ["onCurrentRepositoryChange"],
|
|
31940
|
+
"language": ["onLanguageOrSettingsChange"],
|
|
31941
|
+
"providerSettings": ["onLanguageOrSettingsChange"],
|
|
31776
31942
|
"theme": ["onThemeChange"]
|
|
31777
31943
|
}; }
|
|
31778
31944
|
};
|
|
@@ -19,7 +19,7 @@ var patchBrowser = () => {
|
|
|
19
19
|
|
|
20
20
|
patchBrowser().then(async (options) => {
|
|
21
21
|
await appGlobals.globalScripts();
|
|
22
|
-
return index.bootstrapLazy([["graphwise-reactodia.cjs",[[0,"graphwise-reactodia",{"currentRepository":[1,"current-repository"],"config":[16],"language":[1],"providerSettings":[16,"provider-settings"],"theme":[1]},null,{"currentRepository":["
|
|
22
|
+
return index.bootstrapLazy([["graphwise-reactodia.cjs",[[0,"graphwise-reactodia",{"currentRepository":[1,"current-repository"],"config":[16],"language":[1],"providerSettings":[16,"provider-settings"],"theme":[1]},null,{"currentRepository":["onCurrentRepositoryChange"],"language":["onLanguageOrSettingsChange"],"providerSettings":["onLanguageOrSettingsChange"],"theme":["onThemeChange"]}]]]], options);
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
exports.setNonce = index.setNonce;
|
package/dist/cjs/loader.cjs.js
CHANGED
|
@@ -6,7 +6,7 @@ var appGlobals = require('./app-globals-CcJr5lkF.js');
|
|
|
6
6
|
const defineCustomElements = async (win, options) => {
|
|
7
7
|
if (typeof window === 'undefined') return undefined;
|
|
8
8
|
await appGlobals.globalScripts();
|
|
9
|
-
return index.bootstrapLazy([["graphwise-reactodia.cjs",[[0,"graphwise-reactodia",{"currentRepository":[1,"current-repository"],"config":[16],"language":[1],"providerSettings":[16,"provider-settings"],"theme":[1]},null,{"currentRepository":["
|
|
9
|
+
return index.bootstrapLazy([["graphwise-reactodia.cjs",[[0,"graphwise-reactodia",{"currentRepository":[1,"current-repository"],"config":[16],"language":[1],"providerSettings":[16,"provider-settings"],"theme":[1]},null,{"currentRepository":["onCurrentRepositoryChange"],"language":["onLanguageOrSettingsChange"],"providerSettings":["onLanguageOrSettingsChange"],"theme":["onThemeChange"]}]]]], options);
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
exports.setNonce = index.setNonce;
|
|
@@ -20,12 +20,13 @@ export class GraphwiseReactodia {
|
|
|
20
20
|
*/
|
|
21
21
|
this.language = LanguageKey.EN;
|
|
22
22
|
}
|
|
23
|
-
|
|
23
|
+
onCurrentRepositoryChange() {
|
|
24
24
|
this.renderGraph();
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
onLanguageOrSettingsChange() {
|
|
27
27
|
// The translations are evaluated by the workspace at construction, so the only way
|
|
28
28
|
// to re-translate the UI is to re-create the graph.
|
|
29
|
+
// Setting changes should keep the current diagram despite possible
|
|
29
30
|
this.renderGraph(true);
|
|
30
31
|
}
|
|
31
32
|
onThemeChange() {
|
|
@@ -44,7 +45,7 @@ export class GraphwiseReactodia {
|
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
render() {
|
|
47
|
-
return (h(Host, { key: '
|
|
48
|
+
return (h(Host, { key: '6f1115b91eac308ef155978dfe1482f152c38b1b' }));
|
|
48
49
|
}
|
|
49
50
|
renderGraph(isReloading) {
|
|
50
51
|
var _a;
|
|
@@ -54,6 +55,9 @@ export class GraphwiseReactodia {
|
|
|
54
55
|
if (!((_a = this.config) === null || _a === void 0 ? void 0 : _a.queryFunction)) {
|
|
55
56
|
throw new Error('config.queryFunction is required');
|
|
56
57
|
}
|
|
58
|
+
if (!this.providerSettings) {
|
|
59
|
+
throw new Error('providerSettings is required');
|
|
60
|
+
}
|
|
57
61
|
if (!this.hostElement) {
|
|
58
62
|
return;
|
|
59
63
|
}
|
|
@@ -172,7 +176,7 @@ export class GraphwiseReactodia {
|
|
|
172
176
|
"optional": true,
|
|
173
177
|
"docs": {
|
|
174
178
|
"tags": [],
|
|
175
|
-
"text": "Query preset for the SPARQL data provider, owned and configured by the host. A DOM\nproperty (an object, not an attribute) passed in from outside the wrapper.
|
|
179
|
+
"text": "Query preset for the SPARQL data provider, owned and configured by the host. A DOM\nproperty (an object, not an attribute) passed in from outside the wrapper. Required: the\nwrapper has no default preset and throws when it is missing. Changing it rebuilds the data\nprovider and reloads the graph with it, keeping the current diagram."
|
|
176
180
|
},
|
|
177
181
|
"getter": false,
|
|
178
182
|
"setter": false
|
|
@@ -202,13 +206,13 @@ export class GraphwiseReactodia {
|
|
|
202
206
|
static get watchers() {
|
|
203
207
|
return [{
|
|
204
208
|
"propName": "currentRepository",
|
|
205
|
-
"methodName": "
|
|
206
|
-
}, {
|
|
207
|
-
"propName": "providerSettings",
|
|
208
|
-
"methodName": "onProviderSettingsChange"
|
|
209
|
+
"methodName": "onCurrentRepositoryChange"
|
|
209
210
|
}, {
|
|
210
211
|
"propName": "language",
|
|
211
|
-
"methodName": "
|
|
212
|
+
"methodName": "onLanguageOrSettingsChange"
|
|
213
|
+
}, {
|
|
214
|
+
"propName": "providerSettings",
|
|
215
|
+
"methodName": "onLanguageOrSettingsChange"
|
|
212
216
|
}, {
|
|
213
217
|
"propName": "theme",
|
|
214
218
|
"methodName": "onThemeChange"
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import enTranslation from "./en.reactodia.translation.json";
|
|
1
2
|
import frTranslation from "./fr.reactodia.translation.json";
|
|
2
3
|
import { LanguageKey } from "./language-key";
|
|
3
|
-
// English is provided by default from reactodia so
|
|
4
|
+
// English is provided by default from reactodia, so the English bundle holds only our own keys and overrides. If
|
|
5
|
+
// A key is missing, reactodia defaults to its own translation.
|
|
4
6
|
export const TRANSLATIONS = {
|
|
7
|
+
[LanguageKey.EN]: enTranslation,
|
|
5
8
|
[LanguageKey.FR]: frTranslation
|
|
6
9
|
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createElement, Fragment } from "react";
|
|
2
|
+
import { ToolbarAction, ToolbarActionClearAll, ToolbarActionExport, ToolbarActionOpen, useTranslation, useWorkspace } from "@reactodia/workspace";
|
|
3
|
+
import { service } from "../providers/service/service-inject";
|
|
4
|
+
import { DiagramService } from "../services/diagram/diagram.service";
|
|
5
|
+
import { DiagramFileService } from "../services/diagram-file/diagram-file.service";
|
|
6
|
+
/**
|
|
7
|
+
* The workspace main menu: Reactodia's default actions, followed by the diagram download and upload.
|
|
8
|
+
*
|
|
9
|
+
* Passing a `menu` to the `DefaultWorkspace` replaces its default actions, so they are listed here again.
|
|
10
|
+
* Rendered inside the workspace, so the actions can use the workspace hooks.
|
|
11
|
+
*/
|
|
12
|
+
export function GraphwiseMenu() {
|
|
13
|
+
const { model } = useWorkspace();
|
|
14
|
+
const t = useTranslation();
|
|
15
|
+
const diagramFileService = service(DiagramFileService);
|
|
16
|
+
const diagramService = service(DiagramService);
|
|
17
|
+
const downloadDiagram = () => {
|
|
18
|
+
const timestamp = new Date().toISOString().replace(/[-:]|\.\d+Z$/g, '');
|
|
19
|
+
diagramFileService.download(model.exportLayout(), `diagram-${timestamp}${DiagramFileService.FILE_EXTENSION}`);
|
|
20
|
+
};
|
|
21
|
+
const uploadDiagram = async (file) => {
|
|
22
|
+
try {
|
|
23
|
+
const diagram = await diagramFileService.read(file);
|
|
24
|
+
await diagramService.importDiagram(model, model.dataProvider, diagram);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
console.error('Failed to upload the diagram', error);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
return createElement(Fragment, null, createElement(ToolbarActionClearAll, {}), createElement(ToolbarActionExport, { kind: 'exportRaster' }), createElement(ToolbarActionExport, { kind: 'exportSvg' }), createElement(ToolbarActionExport, { kind: 'print' }), createElement(ToolbarAction,
|
|
31
|
+
// The same icon as ToolbarActionSave. We dont use that action, since it disables saving on refresh
|
|
32
|
+
{ className: 'reactodia-toolbar-action__save', title: t.text('graphwise_toolbar_action.download_diagram.title'), onSelect: downloadDiagram }, t.text('graphwise_toolbar_action.download_diagram.label')), createElement(ToolbarActionOpen, {
|
|
33
|
+
title: t.text('graphwise_toolbar_action.upload_diagram.title'),
|
|
34
|
+
fileAccept: DiagramFileService.FILE_EXTENSION,
|
|
35
|
+
onSelect: (file) => void uploadDiagram(file)
|
|
36
|
+
}, t.text('graphwise_toolbar_action.upload_diagram.label')));
|
|
37
|
+
}
|
|
@@ -9,8 +9,9 @@ import { DiagramStorageService } from "./services/diagram-storage/diagram-storag
|
|
|
9
9
|
import { EventService } from "./services/event/event.service";
|
|
10
10
|
import { SubscriptionList } from "./models/subscription-list";
|
|
11
11
|
import { resolveTypeStyle } from "./styles/type-style.resolver";
|
|
12
|
+
import { GraphwiseMenu } from "./menu/graphwise-menu";
|
|
12
13
|
/**
|
|
13
|
-
* Reactodia ships English as its built-in default bundle, so English
|
|
14
|
+
* Reactodia ships English as its built-in default bundle, so the English bundle only adds our own keys.
|
|
14
15
|
* Other languages are layered on top as partial bundles; unknown codes fall back to English.
|
|
15
16
|
*
|
|
16
17
|
* Reactodia never re-reads the translations, so the component must be remounted
|
|
@@ -34,8 +35,7 @@ let workspaceContext = null;
|
|
|
34
35
|
const subscriptions = new SubscriptionList();
|
|
35
36
|
/**
|
|
36
37
|
* Builds a Reactodia {@link SparqlDataProvider} for the given endpoint using the supplied
|
|
37
|
-
* query preset. The host owns the query configuration and passes it in via props
|
|
38
|
-
* is provided we fall back to Reactodia's generic {@link OwlRdfsSettings} OWL/RDFS preset.
|
|
38
|
+
* query preset. The host owns the query configuration and always passes it in via props.
|
|
39
39
|
*/
|
|
40
40
|
function createDataProvider(props) {
|
|
41
41
|
const { currentRepository, config, providerSettings } = props;
|
|
@@ -128,10 +128,12 @@ function ReactodiaApp(props) {
|
|
|
128
128
|
const dataProvider = createDataProvider(props);
|
|
129
129
|
const isReload = props.isReload;
|
|
130
130
|
const savedDiagram = service(DiagramStorageService).load();
|
|
131
|
+
const diagramService = service(DiagramService);
|
|
131
132
|
if (isReload) {
|
|
132
|
-
//
|
|
133
|
-
//
|
|
134
|
-
|
|
133
|
+
// Reload the diagram that is currently on the canvas. This may happen when the host changes the provider
|
|
134
|
+
// settings, or when the user switches the language at runtime, since there is no existing mechanism to
|
|
135
|
+
// re-translate the UI at runtime (not for the UI labels at least)
|
|
136
|
+
await diagramService.importDiagram(model, dataProvider, currentDiagram, signal);
|
|
135
137
|
}
|
|
136
138
|
else if ((_a = config.seedIris) === null || _a === void 0 ? void 0 : _a.length) {
|
|
137
139
|
await seedIrisToCanvas(context, dataProvider, config.seedIris, signal);
|
|
@@ -142,7 +144,7 @@ function ReactodiaApp(props) {
|
|
|
142
144
|
else {
|
|
143
145
|
// Restore the previously saved layout when present, otherwise start empty. Either way this binds the
|
|
144
146
|
// data provider (savedDiagram is undefined -> empty diagram), so the unified search/lookup works.
|
|
145
|
-
await
|
|
147
|
+
await diagramService.importDiagram(model, dataProvider, savedDiagram, signal);
|
|
146
148
|
}
|
|
147
149
|
}, [language]);
|
|
148
150
|
/**
|
|
@@ -161,7 +163,11 @@ function ReactodiaApp(props) {
|
|
|
161
163
|
defaultLanguage: language,
|
|
162
164
|
translations: translationsForLanguage(language),
|
|
163
165
|
typeStyleResolver: resolveTypeStyle
|
|
164
|
-
}, createElement(DefaultWorkspace, {
|
|
166
|
+
}, createElement(DefaultWorkspace, {
|
|
167
|
+
menu: createElement(GraphwiseMenu),
|
|
168
|
+
// place Undo/redo/layout actions in top right corner.
|
|
169
|
+
actionsToolbar: { dock: 'ne' }
|
|
170
|
+
}));
|
|
165
171
|
}
|
|
166
172
|
/**
|
|
167
173
|
* Mounts the Reactodia application into the given container and returns the React root.
|
|
@@ -172,8 +178,9 @@ export function mountReactodia(container, props) {
|
|
|
172
178
|
return root;
|
|
173
179
|
}
|
|
174
180
|
/**
|
|
175
|
-
* Re-points the diagram at a new SPARQL endpoint
|
|
176
|
-
*
|
|
181
|
+
* Re-points the diagram at a new SPARQL endpoint by recreating it with a fresh data provider.
|
|
182
|
+
* The canvas is reset to empty, matching the initial mount, since the data of another repository
|
|
183
|
+
* has nothing to do with the current graph.
|
|
177
184
|
*/
|
|
178
185
|
export async function updateReactodia(props) {
|
|
179
186
|
if (!workspaceContext) {
|
|
@@ -14,6 +14,20 @@ import { Service } from "../../providers/service/service";
|
|
|
14
14
|
* Service for diagram related operations and subscriptions
|
|
15
15
|
*/
|
|
16
16
|
let DiagramService = DiagramService_1 = class DiagramService {
|
|
17
|
+
/**
|
|
18
|
+
* Replaces the diagram content with the given serialization. Element data is requested from the data provider and
|
|
19
|
+
* the links between the imported elements are validated against it.
|
|
20
|
+
*
|
|
21
|
+
* @param model The diagram model to import into.
|
|
22
|
+
* @param dataProvider The data provider to bind to the diagram.
|
|
23
|
+
* @param diagram The serialization to import. When `undefined`, the diagram is cleared.
|
|
24
|
+
* @param signal Optional signal to abort the import.
|
|
25
|
+
*/
|
|
26
|
+
importDiagram(model, dataProvider, diagram, signal) {
|
|
27
|
+
// selection is not cleared on import, so we clear it manually to avoid painting the previous selection
|
|
28
|
+
model.setSelection([]);
|
|
29
|
+
return model.importLayout({ dataProvider, diagram, signal, validateLinks: true });
|
|
30
|
+
}
|
|
17
31
|
/**
|
|
18
32
|
* Subscribes to diagram changes. On every debounced change the current layout is
|
|
19
33
|
* exported and passed to the callback.
|