graphwise-reactodia 0.0.1-TR16 → 0.0.1-TR18
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/README.md +57 -0
- package/dist/cjs/error-code-BdRU0RQ9.js +36 -0
- package/dist/cjs/graphwise-reactodia.cjs.entry.js +270 -65
- package/dist/cjs/graphwise-reactodia.cjs.js +1 -1
- package/dist/cjs/{index-CII9aUQC.js → index-DtzCybH4.js} +16 -0
- package/dist/cjs/index.cjs.js +14 -4
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/collection/components/graphwise-reactodia/graphwise-reactodia.js +46 -4
- package/dist/collection/components/graphwise-reactodia/menu/graphwise-menu.js +4 -1
- package/dist/collection/components/graphwise-reactodia/models/error/error-cause.js +1 -0
- package/dist/collection/components/graphwise-reactodia/models/error/error-code.js +18 -0
- package/dist/collection/components/graphwise-reactodia/models/error/error-report.js +1 -0
- package/dist/collection/components/graphwise-reactodia/models/event/event-callback.js +1 -0
- package/dist/collection/components/graphwise-reactodia/models/event/event-detail.js +4 -0
- package/dist/collection/components/graphwise-reactodia/models/event/event-type.js +7 -0
- package/dist/collection/components/graphwise-reactodia/reactodia-app.js +53 -19
- package/dist/collection/components/graphwise-reactodia/services/diagram-storage/diagram-storage.service.js +20 -4
- package/dist/collection/components/graphwise-reactodia/services/error/error.service.js +78 -0
- package/dist/collection/components/graphwise-reactodia/services/event/event.service.js +23 -0
- package/dist/collection/index.js +3 -0
- package/dist/collection/pages/graphwise-reactodia/main.js +41 -0
- package/dist/esm/error-code-DHI2bePh.js +34 -0
- package/dist/esm/graphwise-reactodia.entry.js +268 -63
- package/dist/esm/graphwise-reactodia.js +2 -2
- package/dist/esm/{index-Cypw7ydc.js → index-DpCR6zMg.js} +16 -1
- package/dist/esm/index.js +5 -4
- package/dist/esm/loader.js +2 -2
- package/dist/graphwise-reactodia/graphwise-reactodia.esm.js +1 -1
- package/dist/graphwise-reactodia/index.esm.js +1 -1
- package/dist/graphwise-reactodia/p-DHI2bePh.js +1 -0
- package/dist/graphwise-reactodia/p-DpCR6zMg.js +2 -0
- package/dist/graphwise-reactodia/p-abfb5091.entry.js +1 -0
- package/dist/types/components/graphwise-reactodia/graphwise-reactodia.d.ts +9 -0
- package/dist/types/components/graphwise-reactodia/models/error/error-cause.d.ts +10 -0
- package/dist/types/components/graphwise-reactodia/models/error/error-code.d.ts +17 -0
- package/dist/types/components/graphwise-reactodia/models/error/error-report.d.ts +13 -0
- package/dist/types/components/graphwise-reactodia/models/event/event-callback.d.ts +5 -0
- package/dist/types/components/graphwise-reactodia/models/event/event-detail.d.ts +48 -0
- package/dist/types/components/graphwise-reactodia/models/event/event-type.d.ts +6 -0
- package/dist/types/components/graphwise-reactodia/reactodia-app.d.ts +1 -1
- package/dist/types/components/graphwise-reactodia/services/diagram-storage/diagram-storage.service.d.ts +1 -0
- package/dist/types/components/graphwise-reactodia/services/error/error.service.d.ts +41 -0
- package/dist/types/components/graphwise-reactodia/services/event/event.service.d.ts +16 -0
- package/dist/types/components.d.ts +21 -0
- package/dist/types/index.d.ts +5 -0
- package/package.json +1 -1
- package/dist/graphwise-reactodia/p-20637a6f.entry.js +0 -1
- package/dist/graphwise-reactodia/p-Cypw7ydc.js +0 -2
package/dist/cjs/index.cjs.js
CHANGED
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var errorCode = require('./error-code-BdRU0RQ9.js');
|
|
4
|
+
|
|
3
5
|
/**
|
|
4
|
-
*
|
|
5
|
-
* will clear the local store state, whenever this event is fired.
|
|
6
|
+
* Name of the DOM event the `graphwise-reactodia` element dispatches for every event.
|
|
6
7
|
*/
|
|
7
|
-
const
|
|
8
|
+
const GRAPHWISE_REACTODIA_EVENT = 'graphwiseReactodiaEvent';
|
|
8
9
|
|
|
9
|
-
exports.CLEAR_DIAGRAM_STORAGE_EVENT = CLEAR_DIAGRAM_STORAGE_EVENT;
|
|
10
|
+
exports.CLEAR_DIAGRAM_STORAGE_EVENT = errorCode.CLEAR_DIAGRAM_STORAGE_EVENT;
|
|
11
|
+
Object.defineProperty(exports, "ErrorCode", {
|
|
12
|
+
enumerable: true,
|
|
13
|
+
get: function () { return errorCode.ErrorCode; }
|
|
14
|
+
});
|
|
15
|
+
Object.defineProperty(exports, "EventType", {
|
|
16
|
+
enumerable: true,
|
|
17
|
+
get: function () { return errorCode.EventType; }
|
|
18
|
+
});
|
|
19
|
+
exports.GRAPHWISE_REACTODIA_EVENT = GRAPHWISE_REACTODIA_EVENT;
|
package/dist/cjs/loader.cjs.js
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { h, Host } from "@stencil/core";
|
|
2
2
|
import { mountReactodia, unmountReactodia, updateReactodia } from "./reactodia-app";
|
|
3
3
|
import { LanguageKey } from "./i18n/language-key";
|
|
4
|
+
import { ErrorCode } from "./models/error/error-code";
|
|
5
|
+
import { SubscriptionList } from "./models/subscription-list";
|
|
6
|
+
import { service } from "./providers/service/service-inject";
|
|
7
|
+
import { ErrorService } from "./services/error/error.service";
|
|
8
|
+
import { EventService } from "./services/event/event.service";
|
|
4
9
|
import { resetColors } from "./styles/type-style.resolver";
|
|
10
|
+
const errorService = service(ErrorService);
|
|
11
|
+
const eventService = service(EventService);
|
|
5
12
|
/**
|
|
6
13
|
* A web component that renders a graph with the Reactodia workspace.
|
|
7
14
|
*
|
|
@@ -15,6 +22,7 @@ import { resetColors } from "./styles/type-style.resolver";
|
|
|
15
22
|
*/
|
|
16
23
|
export class GraphwiseReactodia {
|
|
17
24
|
constructor() {
|
|
25
|
+
this.subscriptions = new SubscriptionList();
|
|
18
26
|
/**
|
|
19
27
|
* UI language code (e.g. `en`, `fr`) for the Reactodia interface. Defaults to English.
|
|
20
28
|
*/
|
|
@@ -42,6 +50,7 @@ export class GraphwiseReactodia {
|
|
|
42
50
|
this.renderGraph(true);
|
|
43
51
|
}
|
|
44
52
|
connectedCallback() {
|
|
53
|
+
this.subscribeToEvents();
|
|
45
54
|
this.renderGraph();
|
|
46
55
|
}
|
|
47
56
|
componentDidLoad() {
|
|
@@ -49,13 +58,17 @@ export class GraphwiseReactodia {
|
|
|
49
58
|
this.renderGraph();
|
|
50
59
|
}
|
|
51
60
|
disconnectedCallback() {
|
|
61
|
+
this.subscriptions.unsubscribeAll();
|
|
52
62
|
if (this.reactRoot) {
|
|
53
63
|
unmountReactodia(this.reactRoot);
|
|
54
64
|
this.reactRoot = undefined;
|
|
55
65
|
}
|
|
56
66
|
}
|
|
57
67
|
render() {
|
|
58
|
-
return (h(Host, { key: '
|
|
68
|
+
return (h(Host, { key: '2e8541c791f478484c4bad64ad758df99aba2059' }));
|
|
69
|
+
}
|
|
70
|
+
subscribeToEvents() {
|
|
71
|
+
this.subscriptions.add(eventService.subscribe((detail) => this.eventEmitter.emit(detail)));
|
|
59
72
|
}
|
|
60
73
|
renderGraph(isReloading) {
|
|
61
74
|
var _a;
|
|
@@ -63,13 +76,13 @@ export class GraphwiseReactodia {
|
|
|
63
76
|
return;
|
|
64
77
|
}
|
|
65
78
|
if (!this.currentRepository) {
|
|
66
|
-
throw
|
|
79
|
+
throw this.reportMissingPropError('currentRepository is required');
|
|
67
80
|
}
|
|
68
81
|
if (!((_a = this.config) === null || _a === void 0 ? void 0 : _a.queryFunction)) {
|
|
69
|
-
throw
|
|
82
|
+
throw this.reportMissingPropError('config.queryFunction is required');
|
|
70
83
|
}
|
|
71
84
|
if (!this.providerSettings) {
|
|
72
|
-
throw
|
|
85
|
+
throw this.reportMissingPropError('providerSettings is required');
|
|
73
86
|
}
|
|
74
87
|
if (!this.hostElement) {
|
|
75
88
|
return;
|
|
@@ -89,6 +102,11 @@ export class GraphwiseReactodia {
|
|
|
89
102
|
this.reactRoot = mountReactodia(this.hostElement, props);
|
|
90
103
|
}
|
|
91
104
|
}
|
|
105
|
+
reportMissingPropError(message) {
|
|
106
|
+
const error = new Error(message);
|
|
107
|
+
errorService.report(ErrorCode.MISSING_REQUIRED_PROP, error);
|
|
108
|
+
return error;
|
|
109
|
+
}
|
|
92
110
|
static get is() { return "graphwise-reactodia"; }
|
|
93
111
|
static get originalStyleUrls() {
|
|
94
112
|
return {
|
|
@@ -216,6 +234,30 @@ export class GraphwiseReactodia {
|
|
|
216
234
|
}
|
|
217
235
|
};
|
|
218
236
|
}
|
|
237
|
+
static get events() {
|
|
238
|
+
return [{
|
|
239
|
+
"method": "eventEmitter",
|
|
240
|
+
"name": "graphwiseReactodiaEvent",
|
|
241
|
+
"bubbles": true,
|
|
242
|
+
"cancelable": true,
|
|
243
|
+
"composed": true,
|
|
244
|
+
"docs": {
|
|
245
|
+
"tags": [],
|
|
246
|
+
"text": "Fires for every event to the host, differentiated by `detail.type`."
|
|
247
|
+
},
|
|
248
|
+
"complexType": {
|
|
249
|
+
"original": "EventDetail",
|
|
250
|
+
"resolved": "{ type: EventType; payload: ErrorReport; }",
|
|
251
|
+
"references": {
|
|
252
|
+
"EventDetail": {
|
|
253
|
+
"location": "import",
|
|
254
|
+
"path": "./models/event/event-detail",
|
|
255
|
+
"id": "src/components/graphwise-reactodia/models/event/event-detail.ts::EventDetail"
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}];
|
|
260
|
+
}
|
|
219
261
|
static get elementRef() { return "hostElement"; }
|
|
220
262
|
static get watchers() {
|
|
221
263
|
return [{
|
|
@@ -3,6 +3,8 @@ import { ToolbarAction, ToolbarActionClearAll, ToolbarActionExport, ToolbarActio
|
|
|
3
3
|
import { service } from "../providers/service/service-inject";
|
|
4
4
|
import { DiagramService } from "../services/diagram/diagram.service";
|
|
5
5
|
import { DiagramFileService } from "../services/diagram-file/diagram-file.service";
|
|
6
|
+
import { ErrorService } from "../services/error/error.service";
|
|
7
|
+
import { ErrorCode } from "../models/error/error-code";
|
|
6
8
|
/**
|
|
7
9
|
* The workspace main menu: Reactodia's default actions, followed by the diagram download and upload.
|
|
8
10
|
*
|
|
@@ -14,6 +16,7 @@ export function GraphwiseMenu() {
|
|
|
14
16
|
const t = useTranslation();
|
|
15
17
|
const diagramFileService = service(DiagramFileService);
|
|
16
18
|
const diagramService = service(DiagramService);
|
|
19
|
+
const errorService = service(ErrorService);
|
|
17
20
|
const downloadDiagram = () => {
|
|
18
21
|
const timestamp = new Date().toISOString().replace(/[-:]|\.\d+Z$/g, '');
|
|
19
22
|
diagramFileService.download(model.exportLayout(), `diagram-${timestamp}${DiagramFileService.FILE_EXTENSION}`);
|
|
@@ -24,7 +27,7 @@ export function GraphwiseMenu() {
|
|
|
24
27
|
await diagramService.importDiagram(model, model.dataProvider, diagram);
|
|
25
28
|
}
|
|
26
29
|
catch (error) {
|
|
27
|
-
|
|
30
|
+
errorService.report(ErrorCode.DIAGRAM_IMPORT, error);
|
|
28
31
|
}
|
|
29
32
|
};
|
|
30
33
|
return createElement(Fragment, null, createElement(ToolbarActionClearAll, {}), createElement(ToolbarActionExport, { kind: 'exportRaster' }), createElement(ToolbarActionExport, { kind: 'exportSvg' }), createElement(ToolbarActionExport, { kind: 'print' }), createElement(ToolbarAction,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The stable category of a reported error. The host uses it to choose its own message.
|
|
3
|
+
*/
|
|
4
|
+
export var ErrorCode;
|
|
5
|
+
(function (ErrorCode) {
|
|
6
|
+
/** A required prop is missing. */
|
|
7
|
+
ErrorCode["MISSING_REQUIRED_PROP"] = "missing-required-prop";
|
|
8
|
+
/** A SPARQL data provider call failed. */
|
|
9
|
+
ErrorCode["DATA_FETCH"] = "data-fetch";
|
|
10
|
+
/** The startup load, a reload or a repository switch failed. */
|
|
11
|
+
ErrorCode["DIAGRAM_LOAD"] = "diagram-load";
|
|
12
|
+
/** The uploaded file was rejected or its import failed. */
|
|
13
|
+
ErrorCode["DIAGRAM_IMPORT"] = "diagram-import";
|
|
14
|
+
/** Reading the diagram from local storage failed. */
|
|
15
|
+
ErrorCode["LOCAL_DIAGRAM_READ"] = "local-diagram-read";
|
|
16
|
+
/** Saving the diagram in local storage failed. */
|
|
17
|
+
ErrorCode["LOCAL_DIAGRAM_SAVE"] = "local-diagram-save";
|
|
18
|
+
})(ErrorCode || (ErrorCode = {}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { createElement } from "react";
|
|
2
2
|
import { createRoot } from "react-dom/client";
|
|
3
|
-
import { DefaultWorkspace, SparqlDataProvider, useLoadedWorkspace, Workspace } from "@reactodia/workspace";
|
|
3
|
+
import { DecoratedDataProvider, DefaultWorkspace, SparqlDataProvider, useLoadedWorkspace, Workspace } from "@reactodia/workspace";
|
|
4
4
|
import { blockingDefaultLayout } from "@reactodia/workspace/layout-sync";
|
|
5
5
|
import { TRANSLATIONS } from "./i18n/translations";
|
|
6
6
|
import { service } from "./providers/service/service-inject";
|
|
7
7
|
import { DiagramService } from "./services/diagram/diagram.service";
|
|
8
8
|
import { DiagramStorageService } from "./services/diagram-storage/diagram-storage.service";
|
|
9
9
|
import { EventService } from "./services/event/event.service";
|
|
10
|
+
import { ErrorService } from "./services/error/error.service";
|
|
11
|
+
import { ErrorCode } from "./models/error/error-code";
|
|
10
12
|
import { SubscriptionList } from "./models/subscription-list";
|
|
11
13
|
import { resolveTypeStyle } from "./styles/type-style.resolver";
|
|
12
14
|
import { GraphwiseMenu } from "./menu/graphwise-menu";
|
|
@@ -37,17 +39,35 @@ let diagramStorageSubscription;
|
|
|
37
39
|
const diagramService = service(DiagramService);
|
|
38
40
|
const diagramStorageService = service(DiagramStorageService);
|
|
39
41
|
const eventService = service(EventService);
|
|
42
|
+
const errorService = service(ErrorService);
|
|
43
|
+
/**
|
|
44
|
+
* Reports every failed data provider call, unless the call was aborted, and passes the failure on to the caller.
|
|
45
|
+
*/
|
|
46
|
+
const reportDataFetchError = async (_method, params, body) => {
|
|
47
|
+
var _a;
|
|
48
|
+
try {
|
|
49
|
+
return await body(params);
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
if (!((_a = params.signal) === null || _a === void 0 ? void 0 : _a.aborted)) {
|
|
53
|
+
errorService.report(ErrorCode.DATA_FETCH, error);
|
|
54
|
+
}
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
40
58
|
/**
|
|
41
59
|
* Builds a Reactodia {@link SparqlDataProvider} for the given endpoint using the supplied
|
|
42
60
|
* query preset. The host owns the query configuration and always passes it in via props.
|
|
61
|
+
* The provider is decorated, so its failed calls are reported.
|
|
43
62
|
*/
|
|
44
63
|
function createDataProvider(props) {
|
|
45
64
|
const { currentRepository, config, providerSettings } = props;
|
|
46
|
-
|
|
65
|
+
const baseProvider = new SparqlDataProvider({
|
|
47
66
|
endpointUrl: currentRepository,
|
|
48
67
|
queryMethod: 'POST',
|
|
49
68
|
queryFunction: config.queryFunction
|
|
50
69
|
}, providerSettings);
|
|
70
|
+
return new DecoratedDataProvider({ baseProvider, decorator: reportDataFetchError });
|
|
51
71
|
}
|
|
52
72
|
/**
|
|
53
73
|
* Places the seed entities on the canvas. Each IRI is added as a placeholder element, and data is then loaded for the
|
|
@@ -142,22 +162,31 @@ function ReactodiaApp(props) {
|
|
|
142
162
|
const dataProvider = createDataProvider(props);
|
|
143
163
|
const isReload = props.isReload;
|
|
144
164
|
const savedDiagram = diagramStorageService.load();
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
165
|
+
try {
|
|
166
|
+
if (isReload) {
|
|
167
|
+
// Reload the diagram that is currently on the canvas. This may happen when the host changes the provider
|
|
168
|
+
// settings, or when the user switches the language at runtime, since there is no existing mechanism to
|
|
169
|
+
// re-translate the UI at runtime (not for the UI labels at least)
|
|
170
|
+
await diagramService.importDiagram(model, dataProvider, currentDiagram, signal);
|
|
171
|
+
}
|
|
172
|
+
else if ((_a = config.seedIris) === null || _a === void 0 ? void 0 : _a.length) {
|
|
173
|
+
await seedIrisToCanvas(context, dataProvider, config.seedIris, signal);
|
|
174
|
+
}
|
|
175
|
+
else if ((_b = config.seedGraph) === null || _b === void 0 ? void 0 : _b.length) {
|
|
176
|
+
await seedGraphToCanvas(context, dataProvider, config.seedGraph, signal);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
// Restore the previously saved layout when present, otherwise start empty. Either way this binds the
|
|
180
|
+
// data provider (savedDiagram is undefined -> empty diagram), so the unified search/lookup works.
|
|
181
|
+
await diagramService.importDiagram(model, dataProvider, savedDiagram, signal);
|
|
182
|
+
}
|
|
150
183
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
else {
|
|
158
|
-
// Restore the previously saved layout when present, otherwise start empty. Either way this binds the
|
|
159
|
-
// data provider (savedDiagram is undefined -> empty diagram), so the unified search/lookup works.
|
|
160
|
-
await diagramService.importDiagram(model, dataProvider, savedDiagram, signal);
|
|
184
|
+
catch (error) {
|
|
185
|
+
if (!signal.aborted) {
|
|
186
|
+
errorService.report(ErrorCode.DIAGRAM_LOAD, error);
|
|
187
|
+
}
|
|
188
|
+
// rethrow, so the workspace shows the failure on its loading spinner
|
|
189
|
+
throw error;
|
|
161
190
|
}
|
|
162
191
|
}, [language]);
|
|
163
192
|
/**
|
|
@@ -194,7 +223,7 @@ export function mountReactodia(container, props) {
|
|
|
194
223
|
/**
|
|
195
224
|
* Re-points the diagram at a new SPARQL endpoint by recreating it with a fresh data provider.
|
|
196
225
|
* The canvas is reset to empty, matching the initial mount, since the data of another repository
|
|
197
|
-
* has nothing to do with the current graph.
|
|
226
|
+
* has nothing to do with the current graph. A failure is reported, not thrown.
|
|
198
227
|
*/
|
|
199
228
|
export async function updateReactodia(props) {
|
|
200
229
|
if (!workspaceContext) {
|
|
@@ -202,7 +231,12 @@ export async function updateReactodia(props) {
|
|
|
202
231
|
}
|
|
203
232
|
const { model } = workspaceContext;
|
|
204
233
|
const dataProvider = createDataProvider(props);
|
|
205
|
-
|
|
234
|
+
try {
|
|
235
|
+
await model.createNewDiagram({ dataProvider });
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
errorService.report(ErrorCode.DIAGRAM_LOAD, error);
|
|
239
|
+
}
|
|
206
240
|
}
|
|
207
241
|
/**
|
|
208
242
|
* Serializes the current diagram so it can be restored after a remount (e.g. when a
|
|
@@ -12,26 +12,42 @@ var DiagramStorageService_1;
|
|
|
12
12
|
import { Service } from "../../providers/service/service";
|
|
13
13
|
import { service } from "../../providers/service/service-inject";
|
|
14
14
|
import { WindowService } from "../window/window.service";
|
|
15
|
+
import { ErrorService } from "../error/error.service";
|
|
16
|
+
import { ErrorCode } from "../../models/error/error-code";
|
|
15
17
|
/**
|
|
16
18
|
* Service for local store-related diagram operations
|
|
17
19
|
*/
|
|
18
20
|
let DiagramStorageService = DiagramStorageService_1 = class DiagramStorageService {
|
|
21
|
+
constructor() {
|
|
22
|
+
this.errorService = service(ErrorService);
|
|
23
|
+
}
|
|
19
24
|
/**
|
|
20
25
|
* Load the persisted diagram from the local store, or `undefined` when nothing is stored (or the stored value
|
|
21
26
|
* is unreadable).
|
|
22
27
|
*/
|
|
23
28
|
load() {
|
|
24
|
-
|
|
25
|
-
|
|
29
|
+
try {
|
|
30
|
+
const raw = this.storage.getItem(DiagramStorageService_1.STORAGE_KEY);
|
|
31
|
+
if (!raw) {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
return JSON.parse(raw);
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
this.errorService.report(ErrorCode.LOCAL_DIAGRAM_READ, error);
|
|
26
38
|
return undefined;
|
|
27
39
|
}
|
|
28
|
-
return JSON.parse(raw);
|
|
29
40
|
}
|
|
30
41
|
/**
|
|
31
42
|
* Persists the given diagram serialization.
|
|
32
43
|
*/
|
|
33
44
|
save(diagram) {
|
|
34
|
-
|
|
45
|
+
try {
|
|
46
|
+
this.storage.setItem(DiagramStorageService_1.STORAGE_KEY, JSON.stringify(diagram));
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
this.errorService.report(ErrorCode.LOCAL_DIAGRAM_SAVE, error);
|
|
50
|
+
}
|
|
35
51
|
}
|
|
36
52
|
/**
|
|
37
53
|
* Removes the persisted diagram. Used when a new view (a seed) should take precedence over
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
|
|
4
|
+
r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else
|
|
6
|
+
for (var i = decorators.length - 1; i >= 0; i--)
|
|
7
|
+
if (d = decorators[i])
|
|
8
|
+
r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
9
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
10
|
+
};
|
|
11
|
+
var ErrorService_1;
|
|
12
|
+
import { Service } from "../../providers/service/service";
|
|
13
|
+
import { service } from "../../providers/service/service-inject";
|
|
14
|
+
import { EventType } from "../../models/event/event-type";
|
|
15
|
+
import { EventService } from "../event/event.service";
|
|
16
|
+
/**
|
|
17
|
+
* Service that collects the failures of the wrapper and the fork, so they can be announced to the host.
|
|
18
|
+
*/
|
|
19
|
+
let ErrorService = ErrorService_1 = class ErrorService {
|
|
20
|
+
constructor() {
|
|
21
|
+
this.eventService = service(EventService);
|
|
22
|
+
this.reported = new WeakSet();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Reports a failure to the host, unless it's an abort, or this exact error object is already reported
|
|
26
|
+
* from another place.
|
|
27
|
+
*
|
|
28
|
+
* The same error object may be reported from different places. E.g. a query that fails while a diagram loads is
|
|
29
|
+
* reported by the data provider decorator as `data-fetch`, and then reaches the `catch` around the load, which
|
|
30
|
+
* reports it as `diagram-load`. Only the first one is announced.
|
|
31
|
+
*
|
|
32
|
+
* The `cause` is checked because the fork wraps whatever fails during a diagram import in a new error:
|
|
33
|
+
*
|
|
34
|
+
* ```ts
|
|
35
|
+
* // reactodia-workspace/src/editor/dataDiagramModel.ts, importLayout
|
|
36
|
+
* } catch (error) {
|
|
37
|
+
* throw new Error('Reactodia: failed to import a layout', {cause: error});
|
|
38
|
+
* }
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* We need to check the cause to make sure we don't report the same error/abort more than once.
|
|
42
|
+
*
|
|
43
|
+
* @param code The category of the failure.
|
|
44
|
+
* @param thrown The thrown value.
|
|
45
|
+
*/
|
|
46
|
+
report(code, thrown) {
|
|
47
|
+
const causes = this.causeChain(thrown);
|
|
48
|
+
if (this.isAbortedOrAlreadyReported(causes)) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
causes.forEach((cause) => this.reported.add(cause));
|
|
52
|
+
this.eventService.emit({ type: EventType.ERROR, payload: { code, error: thrown } });
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Whether any link of the given cause chain is an abort or is already reported.
|
|
56
|
+
*/
|
|
57
|
+
isAbortedOrAlreadyReported(causes) {
|
|
58
|
+
return causes.some((cause) => cause.name === ErrorService_1.ABORT_ERROR_NAME || this.reported.has(cause));
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* The thrown value followed by its `cause`, the cause of that, and so on, for as long as they are objects.
|
|
62
|
+
*/
|
|
63
|
+
causeChain(thrown) {
|
|
64
|
+
const causes = [];
|
|
65
|
+
let current = thrown;
|
|
66
|
+
while (typeof current === 'object' && current !== null && !causes.includes(current)) {
|
|
67
|
+
causes.push(current);
|
|
68
|
+
current = current.cause;
|
|
69
|
+
}
|
|
70
|
+
return causes;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
ErrorService.ID = 'ErrorService';
|
|
74
|
+
ErrorService.ABORT_ERROR_NAME = 'AbortError';
|
|
75
|
+
ErrorService = ErrorService_1 = __decorate([
|
|
76
|
+
Service
|
|
77
|
+
], ErrorService);
|
|
78
|
+
export { ErrorService };
|
|
@@ -16,6 +16,29 @@ import { WindowService } from "../window/window.service";
|
|
|
16
16
|
* Service for event based operations
|
|
17
17
|
*/
|
|
18
18
|
let EventService = class EventService {
|
|
19
|
+
/**
|
|
20
|
+
* Announces an event to the host.
|
|
21
|
+
*
|
|
22
|
+
* @param detail The event detail.
|
|
23
|
+
*/
|
|
24
|
+
emit(detail) {
|
|
25
|
+
var _a;
|
|
26
|
+
(_a = this.callback) === null || _a === void 0 ? void 0 : _a.call(this, detail);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Subscribes to the emitted events, replacing the previous subscriber.
|
|
30
|
+
*
|
|
31
|
+
* @param callback Called with every emitted event.
|
|
32
|
+
* @returns A {@link Subscription} that, when called, removes the callback, unless it has already been replaced.
|
|
33
|
+
*/
|
|
34
|
+
subscribe(callback) {
|
|
35
|
+
this.callback = callback;
|
|
36
|
+
return () => {
|
|
37
|
+
if (this.callback === callback) {
|
|
38
|
+
this.callback = undefined;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
19
42
|
/**
|
|
20
43
|
* Subscribes to the host's "clear persisted diagram" command.
|
|
21
44
|
*
|
package/dist/collection/index.js
CHANGED
|
@@ -1 +1,4 @@
|
|
|
1
1
|
export { CLEAR_DIAGRAM_STORAGE_EVENT } from './components/graphwise-reactodia/models/clear-diagram-storage-event';
|
|
2
|
+
export { GRAPHWISE_REACTODIA_EVENT } from './components/graphwise-reactodia/models/event/event-detail';
|
|
3
|
+
export { EventType } from './components/graphwise-reactodia/models/event/event-type';
|
|
4
|
+
export { ErrorCode } from './components/graphwise-reactodia/models/error/error-code';
|
|
@@ -17,6 +17,39 @@ async function stubQueryFunction(params) {
|
|
|
17
17
|
return new Response('', {headers: {'Content-Type': 'text/turtle'}});
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
// A transport that always fails, as an unreachable or misconfigured endpoint would.
|
|
21
|
+
async function failingQueryFunction() {
|
|
22
|
+
throw new Error('Query failed');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// A transport that never answers. Once its request is cancelled it fails with an ordinary error, as a transport
|
|
26
|
+
// that does not throw an `AbortError` would. The pending and the cancelled requests are counted.
|
|
27
|
+
window.pendingQueries = 0;
|
|
28
|
+
window.cancelledQueries = 0;
|
|
29
|
+
|
|
30
|
+
function hangingQueryFunction(params) {
|
|
31
|
+
window.pendingQueries++;
|
|
32
|
+
return new Promise((_resolve, reject) => {
|
|
33
|
+
params.signal?.addEventListener('abort', () => {
|
|
34
|
+
window.pendingQueries--;
|
|
35
|
+
window.cancelledQueries++;
|
|
36
|
+
reject(new Error('Request cancelled'));
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// The errors the component reports are recorded, so the tests can tell what the host was notified of.
|
|
42
|
+
const reportedErrors = [];
|
|
43
|
+
window.reportedErrors = reportedErrors;
|
|
44
|
+
// The listener is on the document, since the tests replace the element.
|
|
45
|
+
document.addEventListener('graphwiseReactodiaEvent', (event) => {
|
|
46
|
+
if (event.detail.type !== 'error') {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const {code, error} = event.detail.payload;
|
|
50
|
+
reportedErrors.push({code, message: error.message});
|
|
51
|
+
});
|
|
52
|
+
|
|
20
53
|
const SEED_NODES = ['http://example.com/alice', 'http://example.com/bob'];
|
|
21
54
|
|
|
22
55
|
const SEED_GRAPH = [
|
|
@@ -33,6 +66,14 @@ function setQueryFunction() {
|
|
|
33
66
|
reactodia.config = {...reactodia.config, queryFunction: stubQueryFunction};
|
|
34
67
|
}
|
|
35
68
|
|
|
69
|
+
function setFailingQueryFunction() {
|
|
70
|
+
reactodia.config = {...reactodia.config, queryFunction: failingQueryFunction};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function setHangingQueryFunction() {
|
|
74
|
+
reactodia.config = {...reactodia.config, queryFunction: hangingQueryFunction};
|
|
75
|
+
}
|
|
76
|
+
|
|
36
77
|
// The wrapper has no default preset, so the host always passes one. The demo uses Reactodia's generic
|
|
37
78
|
// OWL/RDFS preset, copied into `owl-rdfs-settings.js`.
|
|
38
79
|
function setProviderSettings() {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event name for clearing the local store state of the diagram. There is an event listener listening for it, which
|
|
3
|
+
* will clear the local store state, whenever this event is fired.
|
|
4
|
+
*/
|
|
5
|
+
const CLEAR_DIAGRAM_STORAGE_EVENT = 'graphwise-reactodia:clear-diagram-storage';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The kind of event the wrapper announces to the host. It selects the payload of an {@link EventDetail}.
|
|
9
|
+
*/
|
|
10
|
+
var EventType;
|
|
11
|
+
(function (EventType) {
|
|
12
|
+
EventType["ERROR"] = "error";
|
|
13
|
+
})(EventType || (EventType = {}));
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The stable category of a reported error. The host uses it to choose its own message.
|
|
17
|
+
*/
|
|
18
|
+
var ErrorCode;
|
|
19
|
+
(function (ErrorCode) {
|
|
20
|
+
/** A required prop is missing. */
|
|
21
|
+
ErrorCode["MISSING_REQUIRED_PROP"] = "missing-required-prop";
|
|
22
|
+
/** A SPARQL data provider call failed. */
|
|
23
|
+
ErrorCode["DATA_FETCH"] = "data-fetch";
|
|
24
|
+
/** The startup load, a reload or a repository switch failed. */
|
|
25
|
+
ErrorCode["DIAGRAM_LOAD"] = "diagram-load";
|
|
26
|
+
/** The uploaded file was rejected or its import failed. */
|
|
27
|
+
ErrorCode["DIAGRAM_IMPORT"] = "diagram-import";
|
|
28
|
+
/** Reading the diagram from local storage failed. */
|
|
29
|
+
ErrorCode["LOCAL_DIAGRAM_READ"] = "local-diagram-read";
|
|
30
|
+
/** Saving the diagram in local storage failed. */
|
|
31
|
+
ErrorCode["LOCAL_DIAGRAM_SAVE"] = "local-diagram-save";
|
|
32
|
+
})(ErrorCode || (ErrorCode = {}));
|
|
33
|
+
|
|
34
|
+
export { CLEAR_DIAGRAM_STORAGE_EVENT as C, EventType as E, ErrorCode as a };
|