fix: make the DynamicLoading story work again (#296)

Fix Story by using `ModelXmlSerializer` to ensure that codecs are
correctly registered. Also move the code of the story to TypeScript to
better detect the errors.

In addition:
  - update `DynamicStyle.stories.js` to improve comments and the code.
- change the `moduleResolution` to `node` in tsconfig to work in all
IDE. This is a temporary change.
development
Thomas Bouffard 2024-01-08 18:49:27 +01:00 committed by GitHub
parent 728776b3e6
commit 9a7b2b463d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 33 deletions

View File

@ -16,15 +16,16 @@ limitations under the License.
*/ */
import { import {
Graph,
TextShape,
Effects, Effects,
EventObject,
Graph,
GraphDataModel,
InternalEvent, InternalEvent,
constants, ModelXmlSerializer,
Perimeter, Perimeter,
Codec, TextShape,
xmlUtils,
} from '@maxgraph/core'; } from '@maxgraph/core';
import type { Cell } from '@maxgraph/core';
import { globalTypes, globalValues } from './shared/args.js'; import { globalTypes, globalValues } from './shared/args.js';
export default { export default {
@ -37,7 +38,7 @@ export default {
}, },
}; };
const Template = ({ label, ...args }) => { const Template = ({ label, ...args }: Record<string, any>) => {
const container = document.createElement('div'); const container = document.createElement('div');
container.style.position = 'relative'; container.style.position = 'relative';
container.style.overflow = 'hidden'; container.style.overflow = 'hidden';
@ -48,7 +49,7 @@ const Template = ({ label, ...args }) => {
let requestId = 0; let requestId = 0;
// Speedup the animation // Speedup the animation
TextShape.prototype.enableBoundingBox = false; TextShape.prototype.useSvgBoundingBox = false;
// Creates the graph inside the given container // Creates the graph inside the given container
const graph = new Graph(container); const graph = new Graph(container);
@ -57,7 +58,7 @@ const Template = ({ label, ...args }) => {
graph.setEnabled(false); graph.setEnabled(false);
// Handles clicks on cells // Handles clicks on cells
graph.addListener(InternalEvent.CLICK, function (sender, evt) { graph.addListener(InternalEvent.CLICK, function (_sender: any, evt: EventObject) {
const cell = evt.getProperty('cell'); const cell = evt.getProperty('cell');
if (cell != null) { if (cell != null) {
@ -67,7 +68,7 @@ const Template = ({ label, ...args }) => {
// Changes the default vertex style in-place // Changes the default vertex style in-place
const style = graph.getStylesheet().getDefaultVertexStyle(); const style = graph.getStylesheet().getDefaultVertexStyle();
style.shape = constants.SHAPE.ELLIPSE; style.shape = 'ellipse';
style.perimeter = Perimeter.EllipsePerimeter; style.perimeter = Perimeter.EllipsePerimeter;
style.gradientColor = 'white'; style.gradientColor = 'white';
@ -81,15 +82,17 @@ const Template = ({ label, ...args }) => {
const cell = graph.insertVertex(parent, '0-0', '0-0', cx - 20, cy - 15, 60, 40); const cell = graph.insertVertex(parent, '0-0', '0-0', cx - 20, cy - 15, 60, 40);
// Animates the changes in the graph model // Animates the changes in the graph model
graph.getDataModel().addListener(InternalEvent.CHANGE, function (sender, evt) { graph
const { changes } = evt.getProperty('edit'); .getDataModel()
Effects.animateChanges(graph, changes); .addListener(InternalEvent.CHANGE, function (_sender: any, evt: EventObject) {
}); const { changes } = evt.getProperty('edit');
Effects.animateChanges(graph, changes);
});
// Loads the links for the given cell into the given graph // Loads the links for the given cell into the given graph
// by requesting the respective data in the server-side // by requesting the respective data in the server-side
// (implemented for this demo using the server-function) // (implemented for this demo using the server-function)
function load(graph, cell) { function load(graph: Graph, cell: Cell) {
if (cell.isVertex()) { if (cell.isVertex()) {
const cx = args.width / 2; const cx = args.width / 2;
const cy = args.height / 2; const cy = args.height / 2;
@ -101,22 +104,24 @@ const Template = ({ label, ...args }) => {
// Adds cells to the model in a single step // Adds cells to the model in a single step
graph.batchUpdate(() => { graph.batchUpdate(() => {
const xml = server(cell.id); const xml = server(cell.id);
const doc = xmlUtils.parseXml(xml);
const dec = new Codec(doc);
const model = dec.decode(doc.documentElement); const model = new GraphDataModel();
new ModelXmlSerializer(model).import(xml);
// Removes all cells which are not in the response // Removes all cells which are not in the response
for (const key in graph.getDataModel().cells) { for (const key in graph.getDataModel().cells) {
const tmp = graph.getDataModel().getCell(key); const tmp = graph.getDataModel().getCell(key);
if (tmp != cell && tmp.isVertex()) { if (tmp != null && tmp != cell && tmp.isVertex()) {
graph.removeCells([tmp]); graph.removeCells([tmp]);
} }
} }
// Merges the response model with the client model // Merges the response model with the client model
graph.getDataModel().mergeChildren(model.getRoot().getChildAt(0), parent); // Here we know that the root is not null
graph
.getDataModel()
.mergeChildren((model.getRoot() as Cell).getChildAt(0), parent);
// Moves the given cell to the center // Moves the given cell to the center
let geo = cell.getGeometry(); let geo = cell.getGeometry();
@ -138,7 +143,7 @@ const Template = ({ label, ...args }) => {
for (const key in graph.getDataModel().cells) { for (const key in graph.getDataModel().cells) {
const tmp = graph.getDataModel().getCell(key); const tmp = graph.getDataModel().getCell(key);
if (tmp != cell && tmp.isVertex()) { if (tmp != null && tmp != cell && tmp.isVertex()) {
vertices.push(tmp); vertices.push(tmp);
// Changes the initial location "in-place" // Changes the initial location "in-place"
@ -176,12 +181,12 @@ const Template = ({ label, ...args }) => {
// Simulates the existence of a server that can crawl the // Simulates the existence of a server that can crawl the
// big graph with a certain depth and create a graph model // big graph with a certain depth and create a graph model
// for the traversed cells, which is then sent to the client // for the traversed cells, which is then sent to the client
function server(cellId) { function server(cellId: string | null) {
// Increments the request ID as a prefix for the cell IDs // Increments the request ID as a prefix for the cell IDs
requestId++; requestId++;
// Creates a local graph with no display // Creates a local graph with no display (pass null as container)
const graph = new Graph(); const graph = new Graph(null!);
// Gets the default parent for inserting new cells. This // Gets the default parent for inserting new cells. This
// is normally the first child of the root (ie. layer 0). // is normally the first child of the root (ie. layer 0).
@ -190,20 +195,17 @@ const Template = ({ label, ...args }) => {
// Adds cells to the model in a single step // Adds cells to the model in a single step
graph.batchUpdate(() => { graph.batchUpdate(() => {
const v0 = graph.insertVertex(parent, cellId, 'Dummy', 0, 0, 60, 40); const v0 = graph.insertVertex(parent, cellId, 'Dummy', 0, 0, 60, 40);
const cellCount = parseInt(Math.random() * 16) + 4; const cellCount = Math.floor(Math.random() * 16) + 4;
// Creates the random links and cells for the response // Creates the random links and cells for the response
for (let i = 0; i < cellCount; i++) { for (let i = 0; i < cellCount; i++) {
const id = `${requestId}-${i}`; const id = `${requestId}-${i}`;
const v = graph.insertVertex(parent, id, id, 0, 0, 60, 40); const v = graph.insertVertex(parent, id, id, 0, 0, 60, 40);
const e = graph.insertEdge(parent, null, `Link ${i}`, v0, v); graph.insertEdge(parent, null, `Link ${i}`, v0, v);
} }
}); });
const enc = new Codec(); return new ModelXmlSerializer(graph.getDataModel()).export();
const node = enc.encode(graph.getDataModel());
return xmlUtils.getXml(node);
} }
load(graph, cell); load(graph, cell);

View File

@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import { Graph, utils, RubberBandHandler } from '@maxgraph/core'; import { Graph, RubberBandHandler } from '@maxgraph/core';
import { import {
globalTypes, globalTypes,
globalValues, globalValues,
@ -57,7 +57,7 @@ const Template = ({ label, ...args }) => {
// Needs to set a flag to check for dynamic style changes, // Needs to set a flag to check for dynamic style changes,
// that is, changes to styles on cells where the style was // that is, changes to styles on cells where the style was
// not explicitely changed using mxStyleChange // not explicitly changed using mxStyleChange
graph.getView().updateStyle = true; graph.getView().updateStyle = true;
// Overrides Cell.getStyle to return a specific style // Overrides Cell.getStyle to return a specific style
@ -74,7 +74,7 @@ const Template = ({ label, ...args }) => {
if (target != null) { if (target != null) {
const targetStyle = graph.getCurrentCellStyle(target); const targetStyle = graph.getCurrentCellStyle(target);
const fill = utils.getValue(targetStyle, 'fillColor'); const fill = targetStyle.fillColor;
if (fill != null) { if (fill != null) {
style.strokeColor = fill; style.strokeColor = fill;

View File

@ -9,7 +9,8 @@
/* Bundler mode */ /* Bundler mode */
"allowJs": true, "allowJs": true,
"moduleResolution": "bundler", // TODO restore bundler - require exports in the package.json of @maxgraph/core
"moduleResolution": "Node",
"allowImportingTsExtensions": true, "allowImportingTsExtensions": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true, "isolatedModules": true,