graphwise-reactodia 0.0.1-TR10 → 0.0.1-TR12
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/COPYING +674 -0
- package/COPYING.LESSER +165 -0
- package/NOTICE +41 -0
- package/README.md +12 -0
- package/dist/cjs/graphwise-reactodia.cjs.entry.js +820 -81
- package/dist/collection/components/graphwise-reactodia/i18n/translations.js +4 -1
- package/dist/collection/components/graphwise-reactodia/menu/graphwise-menu.js +37 -0
- package/dist/collection/components/graphwise-reactodia/reactodia-app.js +6 -4
- package/dist/collection/components/graphwise-reactodia/services/diagram/diagram.service.js +14 -0
- package/dist/collection/components/graphwise-reactodia/services/diagram-file/diagram-file.service.js +68 -0
- package/dist/esm/graphwise-reactodia.entry.js +820 -81
- package/dist/graphwise-reactodia/graphwise-reactodia.esm.js +1 -1
- package/dist/graphwise-reactodia/p-52bd1b0e.entry.js +1 -0
- package/dist/types/components/graphwise-reactodia/menu/graphwise-menu.d.ts +9 -0
- package/dist/types/components/graphwise-reactodia/services/diagram/diagram.service.d.ts +11 -1
- package/dist/types/components/graphwise-reactodia/services/diagram-file/diagram-file.service.d.ts +24 -0
- package/package.json +6 -3
- package/dist/graphwise-reactodia/p-b56c58a0.entry.js +0 -1
|
@@ -1,6 +1,9 @@
|
|
|
1
|
+
import enTranslation from "./en.reactodia.translation.json";
|
|
1
2
|
import frTranslation from "./fr.reactodia.translation.json";
|
|
2
3
|
import { LanguageKey } from "./language-key";
|
|
3
|
-
// English is provided by default from reactodia so
|
|
4
|
+
// English is provided by default from reactodia, so the English bundle holds only our own keys and overrides. If
|
|
5
|
+
// A key is missing, reactodia defaults to its own translation.
|
|
4
6
|
export const TRANSLATIONS = {
|
|
7
|
+
[LanguageKey.EN]: enTranslation,
|
|
5
8
|
[LanguageKey.FR]: frTranslation
|
|
6
9
|
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createElement, Fragment } from "react";
|
|
2
|
+
import { ToolbarAction, ToolbarActionClearAll, ToolbarActionExport, ToolbarActionOpen, useTranslation, useWorkspace } from "@reactodia/workspace";
|
|
3
|
+
import { service } from "../providers/service/service-inject";
|
|
4
|
+
import { DiagramService } from "../services/diagram/diagram.service";
|
|
5
|
+
import { DiagramFileService } from "../services/diagram-file/diagram-file.service";
|
|
6
|
+
/**
|
|
7
|
+
* The workspace main menu: Reactodia's default actions, followed by the diagram download and upload.
|
|
8
|
+
*
|
|
9
|
+
* Passing a `menu` to the `DefaultWorkspace` replaces its default actions, so they are listed here again.
|
|
10
|
+
* Rendered inside the workspace, so the actions can use the workspace hooks.
|
|
11
|
+
*/
|
|
12
|
+
export function GraphwiseMenu() {
|
|
13
|
+
const { model } = useWorkspace();
|
|
14
|
+
const t = useTranslation();
|
|
15
|
+
const diagramFileService = service(DiagramFileService);
|
|
16
|
+
const diagramService = service(DiagramService);
|
|
17
|
+
const downloadDiagram = () => {
|
|
18
|
+
const timestamp = new Date().toISOString().replace(/[-:]|\.\d+Z$/g, '');
|
|
19
|
+
diagramFileService.download(model.exportLayout(), `diagram-${timestamp}${DiagramFileService.FILE_EXTENSION}`);
|
|
20
|
+
};
|
|
21
|
+
const uploadDiagram = async (file) => {
|
|
22
|
+
try {
|
|
23
|
+
const diagram = await diagramFileService.read(file);
|
|
24
|
+
await diagramService.importDiagram(model, model.dataProvider, diagram);
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
console.error('Failed to upload the diagram', error);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
return createElement(Fragment, null, createElement(ToolbarActionClearAll, {}), createElement(ToolbarActionExport, { kind: 'exportRaster' }), createElement(ToolbarActionExport, { kind: 'exportSvg' }), createElement(ToolbarActionExport, { kind: 'print' }), createElement(ToolbarAction,
|
|
31
|
+
// The same icon as ToolbarActionSave. We dont use that action, since it disables saving on refresh
|
|
32
|
+
{ className: 'reactodia-toolbar-action__save', title: t.text('graphwise_toolbar_action.download_diagram.title'), onSelect: downloadDiagram }, t.text('graphwise_toolbar_action.download_diagram.label')), createElement(ToolbarActionOpen, {
|
|
33
|
+
title: t.text('graphwise_toolbar_action.upload_diagram.title'),
|
|
34
|
+
fileAccept: DiagramFileService.FILE_EXTENSION,
|
|
35
|
+
onSelect: (file) => void uploadDiagram(file)
|
|
36
|
+
}, t.text('graphwise_toolbar_action.upload_diagram.label')));
|
|
37
|
+
}
|
|
@@ -9,8 +9,9 @@ import { DiagramStorageService } from "./services/diagram-storage/diagram-storag
|
|
|
9
9
|
import { EventService } from "./services/event/event.service";
|
|
10
10
|
import { SubscriptionList } from "./models/subscription-list";
|
|
11
11
|
import { resolveTypeStyle } from "./styles/type-style.resolver";
|
|
12
|
+
import { GraphwiseMenu } from "./menu/graphwise-menu";
|
|
12
13
|
/**
|
|
13
|
-
* Reactodia ships English as its built-in default bundle, so English
|
|
14
|
+
* Reactodia ships English as its built-in default bundle, so the English bundle only adds our own keys.
|
|
14
15
|
* Other languages are layered on top as partial bundles; unknown codes fall back to English.
|
|
15
16
|
*
|
|
16
17
|
* Reactodia never re-reads the translations, so the component must be remounted
|
|
@@ -128,10 +129,11 @@ function ReactodiaApp(props) {
|
|
|
128
129
|
const dataProvider = createDataProvider(props);
|
|
129
130
|
const isReload = props.isReload;
|
|
130
131
|
const savedDiagram = service(DiagramStorageService).load();
|
|
132
|
+
const diagramService = service(DiagramService);
|
|
131
133
|
if (isReload) {
|
|
132
134
|
// Simply reload without using the current state. This may happen when the user switches the language at runtime.
|
|
133
135
|
// since there is no existing mechanism to re-translate the UI at runtime (not for the UI labels at least)
|
|
134
|
-
await
|
|
136
|
+
await diagramService.importDiagram(model, dataProvider, currentDiagram, signal);
|
|
135
137
|
}
|
|
136
138
|
else if ((_a = config.seedIris) === null || _a === void 0 ? void 0 : _a.length) {
|
|
137
139
|
await seedIrisToCanvas(context, dataProvider, config.seedIris, signal);
|
|
@@ -142,7 +144,7 @@ function ReactodiaApp(props) {
|
|
|
142
144
|
else {
|
|
143
145
|
// Restore the previously saved layout when present, otherwise start empty. Either way this binds the
|
|
144
146
|
// data provider (savedDiagram is undefined -> empty diagram), so the unified search/lookup works.
|
|
145
|
-
await
|
|
147
|
+
await diagramService.importDiagram(model, dataProvider, savedDiagram, signal);
|
|
146
148
|
}
|
|
147
149
|
}, [language]);
|
|
148
150
|
/**
|
|
@@ -161,7 +163,7 @@ function ReactodiaApp(props) {
|
|
|
161
163
|
defaultLanguage: language,
|
|
162
164
|
translations: translationsForLanguage(language),
|
|
163
165
|
typeStyleResolver: resolveTypeStyle
|
|
164
|
-
}, createElement(DefaultWorkspace, {}));
|
|
166
|
+
}, createElement(DefaultWorkspace, { menu: createElement(GraphwiseMenu) }));
|
|
165
167
|
}
|
|
166
168
|
/**
|
|
167
169
|
* Mounts the Reactodia application into the given container and returns the React root.
|
|
@@ -14,6 +14,20 @@ import { Service } from "../../providers/service/service";
|
|
|
14
14
|
* Service for diagram related operations and subscriptions
|
|
15
15
|
*/
|
|
16
16
|
let DiagramService = DiagramService_1 = class DiagramService {
|
|
17
|
+
/**
|
|
18
|
+
* Replaces the diagram content with the given serialization. Element data is requested from the data provider and
|
|
19
|
+
* the links between the imported elements are validated against it.
|
|
20
|
+
*
|
|
21
|
+
* @param model The diagram model to import into.
|
|
22
|
+
* @param dataProvider The data provider to bind to the diagram.
|
|
23
|
+
* @param diagram The serialization to import. When `undefined`, the diagram is cleared.
|
|
24
|
+
* @param signal Optional signal to abort the import.
|
|
25
|
+
*/
|
|
26
|
+
importDiagram(model, dataProvider, diagram, signal) {
|
|
27
|
+
// selection is not cleared on import, so we clear it manually to avoid painting the previous selection
|
|
28
|
+
model.setSelection([]);
|
|
29
|
+
return model.importLayout({ dataProvider, diagram, signal, validateLinks: true });
|
|
30
|
+
}
|
|
17
31
|
/**
|
|
18
32
|
* Subscribes to diagram changes. On every debounced change the current layout is
|
|
19
33
|
* exported and passed to the callback.
|
package/dist/collection/components/graphwise-reactodia/services/diagram-file/diagram-file.service.js
ADDED
|
@@ -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 };
|