graphwise-reactodia 0.0.1-TR6 → 0.0.1-TR8
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 +32 -0
- package/dist/cjs/graphwise-reactodia.cjs.entry.js +281 -27
- package/dist/cjs/index.cjs.js +7 -0
- package/dist/collection/components/graphwise-reactodia/graphwise-reactodia.js +11 -11
- package/dist/collection/components/graphwise-reactodia/models/clear-diagram-storage-event.js +5 -0
- package/dist/collection/components/graphwise-reactodia/models/subscription-list.js +35 -0
- package/dist/collection/components/graphwise-reactodia/models/subscription.js +1 -0
- package/dist/collection/components/graphwise-reactodia/models/triple.js +1 -0
- package/dist/collection/components/graphwise-reactodia/providers/service/service-inject.js +15 -0
- package/dist/collection/components/graphwise-reactodia/providers/service/service.js +1 -0
- package/dist/collection/components/graphwise-reactodia/providers/service/service.provider.js +20 -0
- package/dist/collection/components/graphwise-reactodia/reactodia-app.js +85 -13
- package/dist/collection/components/graphwise-reactodia/services/diagram/diagram.service.js +39 -0
- package/dist/collection/components/graphwise-reactodia/services/diagram-storage/diagram-storage.service.js +42 -0
- package/dist/collection/components/graphwise-reactodia/services/event/event.service.js +22 -0
- package/dist/collection/components/graphwise-reactodia/services/window/window.service.js +8 -0
- package/dist/collection/components/graphwise-reactodia/testing/storage.mock.js +35 -0
- package/dist/collection/index.js +1 -1
- package/dist/collection/pages/graphwise-reactodia/main.js +29 -4
- package/dist/esm/graphwise-reactodia.entry.js +278 -24
- package/dist/esm/index.js +6 -0
- package/dist/graphwise-reactodia/graphwise-reactodia.esm.js +1 -1
- package/dist/graphwise-reactodia/index.esm.js +1 -0
- package/dist/graphwise-reactodia/p-80cb6eef.entry.js +1 -0
- package/dist/types/components/graphwise-reactodia/graphwise-reactodia.d.ts +1 -1
- package/dist/types/components/graphwise-reactodia/i18n/translations.d.ts +2 -6
- package/dist/types/components/graphwise-reactodia/models/clear-diagram-storage-event.d.ts +5 -0
- package/dist/types/components/graphwise-reactodia/models/reactodia-app-props.d.ts +6 -7
- package/dist/types/components/graphwise-reactodia/models/reactodia-config.d.ts +10 -2
- package/dist/types/components/graphwise-reactodia/models/subscription-list.d.ts +26 -0
- package/dist/types/components/graphwise-reactodia/models/subscription.d.ts +4 -0
- package/dist/types/components/graphwise-reactodia/models/triple.d.ts +19 -0
- package/dist/types/components/graphwise-reactodia/providers/service/service-inject.d.ts +13 -0
- package/dist/types/components/graphwise-reactodia/providers/service/service.d.ts +6 -0
- package/dist/types/components/graphwise-reactodia/providers/service/service.provider.d.ts +18 -0
- package/dist/types/components/graphwise-reactodia/services/diagram/diagram.service.d.ts +28 -0
- package/dist/types/components/graphwise-reactodia/services/diagram-storage/diagram-storage.service.d.ts +26 -0
- package/dist/types/components/graphwise-reactodia/services/event/event.service.d.ts +14 -0
- package/dist/types/components/graphwise-reactodia/services/window/window.service.d.ts +7 -0
- package/dist/types/components/graphwise-reactodia/testing/storage.mock.d.ts +18 -0
- package/dist/types/index.d.ts +1 -1
- package/package.json +9 -3
- package/dist/graphwise-reactodia/p-5a330bae.entry.js +0 -1
package/README.md
CHANGED
|
@@ -34,6 +34,38 @@ npm run build
|
|
|
34
34
|
(`reactodia:install` + `reactodia:compile`), then runs `reactodia:dedupe-react` to remove the fork's own
|
|
35
35
|
`react`/`react-dom` copies so the bundle ends up with a single React instance.
|
|
36
36
|
|
|
37
|
+
## Seeding the canvas
|
|
38
|
+
|
|
39
|
+
By default the canvas starts empty and the user populates it through the workspace search bar. The host can
|
|
40
|
+
instead pre-populate it on startup by passing seed data through `config` (see `ReactodiaAppProps`). Seeding is
|
|
41
|
+
skipped when an `initialDiagram` is restored (e.g. after a language-change remount). There are two mechanisms,
|
|
42
|
+
handled in `reactodia-app.ts`:
|
|
43
|
+
|
|
44
|
+
### `seedIris` — lazy seed
|
|
45
|
+
|
|
46
|
+
`config.seedIris` is a list of element(node) IRIs. Each IRI is placed as a placeholder node, then `seedCanvas` calls
|
|
47
|
+
the model's `requestData()` so both the element data **and** its links are fetched from the SPARQL endpoint.
|
|
48
|
+
Use this when the relationships are persisted in the repository and can be resolved lazily.
|
|
49
|
+
|
|
50
|
+
### `seedGraph` — pre-resolved seed
|
|
51
|
+
|
|
52
|
+
`config.seedGraph` is a list of `Triple` objects (mirroring GraphDB's `rest/explore-graph` shape).
|
|
53
|
+
`seedGraphCanvas` places each `source`/`target` as an element and draws the supplied links directly, then
|
|
54
|
+
requests **element data only** (`requestElementData`) — it does *not* ask the endpoint for links.
|
|
55
|
+
|
|
56
|
+
Use this for the result of a CONSTRUCT/DESCRIBE query, whose relationships are computed and therefore not
|
|
57
|
+
persisted in the DB, so they can't be fetched lazily and must be supplied by the host.
|
|
58
|
+
|
|
59
|
+
`Triple` (`models/triple.ts`):
|
|
60
|
+
|
|
61
|
+
| Field | Description |
|
|
62
|
+
|-----------------|----------------------------------------------------------|
|
|
63
|
+
| `source` | Source element IRI. |
|
|
64
|
+
| `target` | Target element IRI. |
|
|
65
|
+
| `rawPredicates` | Full (absolute) predicate IRIs — used as the link types. |
|
|
66
|
+
|
|
67
|
+
When both are supplied `seedGraph` takes precedence over `seedIris`.
|
|
68
|
+
|
|
37
69
|
## Editing the fork
|
|
38
70
|
|
|
39
71
|
Reactodia lives in the `reactodia-workspace/` submodule, which is its own git repo (remote:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-CII9aUQC.js');
|
|
3
|
+
var index$1 = require('./index-CII9aUQC.js');
|
|
4
|
+
var index = require('./index.cjs.js');
|
|
4
5
|
|
|
5
6
|
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
6
7
|
|
|
@@ -18579,11 +18580,15 @@ function addWatermark(svg, viewBox, watermarkSvg) {
|
|
|
18579
18580
|
image.setAttribute("opacity", "0.3");
|
|
18580
18581
|
svg.insertBefore(image, svg.firstChild);
|
|
18581
18582
|
}
|
|
18583
|
+
function stripPseudoElements(selectorText) {
|
|
18584
|
+
if (!selectorText.includes("::")) return selectorText;
|
|
18585
|
+
return selectorText.split(",").map((selector) => selector.replace(/::[a-zA-Z-]+/g, "").trim()).filter(Boolean).join(", ");
|
|
18586
|
+
}
|
|
18582
18587
|
function collectAppliedCssFromDocument(targetSubtree) {
|
|
18583
18588
|
const appliedRules = [];
|
|
18584
18589
|
enumerateStylesheets((rule) => {
|
|
18585
|
-
const
|
|
18586
|
-
if (targetSubtree.querySelector(
|
|
18590
|
+
const selector = stripPseudoElements(rule.selectorText);
|
|
18591
|
+
if (selector && targetSubtree.querySelector(selector)) appliedRules.push(rule);
|
|
18587
18592
|
});
|
|
18588
18593
|
return appliedRules;
|
|
18589
18594
|
}
|
|
@@ -30642,6 +30647,188 @@ const TRANSLATIONS = {
|
|
|
30642
30647
|
[LanguageKey.FR]: frTranslation
|
|
30643
30648
|
};
|
|
30644
30649
|
|
|
30650
|
+
/**
|
|
30651
|
+
* Provider for all {@link Service} instances. Services are singletons: there is only one
|
|
30652
|
+
* instance of each service, created on demand and cached here so every consumer shares it.
|
|
30653
|
+
*/
|
|
30654
|
+
class ServiceProvider {
|
|
30655
|
+
/**
|
|
30656
|
+
* Returns the instance of the given service type, creating and caching it on first request.
|
|
30657
|
+
*
|
|
30658
|
+
* @param type The service type to retrieve.
|
|
30659
|
+
* @returns The shared instance of the service.
|
|
30660
|
+
* @template T The type of the service to retrieve.
|
|
30661
|
+
*/
|
|
30662
|
+
static get(type) {
|
|
30663
|
+
if (!ServiceProvider.SERVICE_INSTANCES.has(type.name)) {
|
|
30664
|
+
ServiceProvider.SERVICE_INSTANCES.set(type.name, new type());
|
|
30665
|
+
}
|
|
30666
|
+
return ServiceProvider.SERVICE_INSTANCES.get(type.name);
|
|
30667
|
+
}
|
|
30668
|
+
}
|
|
30669
|
+
ServiceProvider.SERVICE_INSTANCES = new Map();
|
|
30670
|
+
|
|
30671
|
+
/**
|
|
30672
|
+
* Injects the singleton instance of the given service class from the {@link ServiceProvider}.
|
|
30673
|
+
*
|
|
30674
|
+
* @param serviceClass The class of the service to inject.
|
|
30675
|
+
* @returns The shared instance of the specified service class.
|
|
30676
|
+
* @template T The type of the service to inject.
|
|
30677
|
+
* @example
|
|
30678
|
+
* ```typescript
|
|
30679
|
+
* const diagramStateService = service(DiagramStateService);
|
|
30680
|
+
* ```
|
|
30681
|
+
*/
|
|
30682
|
+
function service(serviceClass) {
|
|
30683
|
+
return ServiceProvider.get(serviceClass);
|
|
30684
|
+
}
|
|
30685
|
+
|
|
30686
|
+
/**
|
|
30687
|
+
* Service for diagram related operations and subscriptions
|
|
30688
|
+
*/
|
|
30689
|
+
class DiagramService {
|
|
30690
|
+
/**
|
|
30691
|
+
* Subscribes to diagram changes. On every debounced change the current layout is
|
|
30692
|
+
* exported and passed to the callback
|
|
30693
|
+
*
|
|
30694
|
+
* @param model The diagram model to observe.
|
|
30695
|
+
* @param onChangeCallback Called with the exported layout when the diagram changes.
|
|
30696
|
+
* @returns A {@link Subscription} that, when called, removes the listener and drops any
|
|
30697
|
+
* pending notification.
|
|
30698
|
+
*/
|
|
30699
|
+
subscribeToDiagramChange(model, onChangeCallback) {
|
|
30700
|
+
let notifyTimer;
|
|
30701
|
+
const onHistoryChange = () => {
|
|
30702
|
+
if (notifyTimer) {
|
|
30703
|
+
clearTimeout(notifyTimer);
|
|
30704
|
+
}
|
|
30705
|
+
notifyTimer = setTimeout(() => {
|
|
30706
|
+
notifyTimer = undefined;
|
|
30707
|
+
onChangeCallback(model.exportLayout());
|
|
30708
|
+
}, DiagramService.NOTIFY_DEBOUNCE_MS);
|
|
30709
|
+
};
|
|
30710
|
+
model.history.events.on(DiagramService.HISTORY_CHANGED_EVENT, onHistoryChange);
|
|
30711
|
+
return () => {
|
|
30712
|
+
model.history.events.off(DiagramService.HISTORY_CHANGED_EVENT, onHistoryChange);
|
|
30713
|
+
if (notifyTimer) {
|
|
30714
|
+
clearTimeout(notifyTimer);
|
|
30715
|
+
}
|
|
30716
|
+
};
|
|
30717
|
+
}
|
|
30718
|
+
}
|
|
30719
|
+
/**
|
|
30720
|
+
* Debounce time for the callback trigger. This is needed, because certain events (like moving a node) can trigger
|
|
30721
|
+
* multiple `historyChanged` events in a short time.
|
|
30722
|
+
*/
|
|
30723
|
+
DiagramService.NOTIFY_DEBOUNCE_MS = 300;
|
|
30724
|
+
DiagramService.HISTORY_CHANGED_EVENT = 'historyChanged';
|
|
30725
|
+
|
|
30726
|
+
/**
|
|
30727
|
+
* Service that provides access to browser window-related functionality.
|
|
30728
|
+
*/
|
|
30729
|
+
class WindowService {
|
|
30730
|
+
getWindow() {
|
|
30731
|
+
return window;
|
|
30732
|
+
}
|
|
30733
|
+
}
|
|
30734
|
+
|
|
30735
|
+
/**
|
|
30736
|
+
* Service for local store-related diagram operations
|
|
30737
|
+
*/
|
|
30738
|
+
class DiagramStorageService {
|
|
30739
|
+
/**
|
|
30740
|
+
* Load the persisted diagram from the local store, or `undefined` when nothing is stored (or the stored value
|
|
30741
|
+
* is unreadable).
|
|
30742
|
+
*/
|
|
30743
|
+
load() {
|
|
30744
|
+
var _a;
|
|
30745
|
+
const raw = (_a = this.storage) === null || _a === void 0 ? void 0 : _a.getItem(DiagramStorageService.STORAGE_KEY);
|
|
30746
|
+
if (!raw) {
|
|
30747
|
+
return undefined;
|
|
30748
|
+
}
|
|
30749
|
+
return JSON.parse(raw);
|
|
30750
|
+
}
|
|
30751
|
+
/**
|
|
30752
|
+
* Persists the given diagram serialization.
|
|
30753
|
+
*/
|
|
30754
|
+
save(diagram) {
|
|
30755
|
+
var _a;
|
|
30756
|
+
(_a = this.storage) === null || _a === void 0 ? void 0 : _a.setItem(DiagramStorageService.STORAGE_KEY, JSON.stringify(diagram));
|
|
30757
|
+
}
|
|
30758
|
+
/**
|
|
30759
|
+
* Removes the persisted diagram. Used when a new view (a seed) should take precedence over
|
|
30760
|
+
* previously saved edits.
|
|
30761
|
+
*/
|
|
30762
|
+
clear() {
|
|
30763
|
+
var _a;
|
|
30764
|
+
(_a = this.storage) === null || _a === void 0 ? void 0 : _a.removeItem(DiagramStorageService.STORAGE_KEY);
|
|
30765
|
+
}
|
|
30766
|
+
/**
|
|
30767
|
+
* Local storage getter
|
|
30768
|
+
*/
|
|
30769
|
+
get storage() {
|
|
30770
|
+
var _a;
|
|
30771
|
+
return (_a = service(WindowService).getWindow()) === null || _a === void 0 ? void 0 : _a.localStorage;
|
|
30772
|
+
}
|
|
30773
|
+
}
|
|
30774
|
+
DiagramStorageService.STORAGE_KEY = 'diagram.state';
|
|
30775
|
+
|
|
30776
|
+
/**
|
|
30777
|
+
* Service for event based operations
|
|
30778
|
+
*/
|
|
30779
|
+
class EventService {
|
|
30780
|
+
/**
|
|
30781
|
+
* Subscribes to the host's "clear persisted diagram" command.
|
|
30782
|
+
*
|
|
30783
|
+
* @param onClear Called whenever the event fires.
|
|
30784
|
+
* @returns A {@link Subscription} that, when called, removes the listener.
|
|
30785
|
+
*/
|
|
30786
|
+
subscribeToClearDiagramStorage(onClear) {
|
|
30787
|
+
const target = service(WindowService).getWindow();
|
|
30788
|
+
if (!target) {
|
|
30789
|
+
return () => undefined;
|
|
30790
|
+
}
|
|
30791
|
+
target.addEventListener(index.CLEAR_DIAGRAM_STORAGE_EVENT, onClear);
|
|
30792
|
+
return () => target.removeEventListener(index.CLEAR_DIAGRAM_STORAGE_EVENT, onClear);
|
|
30793
|
+
}
|
|
30794
|
+
}
|
|
30795
|
+
|
|
30796
|
+
/**
|
|
30797
|
+
* A collection of {@link Subscription}s that can be released together. Components collect the
|
|
30798
|
+
* subscriptions they open and call {@link unsubscribeAll} on teardown so nothing is left
|
|
30799
|
+
* listening.
|
|
30800
|
+
*/
|
|
30801
|
+
class SubscriptionList {
|
|
30802
|
+
constructor(subscriptions = []) {
|
|
30803
|
+
this.items = subscriptions;
|
|
30804
|
+
}
|
|
30805
|
+
/**
|
|
30806
|
+
* Adds a subscription to the list.
|
|
30807
|
+
*/
|
|
30808
|
+
add(subscription) {
|
|
30809
|
+
this.items.push(subscription);
|
|
30810
|
+
}
|
|
30811
|
+
/**
|
|
30812
|
+
* Adds multiple subscriptions to the list.
|
|
30813
|
+
*/
|
|
30814
|
+
addAll(subscriptions) {
|
|
30815
|
+
this.items.push(...subscriptions);
|
|
30816
|
+
}
|
|
30817
|
+
/**
|
|
30818
|
+
* Removes a subscription from the list without unsubscribing it.
|
|
30819
|
+
*/
|
|
30820
|
+
remove(subscription) {
|
|
30821
|
+
this.items = this.items.filter((sub) => sub !== subscription);
|
|
30822
|
+
}
|
|
30823
|
+
/**
|
|
30824
|
+
* Calls every subscription (unsubscribing it) and clears the list.
|
|
30825
|
+
*/
|
|
30826
|
+
unsubscribeAll() {
|
|
30827
|
+
this.items.forEach((subscription) => subscription());
|
|
30828
|
+
this.items = [];
|
|
30829
|
+
}
|
|
30830
|
+
}
|
|
30831
|
+
|
|
30645
30832
|
/**
|
|
30646
30833
|
* Reactodia ships English as its built-in default bundle, so English needs no override.
|
|
30647
30834
|
* Other languages are layered on top as partial bundles; unknown codes fall back to English.
|
|
@@ -30659,6 +30846,12 @@ function translationsForLanguage(language) {
|
|
|
30659
30846
|
* runs outside React and therefore cannot call the `useWorkspace` hook.
|
|
30660
30847
|
*/
|
|
30661
30848
|
let workspaceContext = null;
|
|
30849
|
+
/**
|
|
30850
|
+
* Active listeners that persist diagram edits to local storage. Populated when the workspace
|
|
30851
|
+
* mounts and released in {@link unmountReactodia}, so persistence follows the same lifecycle as
|
|
30852
|
+
* the React root.
|
|
30853
|
+
*/
|
|
30854
|
+
const subscriptions = new SubscriptionList();
|
|
30662
30855
|
/**
|
|
30663
30856
|
* Builds a Reactodia {@link SparqlDataProvider} for the given endpoint using the supplied
|
|
30664
30857
|
* query preset. The host owns the query configuration and passes it in via props; when none
|
|
@@ -30669,21 +30862,71 @@ function createDataProvider(props) {
|
|
|
30669
30862
|
return new SparqlDataProvider({
|
|
30670
30863
|
endpointUrl: currentRepository,
|
|
30671
30864
|
queryMethod: 'POST',
|
|
30672
|
-
queryFunction: config.queryFunction
|
|
30865
|
+
queryFunction: config.queryFunction
|
|
30673
30866
|
}, providerSettings);
|
|
30674
30867
|
}
|
|
30675
30868
|
/**
|
|
30676
30869
|
* Places the seed entities on the canvas. Each IRI is added as a placeholder element, and data is then loaded for the
|
|
30677
30870
|
* respective nodes using the {@link DataDiagramModel.requestData} method.
|
|
30678
30871
|
*/
|
|
30679
|
-
async function
|
|
30872
|
+
async function seedIrisToCanvas(context, dataProvider, seed, signal) {
|
|
30680
30873
|
const { model, performLayout } = context;
|
|
30874
|
+
await model.createNewDiagram({ dataProvider, signal });
|
|
30681
30875
|
for (const iri of seed) {
|
|
30682
30876
|
model.createElement(iri);
|
|
30683
30877
|
}
|
|
30684
30878
|
await model.requestData();
|
|
30685
30879
|
await performLayout({ signal });
|
|
30686
30880
|
}
|
|
30881
|
+
/**
|
|
30882
|
+
* Places a pre-resolved graph (e.g. a CONSTRUCT query result) on the canvas. The difference between this and
|
|
30883
|
+
* {@link seedIrisToCanvas} is that this method does not request link data from the SPARQL endpoint, since describe/construct
|
|
30884
|
+
* queries are not persisted in the DB. Here we expect provided links and query for element data only
|
|
30885
|
+
*/
|
|
30886
|
+
async function seedGraphToCanvas(context, dataProvider, links, signal) {
|
|
30887
|
+
const { model, performLayout } = context;
|
|
30888
|
+
await model.createNewDiagram({ dataProvider, signal });
|
|
30889
|
+
const uniqueIris = new Set();
|
|
30890
|
+
links.forEach((link) => {
|
|
30891
|
+
var _a;
|
|
30892
|
+
uniqueIris.add(link.source);
|
|
30893
|
+
uniqueIris.add(link.target);
|
|
30894
|
+
// this is a createOrGet, regardless of the name, so we don't need to worry about duplicates.
|
|
30895
|
+
model.createElement(link.source);
|
|
30896
|
+
model.createElement(link.target);
|
|
30897
|
+
(_a = link.rawPredicates) === null || _a === void 0 ? void 0 : _a.forEach((predicate) => {
|
|
30898
|
+
model.createLinks({
|
|
30899
|
+
linkTypeId: predicate,
|
|
30900
|
+
sourceId: link.source,
|
|
30901
|
+
targetId: link.target,
|
|
30902
|
+
properties: {}
|
|
30903
|
+
});
|
|
30904
|
+
});
|
|
30905
|
+
});
|
|
30906
|
+
await model.requestElementData(Array.from(uniqueIris));
|
|
30907
|
+
await performLayout({ signal });
|
|
30908
|
+
}
|
|
30909
|
+
/**
|
|
30910
|
+
* Subscribes to the model's changes so diagram edits are persisted to local storage. The
|
|
30911
|
+
* subscription is tracked in {@link subscriptions} so it is released together with the React
|
|
30912
|
+
* root in {@link unmountReactodia}.
|
|
30913
|
+
*/
|
|
30914
|
+
function onDiagramChange(model) {
|
|
30915
|
+
const storage = service(DiagramStorageService);
|
|
30916
|
+
const diagramService = service(DiagramService);
|
|
30917
|
+
subscriptions.add(diagramService.subscribeToDiagramChange(model, (diagram) => storage.save(diagram)));
|
|
30918
|
+
}
|
|
30919
|
+
/**
|
|
30920
|
+
* Subscribes to the host's "clear persisted diagram" command so the saved layout is dropped on
|
|
30921
|
+
* request (e.g. before a fresh seed should take precedence over previously saved edits). The
|
|
30922
|
+
* subscription is tracked in {@link subscriptions} so it is released together with the React
|
|
30923
|
+
* root in {@link unmountReactodia}.
|
|
30924
|
+
*/
|
|
30925
|
+
function onClearDiagramStorage() {
|
|
30926
|
+
const storage = service(DiagramStorageService);
|
|
30927
|
+
const eventService = service(EventService);
|
|
30928
|
+
subscriptions.add(eventService.subscribeToClearDiagramStorage(() => storage.clear()));
|
|
30929
|
+
}
|
|
30687
30930
|
/**
|
|
30688
30931
|
* The Reactodia workspace React component.
|
|
30689
30932
|
*
|
|
@@ -30694,22 +30937,32 @@ async function seedCanvas(context, seed, signal) {
|
|
|
30694
30937
|
* provider's lookup. With a seed, the seeded nodes are placed on the canvas on startup.
|
|
30695
30938
|
*/
|
|
30696
30939
|
function ReactodiaApp(props) {
|
|
30697
|
-
const { language,
|
|
30940
|
+
const { language, config } = props;
|
|
30941
|
+
const currentDiagram = props.isReload ? exportReactodiaLayout() : undefined;
|
|
30698
30942
|
const { onMount } = useLoadedWorkspace(async ({ context, signal }) => {
|
|
30943
|
+
var _a, _b;
|
|
30699
30944
|
workspaceContext = context;
|
|
30700
30945
|
const { model } = context;
|
|
30946
|
+
onDiagramChange(model);
|
|
30947
|
+
onClearDiagramStorage();
|
|
30701
30948
|
const dataProvider = createDataProvider(props);
|
|
30702
|
-
|
|
30703
|
-
|
|
30704
|
-
|
|
30705
|
-
|
|
30706
|
-
|
|
30949
|
+
const isReload = props.isReload;
|
|
30950
|
+
const savedDiagram = service(DiagramStorageService).load();
|
|
30951
|
+
if (isReload) {
|
|
30952
|
+
// Simply reload without using the current state. This may happen when the user switches the language at runtime.
|
|
30953
|
+
// since there is no existing mechanism to re-translate the UI at runtime (not for the UI labels at least)
|
|
30954
|
+
await model.importLayout({ dataProvider, diagram: currentDiagram, signal });
|
|
30955
|
+
}
|
|
30956
|
+
else if ((_a = config.seedIris) === null || _a === void 0 ? void 0 : _a.length) {
|
|
30957
|
+
await seedIrisToCanvas(context, dataProvider, config.seedIris, signal);
|
|
30958
|
+
}
|
|
30959
|
+
else if ((_b = config.seedGraph) === null || _b === void 0 ? void 0 : _b.length) {
|
|
30960
|
+
await seedGraphToCanvas(context, dataProvider, config.seedGraph, signal);
|
|
30707
30961
|
}
|
|
30708
30962
|
else {
|
|
30709
|
-
|
|
30710
|
-
|
|
30711
|
-
|
|
30712
|
-
}
|
|
30963
|
+
// Restore the previously saved layout when present, otherwise start empty. Either way this binds the
|
|
30964
|
+
// data provider (savedDiagram is undefined -> empty diagram), so the unified search/lookup works.
|
|
30965
|
+
await model.importLayout({ dataProvider, diagram: savedDiagram, signal });
|
|
30713
30966
|
}
|
|
30714
30967
|
}, [language]);
|
|
30715
30968
|
/**
|
|
@@ -30760,6 +31013,7 @@ function exportReactodiaLayout() {
|
|
|
30760
31013
|
* Unmounts the Reactodia application.
|
|
30761
31014
|
*/
|
|
30762
31015
|
function unmountReactodia(root) {
|
|
31016
|
+
subscriptions.unsubscribeAll();
|
|
30763
31017
|
root.unmount();
|
|
30764
31018
|
}
|
|
30765
31019
|
|
|
@@ -30767,7 +31021,7 @@ const graphwiseReactodiaCss = "graphwise-reactodia{display:block;width:100%;heig
|
|
|
30767
31021
|
|
|
30768
31022
|
const GraphwiseReactodia = class {
|
|
30769
31023
|
constructor(hostRef) {
|
|
30770
|
-
index.registerInstance(this, hostRef);
|
|
31024
|
+
index$1.registerInstance(this, hostRef);
|
|
30771
31025
|
/**
|
|
30772
31026
|
* UI language code (e.g. `en`, `fr`) for the Reactodia interface. Defaults to English.
|
|
30773
31027
|
*/
|
|
@@ -30778,13 +31032,13 @@ const GraphwiseReactodia = class {
|
|
|
30778
31032
|
}
|
|
30779
31033
|
onLanguageChange() {
|
|
30780
31034
|
// The translations are evaluated by the workspace at construction, so the only way
|
|
30781
|
-
// to re-translate the UI is to re-create the graph.
|
|
30782
|
-
|
|
30783
|
-
const diagram = exportReactodiaLayout();
|
|
30784
|
-
this.renderGraph(diagram);
|
|
31035
|
+
// to re-translate the UI is to re-create the graph.
|
|
31036
|
+
this.renderGraph(true);
|
|
30785
31037
|
}
|
|
30786
|
-
|
|
30787
|
-
this.
|
|
31038
|
+
connectedCallback() {
|
|
31039
|
+
if (this.config) {
|
|
31040
|
+
this.renderGraph();
|
|
31041
|
+
}
|
|
30788
31042
|
}
|
|
30789
31043
|
disconnectedCallback() {
|
|
30790
31044
|
if (this.reactRoot) {
|
|
@@ -30793,9 +31047,9 @@ const GraphwiseReactodia = class {
|
|
|
30793
31047
|
}
|
|
30794
31048
|
}
|
|
30795
31049
|
render() {
|
|
30796
|
-
return (index.h(index.Host, { key: '
|
|
31050
|
+
return (index$1.h(index$1.Host, { key: 'b33d3709a5d7b1fdde8d528d036d9dbc962d6c76' }));
|
|
30797
31051
|
}
|
|
30798
|
-
renderGraph(
|
|
31052
|
+
renderGraph(isReloading) {
|
|
30799
31053
|
var _a;
|
|
30800
31054
|
if (!this.currentRepository) {
|
|
30801
31055
|
throw new Error('currentRepository is required');
|
|
@@ -30807,20 +31061,20 @@ const GraphwiseReactodia = class {
|
|
|
30807
31061
|
return;
|
|
30808
31062
|
}
|
|
30809
31063
|
const props = {
|
|
30810
|
-
|
|
31064
|
+
isReload: isReloading,
|
|
30811
31065
|
currentRepository: this.currentRepository,
|
|
30812
31066
|
config: this.config,
|
|
30813
31067
|
language: this.language,
|
|
30814
31068
|
providerSettings: this.providerSettings,
|
|
30815
31069
|
};
|
|
30816
|
-
if (this.reactRoot && !
|
|
31070
|
+
if (this.reactRoot && !isReloading) {
|
|
30817
31071
|
void updateReactodia(props);
|
|
30818
31072
|
}
|
|
30819
31073
|
else {
|
|
30820
31074
|
this.reactRoot = mountReactodia(this.hostElement, props);
|
|
30821
31075
|
}
|
|
30822
31076
|
}
|
|
30823
|
-
get hostElement() { return index.getElement(this); }
|
|
31077
|
+
get hostElement() { return index$1.getElement(this); }
|
|
30824
31078
|
static get watchers() { return {
|
|
30825
31079
|
"currentRepository": ["onProviderSettingsChange"],
|
|
30826
31080
|
"providerSettings": ["onProviderSettingsChange"],
|
package/dist/cjs/index.cjs.js
CHANGED
|
@@ -1,2 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Event name for clearing the local store state of the diagram. There is an event listener listening for it, which
|
|
5
|
+
* will clear the local store state, whenever this event is fired.
|
|
6
|
+
*/
|
|
7
|
+
const CLEAR_DIAGRAM_STORAGE_EVENT = 'graphwise-reactodia:clear-diagram-storage';
|
|
8
|
+
|
|
9
|
+
exports.CLEAR_DIAGRAM_STORAGE_EVENT = CLEAR_DIAGRAM_STORAGE_EVENT;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { h, Host } from "@stencil/core";
|
|
2
|
-
import {
|
|
2
|
+
import { mountReactodia, unmountReactodia, updateReactodia } from "./reactodia-app";
|
|
3
3
|
import { LanguageKey } from "./i18n/language-key";
|
|
4
4
|
/**
|
|
5
5
|
* A web component that renders a graph with the Reactodia workspace.
|
|
@@ -24,13 +24,13 @@ export class GraphwiseReactodia {
|
|
|
24
24
|
}
|
|
25
25
|
onLanguageChange() {
|
|
26
26
|
// The translations are evaluated by the workspace at construction, so the only way
|
|
27
|
-
// to re-translate the UI is to re-create the graph.
|
|
28
|
-
|
|
29
|
-
const diagram = exportReactodiaLayout();
|
|
30
|
-
this.renderGraph(diagram);
|
|
27
|
+
// to re-translate the UI is to re-create the graph.
|
|
28
|
+
this.renderGraph(true);
|
|
31
29
|
}
|
|
32
|
-
|
|
33
|
-
this.
|
|
30
|
+
connectedCallback() {
|
|
31
|
+
if (this.config) {
|
|
32
|
+
this.renderGraph();
|
|
33
|
+
}
|
|
34
34
|
}
|
|
35
35
|
disconnectedCallback() {
|
|
36
36
|
if (this.reactRoot) {
|
|
@@ -39,9 +39,9 @@ export class GraphwiseReactodia {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
render() {
|
|
42
|
-
return (h(Host, { key: '
|
|
42
|
+
return (h(Host, { key: 'b33d3709a5d7b1fdde8d528d036d9dbc962d6c76' }));
|
|
43
43
|
}
|
|
44
|
-
renderGraph(
|
|
44
|
+
renderGraph(isReloading) {
|
|
45
45
|
var _a;
|
|
46
46
|
if (!this.currentRepository) {
|
|
47
47
|
throw new Error('currentRepository is required');
|
|
@@ -53,13 +53,13 @@ export class GraphwiseReactodia {
|
|
|
53
53
|
return;
|
|
54
54
|
}
|
|
55
55
|
const props = {
|
|
56
|
-
|
|
56
|
+
isReload: isReloading,
|
|
57
57
|
currentRepository: this.currentRepository,
|
|
58
58
|
config: this.config,
|
|
59
59
|
language: this.language,
|
|
60
60
|
providerSettings: this.providerSettings,
|
|
61
61
|
};
|
|
62
|
-
if (this.reactRoot && !
|
|
62
|
+
if (this.reactRoot && !isReloading) {
|
|
63
63
|
void updateReactodia(props);
|
|
64
64
|
}
|
|
65
65
|
else {
|
|
@@ -0,0 +1,5 @@
|
|
|
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
|
+
export const CLEAR_DIAGRAM_STORAGE_EVENT = 'graphwise-reactodia:clear-diagram-storage';
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A collection of {@link Subscription}s that can be released together. Components collect the
|
|
3
|
+
* subscriptions they open and call {@link unsubscribeAll} on teardown so nothing is left
|
|
4
|
+
* listening.
|
|
5
|
+
*/
|
|
6
|
+
export class SubscriptionList {
|
|
7
|
+
constructor(subscriptions = []) {
|
|
8
|
+
this.items = subscriptions;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Adds a subscription to the list.
|
|
12
|
+
*/
|
|
13
|
+
add(subscription) {
|
|
14
|
+
this.items.push(subscription);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Adds multiple subscriptions to the list.
|
|
18
|
+
*/
|
|
19
|
+
addAll(subscriptions) {
|
|
20
|
+
this.items.push(...subscriptions);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Removes a subscription from the list without unsubscribing it.
|
|
24
|
+
*/
|
|
25
|
+
remove(subscription) {
|
|
26
|
+
this.items = this.items.filter((sub) => sub !== subscription);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Calls every subscription (unsubscribing it) and clears the list.
|
|
30
|
+
*/
|
|
31
|
+
unsubscribeAll() {
|
|
32
|
+
this.items.forEach((subscription) => subscription());
|
|
33
|
+
this.items = [];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ServiceProvider } from "./service.provider";
|
|
2
|
+
/**
|
|
3
|
+
* Injects the singleton instance of the given service class from the {@link ServiceProvider}.
|
|
4
|
+
*
|
|
5
|
+
* @param serviceClass The class of the service to inject.
|
|
6
|
+
* @returns The shared instance of the specified service class.
|
|
7
|
+
* @template T The type of the service to inject.
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* const diagramStateService = service(DiagramStateService);
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export function service(serviceClass) {
|
|
14
|
+
return ServiceProvider.get(serviceClass);
|
|
15
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider for all {@link Service} instances. Services are singletons: there is only one
|
|
3
|
+
* instance of each service, created on demand and cached here so every consumer shares it.
|
|
4
|
+
*/
|
|
5
|
+
export class ServiceProvider {
|
|
6
|
+
/**
|
|
7
|
+
* Returns the instance of the given service type, creating and caching it on first request.
|
|
8
|
+
*
|
|
9
|
+
* @param type The service type to retrieve.
|
|
10
|
+
* @returns The shared instance of the service.
|
|
11
|
+
* @template T The type of the service to retrieve.
|
|
12
|
+
*/
|
|
13
|
+
static get(type) {
|
|
14
|
+
if (!ServiceProvider.SERVICE_INSTANCES.has(type.name)) {
|
|
15
|
+
ServiceProvider.SERVICE_INSTANCES.set(type.name, new type());
|
|
16
|
+
}
|
|
17
|
+
return ServiceProvider.SERVICE_INSTANCES.get(type.name);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
ServiceProvider.SERVICE_INSTANCES = new Map();
|