graphwise-reactodia 0.0.1-TR13 → 0.0.1-TR15
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 +72 -42
- package/dist/collection/components/graphwise-reactodia/graphwise-reactodia.css +44 -1
- package/dist/collection/components/graphwise-reactodia/graphwise-reactodia.js +21 -7
- package/dist/collection/components/graphwise-reactodia/reactodia-app.js +24 -10
- package/dist/collection/components/graphwise-reactodia/services/diagram/diagram.service.js +4 -1
- package/dist/collection/components/graphwise-reactodia/styles/type-style.resolver.js +25 -26
- package/dist/collection/pages/graphwise-reactodia/main.js +38 -0
- package/dist/esm/graphwise-reactodia.entry.js +72 -42
- package/dist/graphwise-reactodia/graphwise-reactodia.esm.js +1 -1
- package/dist/graphwise-reactodia/p-a2c710e4.entry.js +1 -0
- package/dist/types/components/graphwise-reactodia/graphwise-reactodia.d.ts +11 -5
- package/dist/types/components/graphwise-reactodia/models/reactodia-app-props.d.ts +4 -0
- package/dist/types/components.d.ts +4 -4
- package/package.json +1 -1
- package/dist/graphwise-reactodia/p-420b9dce.entry.js +0 -1
|
@@ -31376,8 +31376,10 @@ let DiagramService = DiagramService_1 = class DiagramService {
|
|
|
31376
31376
|
clearTimeout(notifyTimer);
|
|
31377
31377
|
}
|
|
31378
31378
|
notifyTimer = setTimeout(() => {
|
|
31379
|
+
if (notifyTimer) {
|
|
31380
|
+
onChangeCallback(model.exportLayout());
|
|
31381
|
+
}
|
|
31379
31382
|
notifyTimer = undefined;
|
|
31380
|
-
onChangeCallback(model.exportLayout());
|
|
31381
31383
|
}, DiagramService_1.NOTIFY_DEBOUNCE_MS);
|
|
31382
31384
|
};
|
|
31383
31385
|
model.history.events.on(DiagramService_1.HISTORY_CHANGED_EVENT, onHistoryChange);
|
|
@@ -31385,6 +31387,7 @@ let DiagramService = DiagramService_1 = class DiagramService {
|
|
|
31385
31387
|
model.history.events.off(DiagramService_1.HISTORY_CHANGED_EVENT, onHistoryChange);
|
|
31386
31388
|
if (notifyTimer) {
|
|
31387
31389
|
clearTimeout(notifyTimer);
|
|
31390
|
+
notifyTimer = undefined;
|
|
31388
31391
|
}
|
|
31389
31392
|
};
|
|
31390
31393
|
}
|
|
@@ -31526,34 +31529,33 @@ class SubscriptionList {
|
|
|
31526
31529
|
}
|
|
31527
31530
|
}
|
|
31528
31531
|
|
|
31529
|
-
const NODE_COLOR_VARIABLES = [
|
|
31530
|
-
'--gw-foreground-visual-diagram-categorical-01',
|
|
31531
|
-
'--gw-foreground-visual-diagram-categorical-02',
|
|
31532
|
-
'--gw-foreground-visual-diagram-categorical-03',
|
|
31533
|
-
'--gw-foreground-visual-diagram-categorical-04',
|
|
31534
|
-
'--gw-foreground-visual-diagram-categorical-05',
|
|
31535
|
-
'--gw-foreground-visual-diagram-categorical-06',
|
|
31536
|
-
'--gw-foreground-visual-diagram-categorical-07',
|
|
31537
|
-
'--gw-foreground-visual-diagram-categorical-08',
|
|
31538
|
-
'--gw-foreground-visual-diagram-categorical-09',
|
|
31539
|
-
'--gw-foreground-visual-diagram-categorical-10',
|
|
31540
|
-
'--gw-foreground-visual-diagram-categorical-11',
|
|
31541
|
-
'--gw-foreground-visual-diagram-categorical-12',
|
|
31542
|
-
'--gw-foreground-visual-diagram-categorical-13',
|
|
31543
|
-
'--gw-foreground-visual-diagram-categorical-14',
|
|
31544
|
-
'--gw-foreground-visual-diagram-categorical-15',
|
|
31545
|
-
'--gw-foreground-visual-diagram-categorical-16',
|
|
31546
|
-
'--gw-foreground-visual-diagram-categorical-17',
|
|
31547
|
-
'--gw-foreground-visual-diagram-categorical-18',
|
|
31548
|
-
'--gw-foreground-visual-diagram-categorical-19',
|
|
31549
|
-
'--gw-foreground-visual-diagram-categorical-20'
|
|
31550
|
-
];
|
|
31551
31532
|
/**
|
|
31552
31533
|
* Color slot assigned to each type, in the order the types are first seen.
|
|
31553
31534
|
*/
|
|
31554
31535
|
const typeToIndex = new Map();
|
|
31555
|
-
|
|
31556
|
-
|
|
31536
|
+
/**
|
|
31537
|
+
* Returns the internal property of the given palette slot, numbered from 1 and padded to two digits as in `_theme.scss`.
|
|
31538
|
+
*/
|
|
31539
|
+
function getTypeColorProperty(slot) {
|
|
31540
|
+
return `--_graphwise-reactodia-type-color-${String(slot).padStart(2, '0')}`;
|
|
31541
|
+
}
|
|
31542
|
+
/**
|
|
31543
|
+
* Reads the type palette of the Theme API: the internal properties `_theme.scss` resolves from the ones
|
|
31544
|
+
* the host declares, in slot order up to the first empty one.
|
|
31545
|
+
*/
|
|
31546
|
+
function getPalette() {
|
|
31547
|
+
const host = document.querySelector('graphwise-reactodia');
|
|
31548
|
+
if (!host) {
|
|
31549
|
+
return [];
|
|
31550
|
+
}
|
|
31551
|
+
const style = getComputedStyle(host);
|
|
31552
|
+
const palette = [];
|
|
31553
|
+
let color = style.getPropertyValue(getTypeColorProperty(1)).trim();
|
|
31554
|
+
while (color) {
|
|
31555
|
+
palette.push(color);
|
|
31556
|
+
color = style.getPropertyValue(getTypeColorProperty(palette.length + 1)).trim();
|
|
31557
|
+
}
|
|
31558
|
+
return palette;
|
|
31557
31559
|
}
|
|
31558
31560
|
/**
|
|
31559
31561
|
* Colors an element by its type: each type takes the next color from the palette, which wraps
|
|
@@ -31573,8 +31575,8 @@ const resolveTypeStyle = (types) => {
|
|
|
31573
31575
|
index = typeToIndex.size;
|
|
31574
31576
|
typeToIndex.set(type, index);
|
|
31575
31577
|
}
|
|
31576
|
-
const
|
|
31577
|
-
return
|
|
31578
|
+
const colors = getPalette();
|
|
31579
|
+
return colors.length ? { color: colors[index % colors.length] } : undefined;
|
|
31578
31580
|
};
|
|
31579
31581
|
const resetColors = () => {
|
|
31580
31582
|
typeToIndex.clear();
|
|
@@ -31697,6 +31699,10 @@ let workspaceContext = null;
|
|
|
31697
31699
|
* the React root.
|
|
31698
31700
|
*/
|
|
31699
31701
|
const subscriptions = new SubscriptionList();
|
|
31702
|
+
let diagramStorageSubscription;
|
|
31703
|
+
const diagramService = service(DiagramService);
|
|
31704
|
+
const diagramStorageService = service(DiagramStorageService);
|
|
31705
|
+
const eventService = service(EventService);
|
|
31700
31706
|
/**
|
|
31701
31707
|
* Builds a Reactodia {@link SparqlDataProvider} for the given endpoint using the supplied
|
|
31702
31708
|
* query preset. The host owns the query configuration and always passes it in via props.
|
|
@@ -31756,20 +31762,30 @@ async function seedGraphToCanvas(context, dataProvider, links, signal) {
|
|
|
31756
31762
|
* root in {@link unmountReactodia}.
|
|
31757
31763
|
*/
|
|
31758
31764
|
function onDiagramChange(model) {
|
|
31759
|
-
|
|
31760
|
-
|
|
31761
|
-
|
|
31765
|
+
subscribeToDiagramChange(model);
|
|
31766
|
+
}
|
|
31767
|
+
/**
|
|
31768
|
+
* Starts persisting the model's edits to local storage, keeping the subscription in {@link diagramStorageSubscription}.
|
|
31769
|
+
*/
|
|
31770
|
+
function subscribeToDiagramChange(model) {
|
|
31771
|
+
diagramStorageSubscription === null || diagramStorageSubscription === void 0 ? void 0 : diagramStorageSubscription();
|
|
31772
|
+
diagramStorageSubscription = diagramService.subscribeToDiagramChange(model, (diagram) => diagramStorageService.save(diagram));
|
|
31773
|
+
subscriptions.add(diagramStorageSubscription);
|
|
31762
31774
|
}
|
|
31763
31775
|
/**
|
|
31764
31776
|
* Subscribes to the host's "clear persisted diagram" command so the saved layout is dropped on
|
|
31765
31777
|
* request (e.g. before a fresh seed should take precedence over previously saved edits). The
|
|
31766
31778
|
* subscription is tracked in {@link subscriptions} so it is released together with the React
|
|
31767
31779
|
* root in {@link unmountReactodia}.
|
|
31780
|
+
*
|
|
31781
|
+
* @param model The diagram model whose edits are persisted
|
|
31768
31782
|
*/
|
|
31769
|
-
function onClearDiagramStorage() {
|
|
31770
|
-
|
|
31771
|
-
|
|
31772
|
-
|
|
31783
|
+
function onClearDiagramStorage(model) {
|
|
31784
|
+
subscriptions.add(eventService.subscribeToClearDiagramStorage(() => {
|
|
31785
|
+
// re-subscribe, to avoid any pending debounced saves, which may write over the cleared diagram
|
|
31786
|
+
subscribeToDiagramChange(model);
|
|
31787
|
+
diagramStorageService.clear();
|
|
31788
|
+
}));
|
|
31773
31789
|
}
|
|
31774
31790
|
/**
|
|
31775
31791
|
* The Reactodia workspace React component.
|
|
@@ -31788,11 +31804,10 @@ function ReactodiaApp(props) {
|
|
|
31788
31804
|
workspaceContext = context;
|
|
31789
31805
|
const { model } = context;
|
|
31790
31806
|
onDiagramChange(model);
|
|
31791
|
-
onClearDiagramStorage();
|
|
31807
|
+
onClearDiagramStorage(model);
|
|
31792
31808
|
const dataProvider = createDataProvider(props);
|
|
31793
31809
|
const isReload = props.isReload;
|
|
31794
|
-
const savedDiagram =
|
|
31795
|
-
const diagramService = service(DiagramService);
|
|
31810
|
+
const savedDiagram = diagramStorageService.load();
|
|
31796
31811
|
if (isReload) {
|
|
31797
31812
|
// Reload the diagram that is currently on the canvas. This may happen when the host changes the provider
|
|
31798
31813
|
// settings, or when the user switches the language at runtime, since there is no existing mechanism to
|
|
@@ -31828,6 +31843,7 @@ function ReactodiaApp(props) {
|
|
|
31828
31843
|
translations: translationsForLanguage(language),
|
|
31829
31844
|
typeStyleResolver: resolveTypeStyle
|
|
31830
31845
|
}, reactExports.createElement(DefaultWorkspace, {
|
|
31846
|
+
colorScheme: props.theme,
|
|
31831
31847
|
menu: reactExports.createElement(GraphwiseMenu),
|
|
31832
31848
|
// place Undo/redo/layout actions in top right corner.
|
|
31833
31849
|
actionsToolbar: { dock: 'ne' }
|
|
@@ -31869,7 +31885,7 @@ function unmountReactodia(root) {
|
|
|
31869
31885
|
root.unmount();
|
|
31870
31886
|
}
|
|
31871
31887
|
|
|
31872
|
-
const graphwiseReactodiaCss = "graphwise-reactodia{display:block;width:100%;height:
|
|
31888
|
+
const graphwiseReactodiaCss = "graphwise-reactodia{--_graphwise-reactodia-type-color-01:var(--graphwise-reactodia-type-color-01);--_graphwise-reactodia-type-color-02:var(--graphwise-reactodia-type-color-02);--_graphwise-reactodia-type-color-03:var(--graphwise-reactodia-type-color-03);--_graphwise-reactodia-type-color-04:var(--graphwise-reactodia-type-color-04);--_graphwise-reactodia-type-color-05:var(--graphwise-reactodia-type-color-05);--_graphwise-reactodia-type-color-06:var(--graphwise-reactodia-type-color-06);--_graphwise-reactodia-type-color-07:var(--graphwise-reactodia-type-color-07);--_graphwise-reactodia-type-color-08:var(--graphwise-reactodia-type-color-08);--_graphwise-reactodia-type-color-09:var(--graphwise-reactodia-type-color-09);--_graphwise-reactodia-type-color-10:var(--graphwise-reactodia-type-color-10);--_graphwise-reactodia-type-color-11:var(--graphwise-reactodia-type-color-11);--_graphwise-reactodia-type-color-12:var(--graphwise-reactodia-type-color-12);--_graphwise-reactodia-type-color-13:var(--graphwise-reactodia-type-color-13);--_graphwise-reactodia-type-color-14:var(--graphwise-reactodia-type-color-14);--_graphwise-reactodia-type-color-15:var(--graphwise-reactodia-type-color-15);--_graphwise-reactodia-type-color-16:var(--graphwise-reactodia-type-color-16);--_graphwise-reactodia-type-color-17:var(--graphwise-reactodia-type-color-17);--_graphwise-reactodia-type-color-18:var(--graphwise-reactodia-type-color-18);--_graphwise-reactodia-type-color-19:var(--graphwise-reactodia-type-color-19);--_graphwise-reactodia-type-color-20:var(--graphwise-reactodia-type-color-20)}graphwise-reactodia{display:block;width:100%;height:100%}graphwise-reactodia .reactodia-container{position:relative;width:100%;height:100%}graphwise-reactodia .reactodia-selection-action__link{display:none}";
|
|
31873
31889
|
|
|
31874
31890
|
const GraphwiseReactodia = class {
|
|
31875
31891
|
constructor(hostRef) {
|
|
@@ -31878,6 +31894,14 @@ const GraphwiseReactodia = class {
|
|
|
31878
31894
|
* UI language code (e.g. `en`, `fr`) for the Reactodia interface. Defaults to English.
|
|
31879
31895
|
*/
|
|
31880
31896
|
this.language = LanguageKey.EN;
|
|
31897
|
+
/**
|
|
31898
|
+
* `connectedCallback` and the watchers can run before all props are set: when the component's
|
|
31899
|
+
* code is already loaded, the instance is created as soon as the
|
|
31900
|
+
* element is attached, and every prop set after that triggers its watcher. Rendering at that
|
|
31901
|
+
* point would initialise the graph without all props. `componentDidLoad` runs once the initial
|
|
31902
|
+
* props are set, so we use it to determine when it's safe to render.
|
|
31903
|
+
*/
|
|
31904
|
+
this.isComponentLoaded = false;
|
|
31881
31905
|
}
|
|
31882
31906
|
onCurrentRepositoryChange() {
|
|
31883
31907
|
this.renderGraph();
|
|
@@ -31893,9 +31917,11 @@ const GraphwiseReactodia = class {
|
|
|
31893
31917
|
this.renderGraph(true);
|
|
31894
31918
|
}
|
|
31895
31919
|
connectedCallback() {
|
|
31896
|
-
|
|
31897
|
-
|
|
31898
|
-
|
|
31920
|
+
this.renderGraph();
|
|
31921
|
+
}
|
|
31922
|
+
componentDidLoad() {
|
|
31923
|
+
this.isComponentLoaded = true;
|
|
31924
|
+
this.renderGraph();
|
|
31899
31925
|
}
|
|
31900
31926
|
disconnectedCallback() {
|
|
31901
31927
|
if (this.reactRoot) {
|
|
@@ -31904,10 +31930,13 @@ const GraphwiseReactodia = class {
|
|
|
31904
31930
|
}
|
|
31905
31931
|
}
|
|
31906
31932
|
render() {
|
|
31907
|
-
return (index$1.h(index$1.Host, { key: '
|
|
31933
|
+
return (index$1.h(index$1.Host, { key: 'a03aad892cb1947ab2426d77b3229e1324776c2c' }));
|
|
31908
31934
|
}
|
|
31909
31935
|
renderGraph(isReloading) {
|
|
31910
31936
|
var _a;
|
|
31937
|
+
if (!this.isComponentLoaded) {
|
|
31938
|
+
return;
|
|
31939
|
+
}
|
|
31911
31940
|
if (!this.currentRepository) {
|
|
31912
31941
|
throw new Error('currentRepository is required');
|
|
31913
31942
|
}
|
|
@@ -31926,6 +31955,7 @@ const GraphwiseReactodia = class {
|
|
|
31926
31955
|
config: this.config,
|
|
31927
31956
|
language: this.language,
|
|
31928
31957
|
providerSettings: this.providerSettings,
|
|
31958
|
+
theme: this.theme,
|
|
31929
31959
|
};
|
|
31930
31960
|
if (this.reactRoot && !isReloading) {
|
|
31931
31961
|
void updateReactodia(props);
|
|
@@ -1,7 +1,50 @@
|
|
|
1
|
+
graphwise-reactodia {
|
|
2
|
+
/** @prop --graphwise-reactodia-type-color-01: Color slot 1 of 20 for node types */
|
|
3
|
+
--_graphwise-reactodia-type-color-01: var(--graphwise-reactodia-type-color-01);
|
|
4
|
+
/** @prop --graphwise-reactodia-type-color-02: Color slot 2 of 20 for node types */
|
|
5
|
+
--_graphwise-reactodia-type-color-02: var(--graphwise-reactodia-type-color-02);
|
|
6
|
+
/** @prop --graphwise-reactodia-type-color-03: Color slot 3 of 20 for node types */
|
|
7
|
+
--_graphwise-reactodia-type-color-03: var(--graphwise-reactodia-type-color-03);
|
|
8
|
+
/** @prop --graphwise-reactodia-type-color-04: Color slot 4 of 20 for node types */
|
|
9
|
+
--_graphwise-reactodia-type-color-04: var(--graphwise-reactodia-type-color-04);
|
|
10
|
+
/** @prop --graphwise-reactodia-type-color-05: Color slot 5 of 20 for node types */
|
|
11
|
+
--_graphwise-reactodia-type-color-05: var(--graphwise-reactodia-type-color-05);
|
|
12
|
+
/** @prop --graphwise-reactodia-type-color-06: Color slot 6 of 20 for node types */
|
|
13
|
+
--_graphwise-reactodia-type-color-06: var(--graphwise-reactodia-type-color-06);
|
|
14
|
+
/** @prop --graphwise-reactodia-type-color-07: Color slot 7 of 20 for node types */
|
|
15
|
+
--_graphwise-reactodia-type-color-07: var(--graphwise-reactodia-type-color-07);
|
|
16
|
+
/** @prop --graphwise-reactodia-type-color-08: Color slot 8 of 20 for node types */
|
|
17
|
+
--_graphwise-reactodia-type-color-08: var(--graphwise-reactodia-type-color-08);
|
|
18
|
+
/** @prop --graphwise-reactodia-type-color-09: Color slot 9 of 20 for node types */
|
|
19
|
+
--_graphwise-reactodia-type-color-09: var(--graphwise-reactodia-type-color-09);
|
|
20
|
+
/** @prop --graphwise-reactodia-type-color-10: Color slot 10 of 20 for node types */
|
|
21
|
+
--_graphwise-reactodia-type-color-10: var(--graphwise-reactodia-type-color-10);
|
|
22
|
+
/** @prop --graphwise-reactodia-type-color-11: Color slot 11 of 20 for node types */
|
|
23
|
+
--_graphwise-reactodia-type-color-11: var(--graphwise-reactodia-type-color-11);
|
|
24
|
+
/** @prop --graphwise-reactodia-type-color-12: Color slot 12 of 20 for node types */
|
|
25
|
+
--_graphwise-reactodia-type-color-12: var(--graphwise-reactodia-type-color-12);
|
|
26
|
+
/** @prop --graphwise-reactodia-type-color-13: Color slot 13 of 20 for node types */
|
|
27
|
+
--_graphwise-reactodia-type-color-13: var(--graphwise-reactodia-type-color-13);
|
|
28
|
+
/** @prop --graphwise-reactodia-type-color-14: Color slot 14 of 20 for node types */
|
|
29
|
+
--_graphwise-reactodia-type-color-14: var(--graphwise-reactodia-type-color-14);
|
|
30
|
+
/** @prop --graphwise-reactodia-type-color-15: Color slot 15 of 20 for node types */
|
|
31
|
+
--_graphwise-reactodia-type-color-15: var(--graphwise-reactodia-type-color-15);
|
|
32
|
+
/** @prop --graphwise-reactodia-type-color-16: Color slot 16 of 20 for node types */
|
|
33
|
+
--_graphwise-reactodia-type-color-16: var(--graphwise-reactodia-type-color-16);
|
|
34
|
+
/** @prop --graphwise-reactodia-type-color-17: Color slot 17 of 20 for node types */
|
|
35
|
+
--_graphwise-reactodia-type-color-17: var(--graphwise-reactodia-type-color-17);
|
|
36
|
+
/** @prop --graphwise-reactodia-type-color-18: Color slot 18 of 20 for node types */
|
|
37
|
+
--_graphwise-reactodia-type-color-18: var(--graphwise-reactodia-type-color-18);
|
|
38
|
+
/** @prop --graphwise-reactodia-type-color-19: Color slot 19 of 20 for node types */
|
|
39
|
+
--_graphwise-reactodia-type-color-19: var(--graphwise-reactodia-type-color-19);
|
|
40
|
+
/** @prop --graphwise-reactodia-type-color-20: Color slot 20 of 20 for node types */
|
|
41
|
+
--_graphwise-reactodia-type-color-20: var(--graphwise-reactodia-type-color-20);
|
|
42
|
+
}
|
|
43
|
+
|
|
1
44
|
graphwise-reactodia {
|
|
2
45
|
display: block;
|
|
3
46
|
width: 100%;
|
|
4
|
-
height:
|
|
47
|
+
height: 100%;
|
|
5
48
|
}
|
|
6
49
|
graphwise-reactodia .reactodia-container {
|
|
7
50
|
position: relative;
|
|
@@ -19,6 +19,14 @@ export class GraphwiseReactodia {
|
|
|
19
19
|
* UI language code (e.g. `en`, `fr`) for the Reactodia interface. Defaults to English.
|
|
20
20
|
*/
|
|
21
21
|
this.language = LanguageKey.EN;
|
|
22
|
+
/**
|
|
23
|
+
* `connectedCallback` and the watchers can run before all props are set: when the component's
|
|
24
|
+
* code is already loaded, the instance is created as soon as the
|
|
25
|
+
* element is attached, and every prop set after that triggers its watcher. Rendering at that
|
|
26
|
+
* point would initialise the graph without all props. `componentDidLoad` runs once the initial
|
|
27
|
+
* props are set, so we use it to determine when it's safe to render.
|
|
28
|
+
*/
|
|
29
|
+
this.isComponentLoaded = false;
|
|
22
30
|
}
|
|
23
31
|
onCurrentRepositoryChange() {
|
|
24
32
|
this.renderGraph();
|
|
@@ -34,9 +42,11 @@ export class GraphwiseReactodia {
|
|
|
34
42
|
this.renderGraph(true);
|
|
35
43
|
}
|
|
36
44
|
connectedCallback() {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
this.renderGraph();
|
|
46
|
+
}
|
|
47
|
+
componentDidLoad() {
|
|
48
|
+
this.isComponentLoaded = true;
|
|
49
|
+
this.renderGraph();
|
|
40
50
|
}
|
|
41
51
|
disconnectedCallback() {
|
|
42
52
|
if (this.reactRoot) {
|
|
@@ -45,10 +55,13 @@ export class GraphwiseReactodia {
|
|
|
45
55
|
}
|
|
46
56
|
}
|
|
47
57
|
render() {
|
|
48
|
-
return (h(Host, { key: '
|
|
58
|
+
return (h(Host, { key: 'a03aad892cb1947ab2426d77b3229e1324776c2c' }));
|
|
49
59
|
}
|
|
50
60
|
renderGraph(isReloading) {
|
|
51
61
|
var _a;
|
|
62
|
+
if (!this.isComponentLoaded) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
52
65
|
if (!this.currentRepository) {
|
|
53
66
|
throw new Error('currentRepository is required');
|
|
54
67
|
}
|
|
@@ -67,6 +80,7 @@ export class GraphwiseReactodia {
|
|
|
67
80
|
config: this.config,
|
|
68
81
|
language: this.language,
|
|
69
82
|
providerSettings: this.providerSettings,
|
|
83
|
+
theme: this.theme,
|
|
70
84
|
};
|
|
71
85
|
if (this.reactRoot && !isReloading) {
|
|
72
86
|
void updateReactodia(props);
|
|
@@ -186,15 +200,15 @@ export class GraphwiseReactodia {
|
|
|
186
200
|
"attribute": "theme",
|
|
187
201
|
"mutable": false,
|
|
188
202
|
"complexType": {
|
|
189
|
-
"original": "
|
|
190
|
-
"resolved": "
|
|
203
|
+
"original": "'light' | 'dark'",
|
|
204
|
+
"resolved": "\"dark\" | \"light\"",
|
|
191
205
|
"references": {}
|
|
192
206
|
},
|
|
193
207
|
"required": false,
|
|
194
208
|
"optional": true,
|
|
195
209
|
"docs": {
|
|
196
210
|
"tags": [],
|
|
197
|
-
"text": "The
|
|
211
|
+
"text": "The reactodia theme to use"
|
|
198
212
|
},
|
|
199
213
|
"getter": false,
|
|
200
214
|
"setter": false,
|
|
@@ -33,6 +33,10 @@ let workspaceContext = null;
|
|
|
33
33
|
* the React root.
|
|
34
34
|
*/
|
|
35
35
|
const subscriptions = new SubscriptionList();
|
|
36
|
+
let diagramStorageSubscription;
|
|
37
|
+
const diagramService = service(DiagramService);
|
|
38
|
+
const diagramStorageService = service(DiagramStorageService);
|
|
39
|
+
const eventService = service(EventService);
|
|
36
40
|
/**
|
|
37
41
|
* Builds a Reactodia {@link SparqlDataProvider} for the given endpoint using the supplied
|
|
38
42
|
* query preset. The host owns the query configuration and always passes it in via props.
|
|
@@ -92,20 +96,30 @@ async function seedGraphToCanvas(context, dataProvider, links, signal) {
|
|
|
92
96
|
* root in {@link unmountReactodia}.
|
|
93
97
|
*/
|
|
94
98
|
function onDiagramChange(model) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
99
|
+
subscribeToDiagramChange(model);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Starts persisting the model's edits to local storage, keeping the subscription in {@link diagramStorageSubscription}.
|
|
103
|
+
*/
|
|
104
|
+
function subscribeToDiagramChange(model) {
|
|
105
|
+
diagramStorageSubscription === null || diagramStorageSubscription === void 0 ? void 0 : diagramStorageSubscription();
|
|
106
|
+
diagramStorageSubscription = diagramService.subscribeToDiagramChange(model, (diagram) => diagramStorageService.save(diagram));
|
|
107
|
+
subscriptions.add(diagramStorageSubscription);
|
|
98
108
|
}
|
|
99
109
|
/**
|
|
100
110
|
* Subscribes to the host's "clear persisted diagram" command so the saved layout is dropped on
|
|
101
111
|
* request (e.g. before a fresh seed should take precedence over previously saved edits). The
|
|
102
112
|
* subscription is tracked in {@link subscriptions} so it is released together with the React
|
|
103
113
|
* root in {@link unmountReactodia}.
|
|
114
|
+
*
|
|
115
|
+
* @param model The diagram model whose edits are persisted
|
|
104
116
|
*/
|
|
105
|
-
function onClearDiagramStorage() {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
117
|
+
function onClearDiagramStorage(model) {
|
|
118
|
+
subscriptions.add(eventService.subscribeToClearDiagramStorage(() => {
|
|
119
|
+
// re-subscribe, to avoid any pending debounced saves, which may write over the cleared diagram
|
|
120
|
+
subscribeToDiagramChange(model);
|
|
121
|
+
diagramStorageService.clear();
|
|
122
|
+
}));
|
|
109
123
|
}
|
|
110
124
|
/**
|
|
111
125
|
* The Reactodia workspace React component.
|
|
@@ -124,11 +138,10 @@ function ReactodiaApp(props) {
|
|
|
124
138
|
workspaceContext = context;
|
|
125
139
|
const { model } = context;
|
|
126
140
|
onDiagramChange(model);
|
|
127
|
-
onClearDiagramStorage();
|
|
141
|
+
onClearDiagramStorage(model);
|
|
128
142
|
const dataProvider = createDataProvider(props);
|
|
129
143
|
const isReload = props.isReload;
|
|
130
|
-
const savedDiagram =
|
|
131
|
-
const diagramService = service(DiagramService);
|
|
144
|
+
const savedDiagram = diagramStorageService.load();
|
|
132
145
|
if (isReload) {
|
|
133
146
|
// Reload the diagram that is currently on the canvas. This may happen when the host changes the provider
|
|
134
147
|
// settings, or when the user switches the language at runtime, since there is no existing mechanism to
|
|
@@ -164,6 +177,7 @@ function ReactodiaApp(props) {
|
|
|
164
177
|
translations: translationsForLanguage(language),
|
|
165
178
|
typeStyleResolver: resolveTypeStyle
|
|
166
179
|
}, createElement(DefaultWorkspace, {
|
|
180
|
+
colorScheme: props.theme,
|
|
167
181
|
menu: createElement(GraphwiseMenu),
|
|
168
182
|
// place Undo/redo/layout actions in top right corner.
|
|
169
183
|
actionsToolbar: { dock: 'ne' }
|
|
@@ -46,8 +46,10 @@ let DiagramService = DiagramService_1 = class DiagramService {
|
|
|
46
46
|
clearTimeout(notifyTimer);
|
|
47
47
|
}
|
|
48
48
|
notifyTimer = setTimeout(() => {
|
|
49
|
+
if (notifyTimer) {
|
|
50
|
+
onChangeCallback(model.exportLayout());
|
|
51
|
+
}
|
|
49
52
|
notifyTimer = undefined;
|
|
50
|
-
onChangeCallback(model.exportLayout());
|
|
51
53
|
}, DiagramService_1.NOTIFY_DEBOUNCE_MS);
|
|
52
54
|
};
|
|
53
55
|
model.history.events.on(DiagramService_1.HISTORY_CHANGED_EVENT, onHistoryChange);
|
|
@@ -55,6 +57,7 @@ let DiagramService = DiagramService_1 = class DiagramService {
|
|
|
55
57
|
model.history.events.off(DiagramService_1.HISTORY_CHANGED_EVENT, onHistoryChange);
|
|
56
58
|
if (notifyTimer) {
|
|
57
59
|
clearTimeout(notifyTimer);
|
|
60
|
+
notifyTimer = undefined;
|
|
58
61
|
}
|
|
59
62
|
};
|
|
60
63
|
}
|
|
@@ -1,31 +1,30 @@
|
|
|
1
|
-
const NODE_COLOR_VARIABLES = [
|
|
2
|
-
'--gw-foreground-visual-diagram-categorical-01',
|
|
3
|
-
'--gw-foreground-visual-diagram-categorical-02',
|
|
4
|
-
'--gw-foreground-visual-diagram-categorical-03',
|
|
5
|
-
'--gw-foreground-visual-diagram-categorical-04',
|
|
6
|
-
'--gw-foreground-visual-diagram-categorical-05',
|
|
7
|
-
'--gw-foreground-visual-diagram-categorical-06',
|
|
8
|
-
'--gw-foreground-visual-diagram-categorical-07',
|
|
9
|
-
'--gw-foreground-visual-diagram-categorical-08',
|
|
10
|
-
'--gw-foreground-visual-diagram-categorical-09',
|
|
11
|
-
'--gw-foreground-visual-diagram-categorical-10',
|
|
12
|
-
'--gw-foreground-visual-diagram-categorical-11',
|
|
13
|
-
'--gw-foreground-visual-diagram-categorical-12',
|
|
14
|
-
'--gw-foreground-visual-diagram-categorical-13',
|
|
15
|
-
'--gw-foreground-visual-diagram-categorical-14',
|
|
16
|
-
'--gw-foreground-visual-diagram-categorical-15',
|
|
17
|
-
'--gw-foreground-visual-diagram-categorical-16',
|
|
18
|
-
'--gw-foreground-visual-diagram-categorical-17',
|
|
19
|
-
'--gw-foreground-visual-diagram-categorical-18',
|
|
20
|
-
'--gw-foreground-visual-diagram-categorical-19',
|
|
21
|
-
'--gw-foreground-visual-diagram-categorical-20'
|
|
22
|
-
];
|
|
23
1
|
/**
|
|
24
2
|
* Color slot assigned to each type, in the order the types are first seen.
|
|
25
3
|
*/
|
|
26
4
|
const typeToIndex = new Map();
|
|
27
|
-
|
|
28
|
-
|
|
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;
|
|
29
28
|
}
|
|
30
29
|
/**
|
|
31
30
|
* Colors an element by its type: each type takes the next color from the palette, which wraps
|
|
@@ -45,8 +44,8 @@ export const resolveTypeStyle = (types) => {
|
|
|
45
44
|
index = typeToIndex.size;
|
|
46
45
|
typeToIndex.set(type, index);
|
|
47
46
|
}
|
|
48
|
-
const
|
|
49
|
-
return
|
|
47
|
+
const colors = getPalette();
|
|
48
|
+
return colors.length ? { color: colors[index % colors.length] } : undefined;
|
|
50
49
|
};
|
|
51
50
|
export const resetColors = () => {
|
|
52
51
|
typeToIndex.clear();
|
|
@@ -2,7 +2,13 @@
|
|
|
2
2
|
// result. The shape has to match what the provider asks for: SELECT/ASK queries are parsed with
|
|
3
3
|
// `response.json()` and would blow up on an empty body, CONSTRUCT/DESCRIBE queries are parsed as
|
|
4
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
|
+
|
|
5
10
|
async function stubQueryFunction(params) {
|
|
11
|
+
sparqlQueries.push(params.body);
|
|
6
12
|
const accept = params.headers?.['Accept'] ?? '';
|
|
7
13
|
if (accept.includes('sparql-results+json')) {
|
|
8
14
|
const body = JSON.stringify({head: {vars: []}, results: {bindings: []}, boolean: false});
|
|
@@ -33,6 +39,34 @@ function setProviderSettings() {
|
|
|
33
39
|
reactodia.providerSettings = OWL_RDFS_SETTINGS;
|
|
34
40
|
}
|
|
35
41
|
|
|
42
|
+
// A runtime change goes through the `providerSettings` prop. The extra prefix marks the queries built
|
|
43
|
+
// with the changed settings.
|
|
44
|
+
function changeProviderSettings() {
|
|
45
|
+
reactodia.providerSettings = {
|
|
46
|
+
...OWL_RDFS_SETTINGS,
|
|
47
|
+
defaultPrefix: `${OWL_RDFS_SETTINGS.defaultPrefix}\nPREFIX changed: <http://example.com/changed#>\n`,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Replaces the element with a new one the way a framework such as Angular renders it: attached first, then
|
|
52
|
+
// the props set one by one. The component code is already loaded by then, so the component is initialized
|
|
53
|
+
// before it has any of its props.
|
|
54
|
+
function attachThenSetProps(order) {
|
|
55
|
+
const props = {
|
|
56
|
+
config: {queryFunction: stubQueryFunction, seedIris: SEED_NODES},
|
|
57
|
+
currentRepository: 'repo-a',
|
|
58
|
+
providerSettings: OWL_RDFS_SETTINGS,
|
|
59
|
+
language: 'fr',
|
|
60
|
+
theme: 'light',
|
|
61
|
+
};
|
|
62
|
+
const element = document.createElement('graphwise-reactodia');
|
|
63
|
+
element.dataset.test = 'reactodia';
|
|
64
|
+
document.querySelector('graphwise-reactodia').replaceWith(element);
|
|
65
|
+
order.forEach((prop) => {
|
|
66
|
+
element[prop] = props[prop];
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
36
70
|
function setSeed() {
|
|
37
71
|
reactodia.config = {...reactodia.config, seedIris: SEED_NODES};
|
|
38
72
|
}
|
|
@@ -49,6 +83,10 @@ function setLanguage(language) {
|
|
|
49
83
|
reactodia.language = language;
|
|
50
84
|
}
|
|
51
85
|
|
|
86
|
+
function setTheme(theme) {
|
|
87
|
+
reactodia.theme = theme;
|
|
88
|
+
}
|
|
89
|
+
|
|
52
90
|
// The host asks the component to drop its persisted diagram by dispatching a namespaced window
|
|
53
91
|
// event, rather than holding an element reference and calling a method on it.
|
|
54
92
|
function clearDiagramStorage() {
|