graphwise-reactodia 0.0.1-TR2 → 0.0.1-TR20

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.
Files changed (117) hide show
  1. package/COPYING +674 -0
  2. package/COPYING.LESSER +165 -0
  3. package/NOTICE +41 -0
  4. package/README.md +225 -1
  5. package/dist/cjs/graphwise-reactodia.cjs.entry.js +28519 -41232
  6. package/dist/cjs/graphwise-reactodia.cjs.js +2 -2
  7. package/dist/cjs/{index-CII9aUQC.js → index-DtzCybH4.js} +16 -0
  8. package/dist/cjs/index.cjs.js +29 -0
  9. package/dist/cjs/loader.cjs.js +2 -2
  10. package/dist/cjs/node-action-DkJ5ct17.js +96 -0
  11. package/dist/collection/components/graphwise-reactodia/graphwise-reactodia.css +57 -1
  12. package/dist/collection/components/graphwise-reactodia/graphwise-reactodia.js +135 -40
  13. package/dist/collection/components/graphwise-reactodia/i18n/language-key.js +5 -0
  14. package/dist/collection/components/graphwise-reactodia/i18n/translations.js +6 -1
  15. package/dist/collection/components/graphwise-reactodia/menu/export-diagram-action.js +19 -0
  16. package/dist/collection/components/graphwise-reactodia/menu/graphwise-menu.js +24 -0
  17. package/dist/collection/components/graphwise-reactodia/menu/import-diagram-action.js +31 -0
  18. package/dist/collection/components/graphwise-reactodia/models/clear-diagram-storage-event.js +5 -0
  19. package/dist/collection/components/graphwise-reactodia/models/error/error-cause.js +1 -0
  20. package/dist/collection/components/graphwise-reactodia/models/error/error-code.js +20 -0
  21. package/dist/collection/components/graphwise-reactodia/models/error/error-report.js +1 -0
  22. package/dist/collection/components/graphwise-reactodia/models/event/event-callback.js +1 -0
  23. package/dist/collection/components/graphwise-reactodia/models/event/event-detail.js +4 -0
  24. package/dist/collection/components/graphwise-reactodia/models/event/event-type.js +8 -0
  25. package/dist/collection/components/graphwise-reactodia/models/reactodia-config.js +1 -0
  26. package/dist/collection/components/graphwise-reactodia/models/sparql/sparql-query-function.js +1 -0
  27. package/dist/collection/components/graphwise-reactodia/models/sparql/sparql-query-params.js +1 -0
  28. package/dist/collection/components/graphwise-reactodia/models/subscription-list.js +35 -0
  29. package/dist/collection/components/graphwise-reactodia/models/subscription.js +1 -0
  30. package/dist/collection/components/graphwise-reactodia/models/triple.js +1 -0
  31. package/dist/collection/components/graphwise-reactodia/models/ui/menu-config.js +1 -0
  32. package/dist/collection/components/graphwise-reactodia/models/ui/menu-item.js +18 -0
  33. package/dist/collection/components/graphwise-reactodia/models/ui/node-action.js +22 -0
  34. package/dist/collection/components/graphwise-reactodia/models/ui/resolved-toolbar-position.js +1 -0
  35. package/dist/collection/components/graphwise-reactodia/models/ui/resolved-ui-config.js +1 -0
  36. package/dist/collection/components/graphwise-reactodia/models/ui/toolbar-dock.js +14 -0
  37. package/dist/collection/components/graphwise-reactodia/models/ui/toolbar-position.js +1 -0
  38. package/dist/collection/components/graphwise-reactodia/models/ui/ui-config.js +1 -0
  39. package/dist/collection/components/graphwise-reactodia/node-action/node-actions.js +22 -0
  40. package/dist/collection/components/graphwise-reactodia/providers/service/service-inject.js +15 -0
  41. package/dist/collection/components/graphwise-reactodia/providers/service/service.js +19 -0
  42. package/dist/collection/components/graphwise-reactodia/providers/service/service.provider.js +20 -0
  43. package/dist/collection/components/graphwise-reactodia/reactodia-app.js +188 -26
  44. package/dist/collection/components/graphwise-reactodia/services/diagram/diagram.service.js +71 -0
  45. package/dist/collection/components/graphwise-reactodia/services/diagram-file/diagram-file.service.js +68 -0
  46. package/dist/collection/components/graphwise-reactodia/services/diagram-storage/diagram-storage.service.js +71 -0
  47. package/dist/collection/components/graphwise-reactodia/services/error/error.service.js +78 -0
  48. package/dist/collection/components/graphwise-reactodia/services/event/event.service.js +58 -0
  49. package/dist/collection/components/graphwise-reactodia/services/window/window.service.js +24 -0
  50. package/dist/collection/components/graphwise-reactodia/styles/type-style.resolver.js +52 -0
  51. package/dist/collection/components/graphwise-reactodia/testing/storage.mock.js +35 -0
  52. package/dist/collection/components/graphwise-reactodia/ui-config/default-ui-config.js +30 -0
  53. package/dist/collection/components/graphwise-reactodia/ui-config/ui-config-mapper.js +51 -0
  54. package/dist/collection/components/graphwise-reactodia/utils/object-util.js +30 -0
  55. package/dist/collection/index.js +7 -1
  56. package/dist/collection/pages/graphwise-reactodia/main.js +157 -0
  57. package/dist/collection/pages/graphwise-reactodia/owl-rdfs-settings.js +195 -0
  58. package/dist/esm/graphwise-reactodia.entry.js +28519 -41232
  59. package/dist/esm/graphwise-reactodia.js +3 -3
  60. package/dist/esm/{index-Cypw7ydc.js → index-DpCR6zMg.js} +16 -1
  61. package/dist/esm/index.js +7 -0
  62. package/dist/esm/loader.js +3 -3
  63. package/dist/esm/node-action-fwJ3Zupw.js +94 -0
  64. package/dist/graphwise-reactodia/graphwise-reactodia.esm.js +1 -1
  65. package/dist/graphwise-reactodia/index.esm.js +1 -0
  66. package/dist/graphwise-reactodia/p-DpCR6zMg.js +2 -0
  67. package/dist/graphwise-reactodia/p-c3d8a69a.entry.js +1 -0
  68. package/dist/graphwise-reactodia/p-fwJ3Zupw.js +1 -0
  69. package/dist/types/components/graphwise-reactodia/graphwise-reactodia.d.ts +44 -16
  70. package/dist/types/components/graphwise-reactodia/i18n/language-key.d.ts +4 -0
  71. package/dist/types/components/graphwise-reactodia/i18n/translations.d.ts +2 -343
  72. package/dist/types/components/graphwise-reactodia/menu/export-diagram-action.d.ts +4 -0
  73. package/dist/types/components/graphwise-reactodia/menu/graphwise-menu.d.ts +6 -0
  74. package/dist/types/components/graphwise-reactodia/menu/import-diagram-action.d.ts +4 -0
  75. package/dist/types/components/graphwise-reactodia/models/clear-diagram-storage-event.d.ts +5 -0
  76. package/dist/types/components/graphwise-reactodia/models/error/error-cause.d.ts +10 -0
  77. package/dist/types/components/graphwise-reactodia/models/error/error-code.d.ts +19 -0
  78. package/dist/types/components/graphwise-reactodia/models/error/error-report.d.ts +13 -0
  79. package/dist/types/components/graphwise-reactodia/models/event/event-callback.d.ts +5 -0
  80. package/dist/types/components/graphwise-reactodia/models/event/event-detail.d.ts +55 -0
  81. package/dist/types/components/graphwise-reactodia/models/event/event-type.d.ts +7 -0
  82. package/dist/types/components/graphwise-reactodia/models/reactodia-app-props.d.ts +20 -15
  83. package/dist/types/components/graphwise-reactodia/models/reactodia-config.d.ts +36 -0
  84. package/dist/types/components/graphwise-reactodia/models/sparql/sparql-query-function.d.ts +6 -0
  85. package/dist/types/components/graphwise-reactodia/models/sparql/sparql-query-params.d.ts +12 -0
  86. package/dist/types/components/graphwise-reactodia/models/subscription-list.d.ts +26 -0
  87. package/dist/types/components/graphwise-reactodia/models/subscription.d.ts +4 -0
  88. package/dist/types/components/graphwise-reactodia/models/triple.d.ts +19 -0
  89. package/dist/types/components/graphwise-reactodia/models/ui/menu-config.d.ts +8 -0
  90. package/dist/types/components/graphwise-reactodia/models/ui/menu-item.d.ts +17 -0
  91. package/dist/types/components/graphwise-reactodia/models/ui/node-action.d.ts +21 -0
  92. package/dist/types/components/graphwise-reactodia/models/ui/resolved-toolbar-position.d.ts +8 -0
  93. package/dist/types/components/graphwise-reactodia/models/ui/resolved-ui-config.d.ts +12 -0
  94. package/dist/types/components/graphwise-reactodia/models/ui/toolbar-dock.d.ts +13 -0
  95. package/dist/types/components/graphwise-reactodia/models/ui/toolbar-position.d.ts +11 -0
  96. package/dist/types/components/graphwise-reactodia/models/ui/ui-config.d.ts +17 -0
  97. package/dist/types/components/graphwise-reactodia/node-action/node-actions.d.ts +6 -0
  98. package/dist/types/components/graphwise-reactodia/providers/service/service-inject.d.ts +13 -0
  99. package/dist/types/components/graphwise-reactodia/providers/service/service.d.ts +28 -0
  100. package/dist/types/components/graphwise-reactodia/providers/service/service.provider.d.ts +16 -0
  101. package/dist/types/components/graphwise-reactodia/reactodia-app.d.ts +3 -2
  102. package/dist/types/components/graphwise-reactodia/services/diagram/diagram.service.d.ts +36 -0
  103. package/dist/types/components/graphwise-reactodia/services/diagram-file/diagram-file.service.d.ts +24 -0
  104. package/dist/types/components/graphwise-reactodia/services/diagram-storage/diagram-storage.service.d.ts +27 -0
  105. package/dist/types/components/graphwise-reactodia/services/error/error.service.d.ts +41 -0
  106. package/dist/types/components/graphwise-reactodia/services/event/event.service.d.ts +30 -0
  107. package/dist/types/components/graphwise-reactodia/services/window/window.service.d.ts +7 -0
  108. package/dist/types/components/graphwise-reactodia/styles/type-style.resolver.d.ts +11 -0
  109. package/dist/types/components/graphwise-reactodia/testing/storage.mock.d.ts +18 -0
  110. package/dist/types/components/graphwise-reactodia/ui-config/default-ui-config.d.ts +5 -0
  111. package/dist/types/components/graphwise-reactodia/ui-config/ui-config-mapper.d.ts +14 -0
  112. package/dist/types/components/graphwise-reactodia/utils/object-util.d.ts +15 -0
  113. package/dist/types/components.d.ts +60 -27
  114. package/dist/types/index.d.ts +15 -1
  115. package/package.json +39 -10
  116. package/dist/graphwise-reactodia/p-Cypw7ydc.js +0 -2
  117. package/dist/graphwise-reactodia/p-bafd6be5.entry.js +0 -1
@@ -0,0 +1,68 @@
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 DiagramFileService_1;
12
+ import { Service } from "../../providers/service/service";
13
+ import { service } from "../../providers/service/service-inject";
14
+ import { WindowService } from "../window/window.service";
15
+ /**
16
+ * Service for downloading and uploading the diagram as a file. The file content is the same
17
+ * {@link SerializedDiagram} that is persisted to the local store.
18
+ */
19
+ let DiagramFileService = DiagramFileService_1 = class DiagramFileService {
20
+ /**
21
+ * Downloads the given diagram serialization as a file with the given name.
22
+ */
23
+ download(diagram, fileName) {
24
+ const window = service(WindowService).getWindow();
25
+ const blob = new Blob([JSON.stringify(diagram)], { type: DiagramFileService_1.MIME_TYPE });
26
+ const url = window.URL.createObjectURL(blob);
27
+ const link = window.document.createElement('a');
28
+ link.href = url;
29
+ link.download = fileName;
30
+ link.click();
31
+ window.URL.revokeObjectURL(url);
32
+ }
33
+ /**
34
+ * Reads a diagram serialization from the given file.
35
+ *
36
+ * @throws Error when the file is not valid JSON or is not a serialized diagram.
37
+ */
38
+ async read(file) {
39
+ let diagram;
40
+ try {
41
+ diagram = JSON.parse(await file.text());
42
+ }
43
+ catch (error) {
44
+ throw new Error(`File "${file.name}" is not valid JSON: ${error.message}`);
45
+ }
46
+ if (!this.isSerializedDiagram(diagram)) {
47
+ throw new Error(`File "${file.name}" is not a serialized diagram`);
48
+ }
49
+ return diagram;
50
+ }
51
+ /**
52
+ * Checks if the provided value is a serialized diagram
53
+ */
54
+ isSerializedDiagram(value) {
55
+ var _a, _b;
56
+ const diagram = value;
57
+ return (diagram === null || diagram === void 0 ? void 0 : diagram['@type']) === 'Diagram'
58
+ && Array.isArray((_a = diagram.layoutData) === null || _a === void 0 ? void 0 : _a.elements)
59
+ && Array.isArray((_b = diagram.layoutData) === null || _b === void 0 ? void 0 : _b.links);
60
+ }
61
+ };
62
+ DiagramFileService.ID = 'DiagramFileService';
63
+ DiagramFileService.FILE_EXTENSION = '.json';
64
+ DiagramFileService.MIME_TYPE = 'application/json';
65
+ DiagramFileService = DiagramFileService_1 = __decorate([
66
+ Service
67
+ ], DiagramFileService);
68
+ export { DiagramFileService };
@@ -0,0 +1,71 @@
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 DiagramStorageService_1;
12
+ import { Service } from "../../providers/service/service";
13
+ import { service } from "../../providers/service/service-inject";
14
+ import { WindowService } from "../window/window.service";
15
+ import { ErrorService } from "../error/error.service";
16
+ import { ErrorCode } from "../../models/error/error-code";
17
+ /**
18
+ * Service for local store-related diagram operations
19
+ */
20
+ let DiagramStorageService = DiagramStorageService_1 = class DiagramStorageService {
21
+ constructor() {
22
+ this.errorService = service(ErrorService);
23
+ }
24
+ /**
25
+ * Load the persisted diagram from the local store, or `undefined` when nothing is stored (or the stored value
26
+ * is unreadable).
27
+ */
28
+ load() {
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);
38
+ return undefined;
39
+ }
40
+ }
41
+ /**
42
+ * Persists the given diagram serialization.
43
+ */
44
+ save(diagram) {
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
+ }
51
+ }
52
+ /**
53
+ * Removes the persisted diagram. Used when a new view (a seed) should take precedence over
54
+ * previously saved edits.
55
+ */
56
+ clear() {
57
+ this.storage.removeItem(DiagramStorageService_1.STORAGE_KEY);
58
+ }
59
+ /**
60
+ * Local storage getter
61
+ */
62
+ get storage() {
63
+ return service(WindowService).getWindow().localStorage;
64
+ }
65
+ };
66
+ DiagramStorageService.ID = 'DiagramStorageService';
67
+ DiagramStorageService.STORAGE_KEY = 'diagram.state';
68
+ DiagramStorageService = DiagramStorageService_1 = __decorate([
69
+ Service
70
+ ], DiagramStorageService);
71
+ export { DiagramStorageService };
@@ -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 };
@@ -0,0 +1,58 @@
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
+ import { Service } from "../../providers/service/service";
12
+ import { CLEAR_DIAGRAM_STORAGE_EVENT } from "../../models/clear-diagram-storage-event";
13
+ import { service } from "../../providers/service/service-inject";
14
+ import { WindowService } from "../window/window.service";
15
+ /**
16
+ * Service for event based operations
17
+ */
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
+ }
42
+ /**
43
+ * Subscribes to the host's "clear persisted diagram" command.
44
+ *
45
+ * @param onClear Called whenever the event fires.
46
+ * @returns A {@link Subscription} that, when called, removes the listener.
47
+ */
48
+ subscribeToClearDiagramStorage(onClear) {
49
+ const target = service(WindowService).getWindow();
50
+ target.addEventListener(CLEAR_DIAGRAM_STORAGE_EVENT, onClear);
51
+ return () => target.removeEventListener(CLEAR_DIAGRAM_STORAGE_EVENT, onClear);
52
+ }
53
+ };
54
+ EventService.ID = 'EventService';
55
+ EventService = __decorate([
56
+ Service
57
+ ], EventService);
58
+ export { EventService };
@@ -0,0 +1,24 @@
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
+ import { Service } from "../../providers/service/service";
12
+ /**
13
+ * Service that provides access to browser window-related functionality.
14
+ */
15
+ let WindowService = class WindowService {
16
+ getWindow() {
17
+ return window;
18
+ }
19
+ };
20
+ WindowService.ID = 'WindowService';
21
+ WindowService = __decorate([
22
+ Service
23
+ ], WindowService);
24
+ export { WindowService };
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Color slot assigned to each type, in the order the types are first seen.
3
+ */
4
+ const typeToIndex = new Map();
5
+ /**
6
+ * Returns the internal property of the given palette slot, numbered from 1 and padded to two digits as in `_theme.scss`.
7
+ */
8
+ function getTypeColorProperty(slot) {
9
+ return `--_graphwise-reactodia-type-color-${String(slot).padStart(2, '0')}`;
10
+ }
11
+ /**
12
+ * Reads the type palette of the Theme API: the internal properties `_theme.scss` resolves from the ones
13
+ * the host declares, in slot order up to the first empty one.
14
+ */
15
+ function getPalette() {
16
+ const host = document.querySelector('graphwise-reactodia');
17
+ if (!host) {
18
+ return [];
19
+ }
20
+ const style = getComputedStyle(host);
21
+ const palette = [];
22
+ let color = style.getPropertyValue(getTypeColorProperty(1)).trim();
23
+ while (color) {
24
+ palette.push(color);
25
+ color = style.getPropertyValue(getTypeColorProperty(palette.length + 1)).trim();
26
+ }
27
+ return palette;
28
+ }
29
+ /**
30
+ * Colors an element by its type: each type takes the next color from the palette, which wraps
31
+ * around once it runs out
32
+ *
33
+ * Returns `undefined` for elements without a type (placeholders and other non-entity elements) and
34
+ * when the host does not define the palette, leaving Reactodia to fall back to its own hash-based
35
+ * colors.
36
+ */
37
+ export const resolveTypeStyle = (types) => {
38
+ const type = types[0];
39
+ if (!type) {
40
+ return undefined;
41
+ }
42
+ let index = typeToIndex.get(type);
43
+ if (index === undefined) {
44
+ index = typeToIndex.size;
45
+ typeToIndex.set(type, index);
46
+ }
47
+ const colors = getPalette();
48
+ return colors.length ? { color: colors[index % colors.length] } : undefined;
49
+ };
50
+ export const resetColors = () => {
51
+ typeToIndex.clear();
52
+ };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Minimal in-memory {@link Storage}, so services that read `localStorage` can be exercised
3
+ * without a real browser store and asserted against directly. Shared across test suites.
4
+ */
5
+ export class StorageMock {
6
+ constructor() {
7
+ this.store = new Map();
8
+ }
9
+ get length() {
10
+ return this.store.size;
11
+ }
12
+ clear() {
13
+ this.store.clear();
14
+ }
15
+ getItem(key) {
16
+ return this.store.has(key) ? this.store.get(key) : null;
17
+ }
18
+ key(index) {
19
+ var _a;
20
+ return (_a = Array.from(this.store.keys())[index]) !== null && _a !== void 0 ? _a : null;
21
+ }
22
+ removeItem(key) {
23
+ this.store.delete(key);
24
+ }
25
+ setItem(key, value) {
26
+ this.store.set(key, value);
27
+ }
28
+ }
29
+ /**
30
+ * Creates a fresh {@link StorageMock}. Suites install the returned instance as the global
31
+ * `localStorage` themselves.
32
+ */
33
+ export function createStorageMock() {
34
+ return new StorageMock();
35
+ }
@@ -0,0 +1,30 @@
1
+ import { MenuItem } from "../models/ui/menu-item";
2
+ import { NodeAction } from "../models/ui/node-action";
3
+ import { ToolbarDock } from "../models/ui/toolbar-dock";
4
+ /**
5
+ * The default UI configuration: Reactodia's behaviour, plus the diagram download and upload in the menu.
6
+ */
7
+ export const DEFAULT_UI_CONFIG = {
8
+ mainToolbar: { dock: ToolbarDock.NW },
9
+ actionsToolbar: { dock: ToolbarDock.SW },
10
+ menu: {
11
+ items: [
12
+ MenuItem.CLEAR_ALL,
13
+ MenuItem.EXPORT_PNG,
14
+ MenuItem.EXPORT_SVG,
15
+ MenuItem.PRINT,
16
+ MenuItem.EXPORT_JSON,
17
+ MenuItem.IMPORT_JSON
18
+ ]
19
+ },
20
+ nodeActions: [
21
+ NodeAction.GROUP,
22
+ NodeAction.REMOVE,
23
+ NodeAction.EXPAND,
24
+ NodeAction.OPEN_LINK,
25
+ NodeAction.CONNECTIONS,
26
+ NodeAction.ADD_TO_FILTER,
27
+ NodeAction.ANNOTATE,
28
+ NodeAction.ESTABLISH_LINK
29
+ ]
30
+ };
@@ -0,0 +1,51 @@
1
+ import { createElement, Fragment } from "react";
2
+ import { ToolbarDock } from "../models/ui/toolbar-dock";
3
+ import { MenuItem } from "../models/ui/menu-item";
4
+ import { NodeAction } from "../models/ui/node-action";
5
+ import { ErrorCode } from "../models/error/error-code";
6
+ import { service } from "../providers/service/service-inject";
7
+ import { ErrorService } from "../services/error/error.service";
8
+ import { mergeWithDefaults } from "../utils/object-util";
9
+ import { DEFAULT_UI_CONFIG } from "./default-ui-config";
10
+ import { createMenuItems } from "../menu/graphwise-menu";
11
+ import { createNodeActions } from "../node-action/node-actions";
12
+ const errorService = service(ErrorService);
13
+ /**
14
+ * Merges the host's UI configuration over the default and maps the result to `DefaultWorkspace` props. A `null` or
15
+ * missing field keeps the default; objects merge key by key and lists replace the default whole. Unknown values are
16
+ * reported and left out; a repeated list entry is kept once.
17
+ *
18
+ * @param ui The host's UI configuration.
19
+ */
20
+ export function toWorkspaceProps(ui) {
21
+ const resolved = mergeWithDefaults(ui !== null && ui !== void 0 ? ui : {}, DEFAULT_UI_CONFIG);
22
+ const menuItems = [...new Set(resolved.menu.items)].filter((item) => isValid(item, MenuItem));
23
+ const nodeActions = [...new Set(resolved.nodeActions)].filter((action) => isValid(action, NodeAction));
24
+ return {
25
+ menu: menuItems.length ? createElement(Fragment, null, createMenuItems(menuItems)) : null,
26
+ mainToolbar: toToolbarProps(resolved.mainToolbar, DEFAULT_UI_CONFIG.mainToolbar),
27
+ actionsToolbar: toToolbarProps(resolved.actionsToolbar, DEFAULT_UI_CONFIG.actionsToolbar),
28
+ halo: { children: createNodeActions(nodeActions) }
29
+ };
30
+ }
31
+ /**
32
+ * Maps a toolbar position to the `DefaultWorkspace` toolbar props. With an unknown dock, `defaultPosition` is used
33
+ * whole, since the offsets are relative to the dock.
34
+ */
35
+ function toToolbarProps(position, defaultPosition) {
36
+ const { dock, offsetX, offsetY } = isValid(position.dock, ToolbarDock) ? position : defaultPosition;
37
+ return { dock, dockOffsetX: offsetX, dockOffsetY: offsetY };
38
+ }
39
+ /**
40
+ * Whether `value` is one of the `known` values. Reports it as unknown UI configuration when it is not.
41
+ *
42
+ * @param value The value from the UI configuration.
43
+ * @param known The known values, e.g. an enum.
44
+ */
45
+ function isValid(value, known) {
46
+ const isValid = Object.values(known).includes(value);
47
+ if (!isValid) {
48
+ errorService.report(ErrorCode.UNKNOWN_UI_CONFIG, new Error(`Unknown UI configuration value: "${value}"`));
49
+ }
50
+ return isValid;
51
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Merges an object with default values. Ported from the GraphDB Workbench `ObjectUtil.mergeWithDefaults`.
3
+ *
4
+ * For each property in `defaults`, if the value in `object` is `null` or `undefined`, the default value is used instead.
5
+ * Nested objects are merged recursively. Arrays and other non-plain values are treated as single values and are not
6
+ * merged.
7
+ *
8
+ * The returned object is a new object and does not share references with the inputs. The inputs must be
9
+ * structured-cloneable.
10
+ *
11
+ * @param object Source object whose values take precedence over defaults.
12
+ * @param defaults Default values applied when properties are missing or null.
13
+ * @returns A new object containing the merged result.
14
+ */
15
+ export function mergeWithDefaults(object, defaults) {
16
+ const result = structuredClone(object);
17
+ Object.entries(defaults).forEach(([key, defaultValue]) => {
18
+ const value = result[key];
19
+ if (value === null || value === undefined) {
20
+ result[key] = structuredClone(defaultValue);
21
+ }
22
+ else if (isPlainObject(value) && isPlainObject(defaultValue)) {
23
+ result[key] = mergeWithDefaults(value, defaultValue);
24
+ }
25
+ });
26
+ return result;
27
+ }
28
+ function isPlainObject(value) {
29
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
30
+ }
@@ -1 +1,7 @@
1
- export {};
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';
5
+ export { ToolbarDock } from './components/graphwise-reactodia/models/ui/toolbar-dock';
6
+ export { MenuItem } from './components/graphwise-reactodia/models/ui/menu-item';
7
+ export { NodeAction } from './components/graphwise-reactodia/models/ui/node-action';
@@ -0,0 +1,157 @@
1
+ // There is no SPARQL endpoint behind the dev server, so every query is answered with an empty
2
+ // result. The shape has to match what the provider asks for: SELECT/ASK queries are parsed with
3
+ // `response.json()` and would blow up on an empty body, CONSTRUCT/DESCRIBE queries are parsed as
4
+ // turtle, where an empty body is a valid (empty) graph.
5
+ //
6
+ // The queries are recorded, so the tests can tell which provider settings built them.
7
+ const sparqlQueries = [];
8
+ window.sparqlQueries = sparqlQueries;
9
+
10
+ async function stubQueryFunction(params) {
11
+ sparqlQueries.push(params.body);
12
+ const accept = params.headers?.['Accept'] ?? '';
13
+ if (accept.includes('sparql-results+json')) {
14
+ const body = JSON.stringify({head: {vars: []}, results: {bindings: []}, boolean: false});
15
+ return new Response(body, {headers: {'Content-Type': 'application/sparql-results+json'}});
16
+ }
17
+ return new Response('', {headers: {'Content-Type': 'text/turtle'}});
18
+ }
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
+
53
+ // The text search events are counted.
54
+ window.textSearches = 0;
55
+ document.addEventListener('graphwiseReactodiaEvent', (event) => {
56
+ if (event.detail.type === 'text-search') {
57
+ window.textSearches++;
58
+ }
59
+ });
60
+
61
+ const SEED_NODES = ['http://example.com/alice', 'http://example.com/bob'];
62
+
63
+ const SEED_GRAPH = [
64
+ {
65
+ source: 'http://example.com/alice',
66
+ target: 'http://example.com/bob',
67
+ rawPredicates: ['http://example.com/knows'],
68
+ },
69
+ ];
70
+
71
+ const reactodia = document.querySelector('graphwise-reactodia');
72
+
73
+ function setQueryFunction() {
74
+ reactodia.config = {...reactodia.config, queryFunction: stubQueryFunction};
75
+ }
76
+
77
+ function setFailingQueryFunction() {
78
+ reactodia.config = {...reactodia.config, queryFunction: failingQueryFunction};
79
+ }
80
+
81
+ function setHangingQueryFunction() {
82
+ reactodia.config = {...reactodia.config, queryFunction: hangingQueryFunction};
83
+ }
84
+
85
+ // The wrapper has no default preset, so the host always passes one. The demo uses Reactodia's generic
86
+ // OWL/RDFS preset, copied into `owl-rdfs-settings.js`.
87
+ function setProviderSettings() {
88
+ reactodia.providerSettings = OWL_RDFS_SETTINGS;
89
+ }
90
+
91
+ // A runtime change goes through the `providerSettings` prop. The extra prefix marks the queries built
92
+ // with the changed settings.
93
+ function changeProviderSettings() {
94
+ reactodia.providerSettings = {
95
+ ...OWL_RDFS_SETTINGS,
96
+ defaultPrefix: `${OWL_RDFS_SETTINGS.defaultPrefix}\nPREFIX changed: <http://example.com/changed#>\n`,
97
+ };
98
+ }
99
+
100
+ // Replaces the element with a new one the way a framework such as Angular renders it: attached first, then
101
+ // the props set one by one. The component code is already loaded by then, so the component is initialized
102
+ // before it has any of its props.
103
+ function attachThenSetProps(order) {
104
+ const props = {
105
+ config: {queryFunction: stubQueryFunction, seedIris: SEED_NODES},
106
+ currentRepository: 'repo-a',
107
+ providerSettings: OWL_RDFS_SETTINGS,
108
+ language: 'fr',
109
+ theme: 'light',
110
+ };
111
+ const element = document.createElement('graphwise-reactodia');
112
+ element.dataset.test = 'reactodia';
113
+ document.querySelector('graphwise-reactodia').replaceWith(element);
114
+ order.forEach((prop) => {
115
+ element[prop] = props[prop];
116
+ });
117
+ }
118
+
119
+ function setSeed() {
120
+ reactodia.config = {...reactodia.config, seedIris: SEED_NODES};
121
+ }
122
+
123
+ function setSeedGraph() {
124
+ reactodia.config = {...reactodia.config, seedGraph: SEED_GRAPH};
125
+ }
126
+
127
+ // A partial host UI configuration, merged over the default.
128
+ const HOST_UI = {
129
+ actionsToolbar: {dock: 'ne'},
130
+ nodeActions: ['group', 'remove', 'expand', 'connections', 'add-to-filter', 'annotate', 'establish-link'],
131
+ };
132
+
133
+ function setHostUi() {
134
+ reactodia.config = {...reactodia.config, ui: HOST_UI};
135
+ }
136
+
137
+ function setEmptyMenuUi() {
138
+ reactodia.config = {...reactodia.config, ui: {menu: {items: []}}};
139
+ }
140
+
141
+ function setRepository(repository) {
142
+ reactodia.currentRepository = repository;
143
+ }
144
+
145
+ function setLanguage(language) {
146
+ reactodia.language = language;
147
+ }
148
+
149
+ function setTheme(theme) {
150
+ reactodia.theme = theme;
151
+ }
152
+
153
+ // The host asks the component to drop its persisted diagram by dispatching a namespaced window
154
+ // event, rather than holding an element reference and calling a method on it.
155
+ function clearDiagramStorage() {
156
+ window.dispatchEvent(new Event('graphwise-reactodia:clear-diagram-storage'));
157
+ }