Skip to content

Commit

Permalink
55 add export tree data to json (#137)
Browse files Browse the repository at this point in the history
* #55: add export tree data to json

* update version: set version to 1.0.6

---------

Co-authored-by: Egor Fedoseev <[email protected]>
  • Loading branch information
egor-progger and egor-progger authored Jan 8, 2025
1 parent e7330be commit 520b7f5
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 61 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
PointlineJS is an SVG based JS library for drawing tree diagrams.
It relies on Treant-JS, Raphael for handling SVG and animations, JQuery.

# Build status

[![Node.js Package](https://github.com/egor-progger/pointlinejs/actions/workflows/npm-publish.yml/badge.svg)](https://github.com/egor-progger/pointlinejs/actions/workflows/npm-publish.yml)

# Quick start

1. clone repository with command:
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pointlinejs",
"version": "1.0.5",
"version": "1.0.6",
"description": "JavaScipt library for visualization of tree diagrams",
"directories": {
"example": "examples"
Expand Down
13 changes: 8 additions & 5 deletions src/pointlinejs/components/button-callback.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
import { PointlineJS } from "@pointlinejs/pointlinejs";

export enum BUTTON_TYPE {
ADD_BUTTON = 'ADD_BUTTON'
ADD_BUTTON = 'ADD_BUTTON',
EXPORT_TO_JSON_BUTTON = 'EXPORT_TO_JSON_BUTTON',
}

export const BUTTON_CALLBACK = {
ADD_BUTTON: addBtnClickEvent,
EXPORT_TO_JSON_BUTTON: exportToJSONBtnClickEvent
}

function addBtnClickEvent(pointlineJS: PointlineJS, selectedEl: HTMLElement) {
console.log('addBtnClickEvent');
const tree = pointlineJS.getTree();
const nodeDb = tree.getNodeDb().db;
console.log(tree);
for (var key in nodeDb) {
var nodeTree = nodeDb[key];
if (nodeTree.text.name == selectedEl.textContent) {
const selectedNodeTree = nodeTree;
tree.addNode(selectedNodeTree, { text: { name: 'test' } })
// $('#modalWin').dialog("open");
tree.addNode(selectedNodeTree, { text: { name: 'test' } });
break;
}
}
}

function exportToJSONBtnClickEvent(pointlineJS: PointlineJS) {
return JSON.stringify(pointlineJS.exportTreeToJSON());
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const AddNodeDialogTemplate = `<div class="mdc-dialog">
export const DialogTemplate = `<div class="mdc-dialog">
<div class="mdc-dialog__container">
<div
class="mdc-dialog__surface"
Expand All @@ -8,8 +8,9 @@ export const AddNodeDialogTemplate = `<div class="mdc-dialog">
aria-describedby="my-dialog-content"
tabindex="-1"
>
<div class="mdc-dialog__content" id="my-dialog-content">
Add child node to selected?
<h2 class="mdc-dialog__title" id="dialog-title">[title]</h2>
<div class="mdc-dialog__content" id="dialog-content">
[content]
</div>
<div class="mdc-dialog__actions">
<button
Expand Down
80 changes: 55 additions & 25 deletions src/pointlinejs/components/pointline-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { PointlineJS } from "@pointlinejs/pointlinejs";
import { injectable } from "inversify";
import { BUTTON_CALLBACK, BUTTON_TYPE } from "./button-callback";
import { MDCDialog, MDCDialogCloseEvent } from '@material/dialog';
import { AddNodeDialogTemplate } from "./add-node-dialog";
import { DialogTemplate } from "./dialog-template";

interface ButtonAction {
id: string;
Expand Down Expand Up @@ -32,17 +32,16 @@ class ButtonItem implements ButtonAction {
getCallback(event: MouseEvent) {
return this.callback(event);
}

initCallback(callback: (ev: MouseEvent) => void) {
this.callback = callback;
}
}


const defaultButtons: ButtonItem[] = [
new ButtonItem(
'addNodeBtn', 'Add child node to selected', BUTTON_TYPE.ADD_BUTTON
),
new ButtonItem(
'exportNodeStructureBtn', 'Export nodes to JSON', BUTTON_TYPE.EXPORT_TO_JSON_BUTTON
)
];

export type PointlineAction = {
Expand All @@ -62,6 +61,7 @@ export class PointlineActions {
}

async init(idDiv: string, pointlineJS: PointlineJS) {
const dialogElements: HTMLElement[] = [];
this.actionsDiv = $('#' + idDiv)[0];
this.pointlineJS = pointlineJS;
$('.node').each((index, element) => {
Expand All @@ -71,55 +71,85 @@ export class PointlineActions {
});
for (var key in defaultButtons) {
var btnData = defaultButtons[key];
if (btnData.type === BUTTON_TYPE.ADD_BUTTON) {
this.createAddNodeModal(this.actionsDiv);
btnData.initCallback(() => this.showAddNodeModal(this.pointlineJS, this.selectedEl));
}
const modalId = `${btnData.id}-dialog`;
var btn = document.createElement('button');
btn.setAttribute("id", btnData.id);
btn.innerHTML = btnData.text;
btn.addEventListener("click", (event) => btnData.getCallback(event));
if (btnData.type === BUTTON_TYPE.ADD_BUTTON) {
dialogElements.push(this.createDivWithContentForModal(this.actionsDiv, modalId));
btn.addEventListener("click", () => this.showAddNodeModal(this.pointlineJS, this.selectedEl, modalId));
}
if (btnData.type === BUTTON_TYPE.EXPORT_TO_JSON_BUTTON) {
dialogElements.push(this.createDivWithContentForModal(this.actionsDiv, modalId));
btn.addEventListener("click", () => this.showExportJSONModal(this.pointlineJS, modalId));
}
if (btnData.type === BUTTON_TYPE.ADD_BUTTON) {
if (!this.selectedEl) {
btn.setAttribute('disabled', 'true');
}
}
this.actionsDiv.append(btn);
}
dialogElements.forEach((dialog) => this.actionsDiv.append(dialog));
}

selectFunc(nodeEl: EventTarget) {
if (this.selectedEl !== null) {
if (typeof this.selectedEl !== 'undefined') {
$(this.selectedEl).css("background-color", "");
this.disableAddNodeButton();
this.selectedEl = undefined;
} else {
const nodeName = $(nodeEl).find(".node-name");
nodeName.css("background-color", this.options.selectedElBackgroundColor);
this.selectedEl = nodeName[0];
this.enableAddNodeButton();
}
const nodeName = $(nodeEl).find(".node-name");
nodeName.css("background-color", this.options.selectedElBackgroundColor);
this.selectedEl = nodeName[0];
if (this.selectedEl) {
this.enabledAddNodeButton();
}
}

enabledAddNodeButton() {
enableAddNodeButton() {
const addNodeButton = defaultButtons.find((item) => item.type === BUTTON_TYPE.ADD_BUTTON);
const buttomElement = document.getElementById(addNodeButton.id);
buttomElement.removeAttribute("disabled");
}

disableAddNodeButton() {
const addNodeButton = defaultButtons.find((item) => item.type === BUTTON_TYPE.ADD_BUTTON);
const buttomElement = document.getElementById(addNodeButton.id);
buttomElement.removeAttribute('disabled');
buttomElement.setAttribute("disabled", "");
}

createAddNodeModal(parentElement: HTMLElement) {
const modalWin = document.createElement('div');
modalWin.innerHTML = AddNodeDialogTemplate;
parentElement.appendChild(modalWin);
createDivWithContentForModal(parentElement: HTMLElement, modalId: string) {
let modalWin = document.getElementById(modalId);
if (!modalWin || typeof modalWin === 'undefined') {
modalWin = document.createElement('div');
modalWin.setAttribute('id', modalId);
}
modalWin.innerHTML = DialogTemplate;
return modalWin;
}

showAddNodeModal(pointlineJS: PointlineJS, selectedEl: HTMLElement) {
const dialog = new MDCDialog(document.querySelector('.mdc-dialog'));
showAddNodeModal(pointlineJS: PointlineJS, selectedEl: HTMLElement, modalId: string) {
const dialogElement = document.getElementById(modalId);
const dialogTitle = dialogElement.querySelector('#dialog-title');
dialogTitle.innerHTML = 'Add child node to selected?';
const dialogContent = dialogElement.querySelector('#dialog-content');
dialogContent.innerHTML = '';
const dialog = new MDCDialog(document.querySelector(`#${modalId} .mdc-dialog`));
dialog.open();
dialog.listen('MDCDialog:closed', (event: MDCDialogCloseEvent) => {
if (event.detail.action === 'accept') {
BUTTON_CALLBACK.ADD_BUTTON(pointlineJS, selectedEl);
}
})
}

showExportJSONModal(pointlineJS: PointlineJS, modalId: string) {
const dialogTitle = document.querySelector(`#${modalId} #dialog-title`);
const dialogContent = document.querySelector(`#${modalId} #dialog-content`);
const JSON_data = BUTTON_CALLBACK.EXPORT_TO_JSON_BUTTON(pointlineJS);
dialogTitle.innerHTML = 'Export JSON result';
dialogContent.innerHTML = JSON_data;
const dialog = new MDCDialog(document.querySelector(`#${modalId} .mdc-dialog`));
dialog.open();
}
}
11 changes: 4 additions & 7 deletions src/pointlinejs/pointlinejs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ export class PointlineJS {

async draw() {
const tree = await this.treant.init(this.chartConfig);
console.log('draw');
console.log(tree);
if (tree) {
this.tree = tree;
if (this.actionsId) {
Expand All @@ -71,13 +69,9 @@ export class PointlineJS {
}
}
}
console.log('draw');
console.log(this.tree);
}

getTree() {
console.log('getTree');
console.log(this.tree);
return this.tree;
}

Expand All @@ -86,7 +80,10 @@ export class PointlineJS {
}

reload() {
console.log('reload');
this.tree.reload();
}

exportTreeToJSON() {
return this.treant.exportTreeToJSON();
}
}
15 changes: 15 additions & 0 deletions src/pointlinejs/vendor/treant/Treant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,13 @@ export class Treant {
this.tree.then((tree) => this.treeStore.destroy(tree.initTreeId));
}

/**
*
* @param jsonConfig
* @param callback
* @param jQuery
* @returns
*/
init(
jsonConfig: ChartConfigType,
callback?: (tree: Tree) => void,
Expand Down Expand Up @@ -389,4 +396,12 @@ export class Treant {
async getNodeDb() {
return (await this.tree).getNodeDb();
}

/**
*
* @returns {Tree}
*/
exportTreeToJSON() {
return this.treeStore.tree.initJsonConfig;
}
}
14 changes: 0 additions & 14 deletions src/pointlinejs/vendor/treant/Tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ export class Tree {
* @returns {Tree}
*/
reset(jsonConfig: ChartStructure, treeId: number) {
console.log('reset');
this.initJsonConfig = { ...this.initJsonConfig, ...jsonConfig };
this.initTreeId = treeId;

Expand All @@ -176,8 +175,6 @@ export class Tree {
// this.drawArea.innerHTML = '';

this.nodeDB = this.nodeDBClass.init(jsonConfig.nodeStructure, this);
console.log('this.nodeDB');
console.log(this.nodeDB);

// key store for storing reference to node connectors,
// key = nodeId where the connector ends
Expand All @@ -194,8 +191,6 @@ export class Tree {
* @returns {Tree}
*/
reload() {
console.log('reload tree');
console.log(this.initJsonConfig);
if (this.initJsonConfig !== null) {
this.reset(this.initJsonConfig, this.initTreeId).redraw();
}
Expand All @@ -213,7 +208,6 @@ export class Tree {
* @returns {Tree}
*/
redraw() {
console.log('redraw');
this.positionTree();
return this;
}
Expand All @@ -223,11 +217,9 @@ export class Tree {
* @returns {Tree}
*/
positionTree(callback?: (tree: Tree) => void) {
console.log('positionTree');
var self = this;

if (this.imageLoader.isNotLoading() === true) {
console.log('this.imageLoader.isNotLoading');
const root = this.root();

this.resetLevelData();
Expand Down Expand Up @@ -494,7 +486,6 @@ export class Tree {
* @returns {Tree}
*/
positionNodes() {
console.log('positionNodes');
var self = this,
treeSize = {
x: self.nodeDB.getMinMaxCoord('X', null, null),
Expand Down Expand Up @@ -522,8 +513,6 @@ export class Tree {
len,
node: TreeNode;

console.log(containerCenter);

// position all the nodes
for (i = 0, len = this.nodeDB.size; i < len; i++) {
node = this.nodeDB.get(i);
Expand Down Expand Up @@ -582,9 +571,6 @@ export class Tree {
node.drawLineThroughMe();
}

console.log('node');
console.log(node);

self.CONFIG.callback.onAfterPositionNode.apply(self, [
node,
i,
Expand Down
4 changes: 0 additions & 4 deletions src/pointlinejs/vendor/treant/TreeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,6 @@ export class TreeNode {
* @param {Tree} tree
*/
createGeometry(tree: Tree) {
console.log('createGeometry');
if (this.id === 0 && tree.CONFIG.hideRootNode) {
this.width = 0;
this.height = 0;
Expand Down Expand Up @@ -812,9 +811,6 @@ export class TreeNode {
tree.CONFIG.callback.onCreateNode.apply(tree, [this, node]);

/////////// APPEND all //////////////
console.log(node);
console.log('drawArea');
console.log(drawArea);
drawArea.appendChild(node);
this.width = node.offsetWidth;
this.height = node.offsetHeight;
Expand Down

0 comments on commit 520b7f5

Please sign in to comment.