Able to add new vertices

This commit is contained in:
Ladd Hoffman 2023-07-09 23:00:57 -05:00
parent 07370be4fa
commit a743a81218
7 changed files with 55 additions and 38 deletions

View File

@ -1,10 +1,11 @@
import { MermaidDiagram } from './mermaid.js';
export class Flowchart extends MermaidDiagram {
constructor(box, logBox, direction = 'BT') {
constructor(box, logBox, { direction = 'BT' } = {}) {
super(box, logBox);
this.direction = direction;
this.init();
this.controlBox = this.box.addBox('Controls');
}
init() {

View File

@ -9,7 +9,6 @@ export class MermaidDiagram {
this.renderBox = this.box.addBox('Render');
this.box.addBox('Spacer').setInnerHTML(' ');
this.logBoxPre = logBox.el.appendChild(document.createElement('pre'));
this.inSection = 0;
}
static initializeAPI() {
@ -20,10 +19,8 @@ export class MermaidDiagram {
darkMode: true,
primaryColor: '#2a5b6c',
primaryTextColor: '#b6b6b6',
// lineColor: '#349cbd',
lineColor: '#57747d',
signalColor: '#57747d',
// signalColor: '#349cbd',
noteBkgColor: '#516f77',
noteTextColor: '#cecece',
activationBkgColor: '#1d3f49',

View File

@ -47,26 +47,27 @@ export class Scene {
}
withFlowchart({ direction = 'BT' } = {}) {
const box = this.topSection.addBox('Flowchart').addClass('padded');
this.box.addBox('Spacer').setInnerHTML(' ');
const logBox = this.box.addBox('Flowchart text').addClass('dim');
this.flowchart = new Flowchart(box, logBox, direction);
this.withSectionFlowchart({ direction, section: this.topSection });
this.flowchart = this.lastFlowchart;
return this;
}
withAdditionalFlowchart({ id, name, direction = 'BT' } = {}) {
withSectionFlowchart({
id, name, direction = 'BT', section,
} = {}) {
section = section ?? this.middleSection;
const index = this.flowcharts.size;
name = name ?? `Flowchart ${index}`;
id = id ?? `flowchart_${CryptoUtil.randomUUID().slice(0, 4)}`;
const container = this.middleSection.addBox(name).flex();
const container = section.addBox(name).flex();
const box = container.addBox('Flowchart').addClass('padded');
const logBox = container.addBox('Flowchart text').addClass('dim');
const flowchart = new Flowchart(box, logBox, direction);
const flowchart = new Flowchart(box, logBox, { direction });
this.flowcharts.set(id, flowchart);
return this;
}
lastFlowchart() {
get lastFlowchart() {
if (!this.flowcharts.size) {
if (this.flowchart) {
return this.flowchart;

View File

@ -117,7 +117,7 @@ export class Edge {
.button({
id: 'cancel',
name: 'Cancel',
cb: () => doc.clear(),
cb: () => graph.resetEditorDocument(),
});
}
}

View File

@ -54,18 +54,15 @@ export class Vertex {
static prepareEditorDocument(graph, doc, vertexId) {
doc.clear();
const vertex = graph.getVertex(vertexId);
if (!vertex) {
throw new Error(`Could not find WDG Vertex ${vertexId}`);
}
const vertex = vertexId ? graph.getVertex(vertexId) : undefined;
const form = doc.form().lastElement;
doc.remark('<h3>Edit Vertex</h3>', { parentEl: form.el });
doc.remark(`<h3>${vertex ? 'Edit' : 'Add'} Vertex</h3>`, { parentEl: form.el });
form
.textField({
id: 'id', name: 'id', defaultValue: vertex.id,
id: 'id', name: 'id', defaultValue: vertex?.id,
})
.textField({ id: 'type', name: 'type', defaultValue: vertex.type })
.textField({ id: 'label', name: 'label', defaultValue: vertex.label });
.textField({ id: 'type', name: 'type', defaultValue: vertex?.type })
.textField({ id: 'label', name: 'label', defaultValue: vertex?.label });
doc.remark('<h4>Properties</h4>', { parentEl: form.el });
const subFormArray = form.subFormArray({ id: 'properties', name: 'properties' }).lastItem;
@ -81,8 +78,10 @@ export class Vertex {
doc.remark('<br>', { parentEl: subForm.el });
};
for (const [key, value] of vertex.properties.entries()) {
addPropertyForm(key, value);
if (vertex) {
for (const [key, value] of vertex.properties.entries()) {
addPropertyForm(key, value);
}
}
form.button({
@ -92,26 +91,34 @@ export class Vertex {
})
.button({
id: 'save',
name: 'Save',
name: this.id ? 'Save' : 'Add',
type: 'submit',
cb: ({ form: { value: formValue } }) => {
let fullRedraw = false;
if (formValue.id !== vertex.id) {
if (vertex && formValue.id !== vertex.id) {
fullRedraw = true;
}
// TODO: preserve data types of properties
formValue.properties = new Map(formValue.properties.map(({ key, value }) => [key, value]));
Object.assign(vertex, formValue);
vertex.displayVertex();
if (vertex) {
Object.assign(vertex, formValue);
vertex.displayVertex();
} else {
graph.addVertex(formValue.type, formValue.id, null, formValue.label);
}
if (fullRedraw) {
graph.redraw();
}
if (!vertex) {
// This was a new vertex. Now let's edit.
Vertex.prepareEditorDocument(graph, doc, formValue.id);
}
},
})
.button({
id: 'cancel',
name: 'Cancel',
cb: () => doc.clear(),
cb: () => graph.resetEditorDocument(),
});
return doc;
}

View File

@ -1,13 +1,13 @@
import { Vertex } from './vertex.js';
import { Edge } from './edge.js';
import { Document } from '../display/document.js';
const graphs = [];
const allGraphs = [];
const makeWDGHandler = (graphIndex) => (vertexId) => {
const graph = graphs[graphIndex];
const graph = allGraphs[graphIndex];
// We want a document for editing this node, which may be a vertex or an edge
const editorDoc = graph.scene.getDocument('editorDocument')
?? graph.scene.withDocument('editorDocument').lastDocument;
const { editorDoc } = graph;
if (vertexId.startsWith('edge:')) {
const [, from, to] = vertexId.split(':');
Edge.prepareEditorDocument(graph, editorDoc, from, to);
@ -22,14 +22,17 @@ export class WeightedDirectedGraph {
this.vertices = new Map();
this.edgeTypes = new Map();
this.nextVertexId = 0;
this.flowchart = scene?.flowchart;
this.flowchart = undefined;
this.editable = options.editable;
this.index = graphs.length;
graphs.push(this);
// Mermaid supports a click callback, but we can't customize arguments; we just get the vertex ID.
// In order to provide the appropriate graph context for each callback, we create a separate callback
// function for each graph.
this.index = allGraphs.length;
allGraphs.push(this);
window[`WDGHandler${this.index}`] = makeWDGHandler(this.index);
// TODO: Populate history
this.history = {};
}
@ -88,11 +91,19 @@ export class WeightedDirectedGraph {
}
withFlowchart() {
this.scene?.withAdditionalFlowchart();
this.flowchart = this.scene?.lastFlowchart();
this.scene?.withSectionFlowchart();
this.flowchart = this.scene?.lastFlowchart;
if (this.editable) {
this.editorDoc = new Document('Controls', this.flowchart.controlBox.el);
this.resetEditorDocument();
}
return this;
}
resetEditorDocument() {
Vertex.prepareEditorDocument(this, this.editorDoc);
}
addVertex(type, id, data, label, options) {
// Supports simple case of auto-incremented numeric ids
if (typeof id === 'object') {

View File

@ -37,7 +37,7 @@ describe('Document > Form > TextField', () => {
doc.remark('Hmm...!');
});
// it('can exist within a graph', () => {
// scene.withAdditionalFlowchart({ id: 'flowchart', name: 'Graph' });
// scene.withSectionFlowchart({ id: 'flowchart', name: 'Graph' });
// const graph = scene.lastFlowchart();
// });
});