UNPKG

family-hierarchy

Version:

A small library for **Angular 9+** that implements [vis-network](https://github.com/visjs/vis-network) to generate a hierarchy chart of a family.

378 lines (370 loc) 19.4 kB
import { __spread, __decorate } from 'tslib'; import { ɵɵdefineInjectable, Injectable, ViewChild, ContentChild, Input, Component, NgModule } from '@angular/core'; import { BehaviorSubject, Subject, Subscription } from 'rxjs'; import { DataSet, Network } from 'vis-network/standalone'; import { isObject } from 'util'; import { CommonModule } from '@angular/common'; var DEFAULT_NODE_IMAGE = 'data:image/png;base64,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'; var DEFAULT_UNION_IMAGE = 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE4LjEuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJDYXBhXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgMzEuODkxIDMxLjg5MSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgMzEuODkxIDMxLjg5MTsiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPGc+DQoJPHBhdGggZD0iTTMwLjU0Myw1Ljc0bC00LjA3OC00LjAzNWMtMS44MDUtMS43NzctNC43MzYtMS43ODktNi41NDUtMC4wMmwtNC41MjUsNC40MTRjLTEuODEyLDEuNzY4LTEuODIsNC42NDgtMC4wMiw2LjQyNA0KCQlsMi41ODYtMi40ODRjLTAuMjYyLTAuNzkxLDAuMDYxLTEuNjk3LDAuNzAxLTIuMzI0bDIuODc5LTIuODA3YzAuOTEyLTAuODg1LDIuMzc1LTAuODgxLDMuMjc1LDAuMDFsMi40NDksMi40Mg0KCQljMC45LDAuODkxLDAuODk2LDIuMzI2LTAuMDEsMy4yMTNsLTIuODc5LDIuODA5Yy0wLjYwOSwwLjU5NC0xLjYwOSwwLjkyLTIuMzg1LDAuNzExbC0yLjUzMywyLjQ4Ng0KCQljMS44MDMsMS43ODEsNC43MzIsMS43ODksNi41NDUsMC4wMmw0LjUyLTQuNDFDMzIuMzQsMTAuMzk2LDMyLjM0Niw3LjUxOSwzMC41NDMsNS43NHoiLz4NCgk8cGF0aCBkPSJNMTMuOTc1LDIxLjg5NGMwLjIxNSwwLjc3My0wLjEyOSwxLjc3My0wLjc1MiwyLjM4MWwtMi42ODksMi42MjdjLTAuOTIyLDAuOS0yLjQxNCwwLjg5NS0zLjMzMi0wLjAxMmwtMi40OTgtMi40NjENCgkJYy0wLjkxNi0wLjkwNi0wLjkxLTIuMzc5LDAuMDEyLTMuMjc1bDIuNjkxLTIuNjI3YzAuNjU2LTAuNjM3LDEuNTk4LTAuOTYxLDIuNDItMC42ODlsMi41OTQtMi41Nw0KCQljLTEuODM2LTEuODExLTQuODI0LTEuODItNi42NjgtMC4wMmwtNC4zNjMsNC4yNmMtMS44NDYsMS44MDMtMS44NTUsNC43MzQtMC4wMiw2LjU0OWw0LjE1NCw0LjEwNw0KCQljMS44MzQsMS44MDksNC44MiwxLjgxOCw2LjY2OCwwLjAxOGw0LjM2My00LjI2YzEuODQ0LTEuODA1LDEuODUyLTQuNzM0LDAuMDItNi41NDdMMTMuOTc1LDIxLjg5NHoiLz4NCgk8cGF0aCBkPSJNMTEuMTM5LDIwLjcyMmMwLjYxMSwwLjYxNywxLjYxMSwwLjYyMywyLjIzNCwwLjAwOGw3LjQ1NS03LjQxNmMwLjYyMS0wLjYxNywwLjYyNS0xLjYxNSwwLjAwOC0yLjIzNA0KCQljLTAuNjEzLTAuNjE1LTEuNjExLTAuNjE5LTIuMjMtMC4wMDZsLTcuNDU3LDcuNDE0QzEwLjUyOSwxOS4xMDMsMTAuNTI1LDIwLjEwMSwxMS4xMzksMjAuNzIyeiIvPg0KPC9nPg0KPC9zdmc+DQo='; var OPTION_DEFAULT = { interaction: { hover: true, selectConnectedEdges: false }, layout: { hierarchical: { enabled: true, levelSeparation: 150, nodeSpacing: 200, treeSpacing: 200, blockShifting: true, edgeMinimization: true, parentCentralization: true, direction: 'UD', sortMethod: 'directed', shakeTowards: 'leaves' // roots, leaves } }, edges: { shadow: true }, nodes: { shadow: true }, physics: { maxVelocity: 10, minVelocity: 0.1, } }; var DEFAULT_CONFIG = { links: { childrens: { styles: { color: '#848484', highlight: '#848484', hover: '#848484' } }, parents: { styles: { color: '#99004d', highlight: '#800040', hover: '#800040', } } }, nodes: { images: DEFAULT_NODE_IMAGE, size: 20 }, union: { images: DEFAULT_UNION_IMAGE, size: 20 } }; /* tslint:disable */ var FamilyHierarchyService = /** @class */ (function () { function FamilyHierarchyService() { this.currentEdges = new BehaviorSubject(new DataSet()); this._Edges = this.currentEdges.asObservable(); this.currentNodes = new BehaviorSubject(new DataSet()); this._Nodes = this.currentNodes.asObservable(); this.currentFhNodes = new BehaviorSubject([]); this._fhNodes = this.currentFhNodes.asObservable(); this.currentFhUnions = new BehaviorSubject([]); this._fhUnions = this.currentFhUnions.asObservable(); this.currentFhLinks = new BehaviorSubject([]); this._fhLinks = this.currentFhLinks.asObservable(); this.currentConfig = new BehaviorSubject(DEFAULT_CONFIG); this._config = this.currentConfig.asObservable(); this.init = new Subject(); this._init = this.init.asObservable(); this._clickNode = new Subject(); this.clickNode = this._clickNode.asObservable(); this._clickUnion = new Subject(); this.clickUnion = this._clickUnion.asObservable(); this._clickLink = new Subject(); this.clickLink = this._clickLink.asObservable(); } Object.defineProperty(FamilyHierarchyService.prototype, "Edges", { get: function () { return this._Edges; }, enumerable: true, configurable: true }); Object.defineProperty(FamilyHierarchyService.prototype, "Nodes", { get: function () { return this._Nodes; }, enumerable: true, configurable: true }); FamilyHierarchyService.prototype.setFhNodes = function (nodes) { this.currentNodes.next(this.generateNodes(nodes)); this.currentFhNodes.next(nodes); }; Object.defineProperty(FamilyHierarchyService.prototype, "FhNodes", { get: function () { return this._fhNodes; }, enumerable: true, configurable: true }); FamilyHierarchyService.prototype.setFhUnions = function (unions) { this.generateUnions(unions); this.currentFhUnions.next(unions); }; Object.defineProperty(FamilyHierarchyService.prototype, "FhUnions", { get: function () { return this._fhUnions; }, enumerable: true, configurable: true }); FamilyHierarchyService.prototype.setFhLinks = function (links) { this.currentEdges.next(this.generateEdges(links)); this.currentFhLinks.next(links); }; Object.defineProperty(FamilyHierarchyService.prototype, "FhLinks", { get: function () { return this._fhLinks; }, enumerable: true, configurable: true }); FamilyHierarchyService.prototype.setConfig = function (config) { this.currentConfig.next(this.mergeDeep(this.currentConfig.getValue(), config)); }; Object.defineProperty(FamilyHierarchyService.prototype, "config", { get: function () { return this._config; }, enumerable: true, configurable: true }); FamilyHierarchyService.prototype.sendClickEvent = function (e, type) { if (type === 'node') { var node = this.currentFhNodes.getValue().find(function (el) { return el.id === e.nodes[0]; }); if (node) { this._clickNode.next(node); } else { var id_1 = e.nodes[0].replace('u', ''); var union = this.currentFhUnions.getValue().find(function (el) { return el.id == id_1; }); this._clickUnion.next(union); } } else { var link = this.currentFhLinks.getValue().find(function (el) { return el.id == e.edges[0]; }); if (link) { this._clickLink.next(link); } else { var regex = /(?<=l)(.*?)(?=_)/; var id_2 = e.edges[0].toString().match(regex)[0]; this._clickLink.next(this.currentFhUnions.getValue().find(function (o) { return o.id == id_2; })); } } }; FamilyHierarchyService.prototype.initialize = function (data, config) { this.currentFhLinks.next(data.links); this.currentFhNodes.next(data.nodes); this.currentFhUnions.next(data.unions); this.currentEdges.next(this.generateEdges(data.links)), this.currentNodes.next(this.generateNodes(data.nodes)); this.generateUnions(data.unions); if (config) { this.setConfig(config); } this.init.next(true); }; FamilyHierarchyService.prototype.mergeDeep = function (target) { var _a, _b; var sources = []; for (var _i = 1; _i < arguments.length; _i++) { sources[_i - 1] = arguments[_i]; } if (!sources.length) { return target; } var source = sources.shift(); if (isObject(target) && isObject(source)) { for (var key in source) { if (isObject(source[key])) { if (!target[key]) { Object.assign(target, (_a = {}, _a[key] = {}, _a)); } else { target[key] = Object.assign({}, target[key]); } this.mergeDeep(target[key], source[key]); } else { Object.assign(target, (_b = {}, _b[key] = source[key], _b)); } } } return this.mergeDeep.apply(this, __spread([target], sources)); }; FamilyHierarchyService.prototype.generateNodes = function (nodes) { var _this = this; return new DataSet(nodes.map(function (o) { return _this.createNode(o); })); }; FamilyHierarchyService.prototype.createNode = function (o) { return { id: o.id, image: o.image ? o.image : this.currentConfig.getValue().nodes.images, shape: 'image', size: this.currentConfig.getValue().nodes.size, level: (o.level * 2) - 1, label: o.label }; }; FamilyHierarchyService.prototype.createEdge = function (o) { return { id: o.id, from: o.nodeId, to: "u" + o.unionId, color: this.currentConfig.getValue().links.childrens.styles }; }; FamilyHierarchyService.prototype.generateEdges = function (links) { var _this = this; return new DataSet(links.map(function (o) { return _this.createEdge(o); })); }; FamilyHierarchyService.prototype.generateUnions = function (unions) { var _this = this; unions.forEach(function (u) { _this.createUnion(u); }); }; FamilyHierarchyService.prototype.createUnion = function (u) { var _this = this; var level; var node = { id: "u" + u.id, image: this.currentConfig.getValue().union.images, shape: 'image', size: this.currentConfig.getValue().union.size, }; u.components.forEach(function (e) { var edge = { id: "l" + u.id + "_" + node.id + "-" + e, from: node.id, to: e, color: _this.currentConfig.getValue().links.parents.styles, }; level = _this.currentFhNodes.getValue().filter(function (n) { return n.id === e; })[0].level; _this.currentEdges.getValue().add(edge); }); node.level = (level * 2); this.currentNodes.getValue().add(node); }; FamilyHierarchyService.prototype.addNode = function (node) { this.currentFhNodes.getValue().push(node); this.currentNodes.getValue().add(this.createNode(node)); }; FamilyHierarchyService.prototype.addLink = function (link) { this.currentFhLinks.getValue().push(link); this.currentEdges.getValue().add(this.createEdge(link)); }; FamilyHierarchyService.prototype.addUnion = function (union) { this.currentFhUnions.getValue().push(union); this.createUnion(union); }; FamilyHierarchyService.ɵprov = ɵɵdefineInjectable({ factory: function FamilyHierarchyService_Factory() { return new FamilyHierarchyService(); }, token: FamilyHierarchyService, providedIn: "root" }); FamilyHierarchyService = __decorate([ Injectable({ providedIn: 'root' }) ], FamilyHierarchyService); return FamilyHierarchyService; }()); var FamilyHierarchyComponent = /** @class */ (function () { function FamilyHierarchyComponent(familyService) { this.familyService = familyService; this.class = ''; this.editMode = false; this.subs = new Subscription(); } FamilyHierarchyComponent.prototype.ngOnInit = function () { }; FamilyHierarchyComponent.prototype.ngAfterViewInit = function () { var _this = this; var init = this.familyService._init .subscribe(function (e) { _this.createNetwork(); }); this.subs.add(init); this.subs.add(this.familyService._config.subscribe(function (config) { return _this.config = config; })); this.subs.add(this.familyService.Edges.subscribe(function (edges) { return _this.dsEdge = edges; })); this.subs.add(this.familyService.Nodes.subscribe(function (nodes) { return _this.dsNode = nodes; })); }; FamilyHierarchyComponent.prototype.createNetwork = function () { var _this = this; this.visNetworkData = { nodes: this.dsNode, edges: this.dsEdge }; this.visNetwork = new Network(this.el.nativeElement, this.visNetworkData, OPTION_DEFAULT); this.visNetwork.on('selectNode', function (e) { _this.familyService.sendClickEvent(e, 'node'); }); this.visNetwork.on('selectEdge', function (e) { _this.familyService.sendClickEvent(e); }); }; FamilyHierarchyComponent.prototype.ngOnDestroy = function () { this.subs.unsubscribe(); }; FamilyHierarchyComponent.ctorParameters = function () { return [ { type: FamilyHierarchyService } ]; }; __decorate([ ViewChild('box') ], FamilyHierarchyComponent.prototype, "el", void 0); __decorate([ ContentChild('nodeTemplate') ], FamilyHierarchyComponent.prototype, "nodeTemplate", void 0); __decorate([ ViewChild('contentNode') ], FamilyHierarchyComponent.prototype, "contentNode", void 0); __decorate([ Input() ], FamilyHierarchyComponent.prototype, "class", void 0); __decorate([ Input() ], FamilyHierarchyComponent.prototype, "editMode", void 0); FamilyHierarchyComponent = __decorate([ Component({ selector: 'FamilyHierarchy', template: "<!-- <div class=\"vis-container\"\r\n [visNetwork]=\"visNetwork\"\r\n [visNetworkData]=\"visNetworkData\"\r\n [visNetworkOptions]=\"visNetworkOptions\"\r\n (initialized)=\"networkInitialized()\">\r\n</div>\r\n -->\r\n<div #box [class.edit-mode]=\"editMode\" [ngClass]=\"['vis-container', class]\"></div>", styles: [".vis-container{width:100%;height:100%;outline:0}.edit-mode{background-size:40px 40px;background-image:linear-gradient(to right,grey 1px,transparent 1px),linear-gradient(to bottom,grey 1px,transparent 1px)}"] }) ], FamilyHierarchyComponent); return FamilyHierarchyComponent; }()); var FamilyHierarchyModule = /** @class */ (function () { function FamilyHierarchyModule() { } FamilyHierarchyModule = __decorate([ NgModule({ declarations: [FamilyHierarchyComponent], imports: [ CommonModule, ], exports: [FamilyHierarchyComponent] }) ], FamilyHierarchyModule); return FamilyHierarchyModule; }()); /* * Public API Surface of family-hierarchy */ /** * Generated bundle index. Do not edit. */ export { FamilyHierarchyComponent, FamilyHierarchyModule, FamilyHierarchyService }; //# sourceMappingURL=family-hierarchy.js.map