182 lines
5.0 KiB
JavaScript
182 lines
5.0 KiB
JavaScript
import { displayNumber } from '../../util/helpers.js';
|
|
|
|
import { Edge } from './edge.js';
|
|
|
|
export class Vertex {
|
|
constructor(graph, type, id, data, options = {}) {
|
|
this.graph = graph;
|
|
this.type = type;
|
|
this.id = id;
|
|
this.data = data;
|
|
this.label = options.label ?? this.id;
|
|
this.options = options;
|
|
this.edges = {
|
|
from: [],
|
|
to: [],
|
|
};
|
|
this.installedClickCallback = false;
|
|
this.properties = options.properties ?? new Map();
|
|
}
|
|
|
|
toJSON() {
|
|
return {
|
|
id: this.id,
|
|
type: this.type,
|
|
label: this.label,
|
|
properties: Array.from(this.properties.entries()).reduce((props, [key, value]) => {
|
|
props[key] = value;
|
|
return props;
|
|
}, {}),
|
|
};
|
|
}
|
|
|
|
reset() {
|
|
this.installedClickCallback = false;
|
|
}
|
|
|
|
getEdges(type, away) {
|
|
return this.edges[away ? 'from' : 'to'].filter(
|
|
(edge) => edge.type === type,
|
|
);
|
|
}
|
|
|
|
setProperty(key, value) {
|
|
this.properties.set(key, value);
|
|
return this;
|
|
}
|
|
|
|
displayVertex() {
|
|
if (this.options.hide) {
|
|
return;
|
|
}
|
|
|
|
let html = '';
|
|
if (this.type) {
|
|
html += `<span class='small'>${this.type}</span>`;
|
|
}
|
|
html += `${this.label || this.id}`;
|
|
html += '<table>';
|
|
console.log('displayVertex', { properties: this.properties });
|
|
for (const [key, value] of this.properties.entries()) {
|
|
const displayValue = typeof value === 'number' ? displayNumber(value) : value;
|
|
html += `<tr><td>${key}</td><td>${displayValue}</td></tr>`;
|
|
}
|
|
html += '</table>';
|
|
if (this.label && this.id !== this.label) {
|
|
html += `<span class=small>${this.id}</span><br>`;
|
|
}
|
|
html = html.replaceAll(/\n\s*/g, '');
|
|
this.graph.flowchart?.log(`${this.id}["${html}"]`);
|
|
|
|
if (this.graph.editable && !this.installedClickCallback) {
|
|
this.graph.flowchart?.log(`click ${this.id} WDGHandler${this.graph.index} "Edit Vertex ${this.id}"`);
|
|
this.installedClickCallback = true;
|
|
}
|
|
}
|
|
|
|
static prepareEditorDocument(graph, doc, vertexId) {
|
|
const vertex = vertexId ? graph.getVertex(vertexId) : undefined;
|
|
const form = doc.form().lastElement;
|
|
|
|
if (vertex) {
|
|
form.button({
|
|
name: 'New Vertex',
|
|
cb: () => {
|
|
graph.resetEditor();
|
|
},
|
|
});
|
|
}
|
|
doc.remark(`<h3>${vertex ? 'Edit' : 'Add'} Vertex</h3>`, { parentEl: form.el });
|
|
form
|
|
.textField({
|
|
name: 'id', defaultValue: vertex?.id,
|
|
})
|
|
.textField({ name: 'type', defaultValue: vertex?.type })
|
|
.textField({ name: 'label', defaultValue: vertex?.label });
|
|
|
|
doc.remark('<h4>Properties</h4>', { parentEl: form.el });
|
|
const subFormArray = form.subFormArray({ name: 'properties' }).lastItem;
|
|
const addPropertyForm = (key, value) => {
|
|
const { subForm } = form.subForm({ subFormArray }).lastItem;
|
|
subForm.textField({ name: 'key', defaultValue: key })
|
|
.textField({ name: 'value', defaultValue: value })
|
|
.button({
|
|
name: 'Remove Property',
|
|
cb: () => subFormArray.remove(subForm),
|
|
})
|
|
.remark('<br>');
|
|
};
|
|
|
|
if (vertex) {
|
|
for (const [key, value] of vertex.properties.entries()) {
|
|
addPropertyForm(key, value);
|
|
}
|
|
}
|
|
|
|
form.button({
|
|
name: 'Add Property',
|
|
cb: () => addPropertyForm('', ''),
|
|
});
|
|
|
|
form.submit({
|
|
name: 'Save',
|
|
cb: ({ form: { value: formValue } }) => {
|
|
let fullRedraw = false;
|
|
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]));
|
|
if (vertex) {
|
|
Object.assign(vertex, formValue);
|
|
vertex.displayVertex();
|
|
} else {
|
|
const {
|
|
type, id, label, properties,
|
|
} = formValue;
|
|
const newVertex = graph.addVertex(type, id, null, label, { properties });
|
|
Object.assign(newVertex, formValue);
|
|
doc.clear();
|
|
Vertex.prepareEditorDocument(graph, doc, newVertex.id);
|
|
}
|
|
if (fullRedraw) {
|
|
graph.redraw();
|
|
}
|
|
},
|
|
});
|
|
|
|
if (vertex) {
|
|
form.button({
|
|
name: 'Delete Vertex',
|
|
cb: () => {
|
|
graph.deleteVertex(vertex.id);
|
|
graph.redraw();
|
|
graph.resetEditor();
|
|
},
|
|
});
|
|
|
|
doc.remark('<h3>New Edge</h3>', { parentEl: form.el });
|
|
const newEdgeForm = doc.form({ name: 'newEdge' }).lastElement;
|
|
newEdgeForm.textField({ name: 'to' });
|
|
newEdgeForm.textField({ name: 'type' });
|
|
newEdgeForm.textField({ name: 'weight' });
|
|
newEdgeForm.submit({
|
|
name: 'Save',
|
|
cb: ({ form: { value: { to, type, weight } } }) => {
|
|
graph.setEdgeWeight(type, vertex, to, weight, null);
|
|
doc.clear();
|
|
Edge.prepareEditorDocument(graph, doc, vertex.id, to);
|
|
},
|
|
});
|
|
}
|
|
|
|
form.button({
|
|
name: 'Cancel',
|
|
cb: () => graph.resetEditor(),
|
|
parentEl: doc.el,
|
|
});
|
|
|
|
return doc;
|
|
}
|
|
}
|