Skip to content

Instantly share code, notes, and snippets.

@harpreetkhalsagtbit
Last active May 12, 2018 12:59
Show Gist options
  • Save harpreetkhalsagtbit/9660ea58d4613a6b4d509af7889bb414 to your computer and use it in GitHub Desktop.
Save harpreetkhalsagtbit/9660ea58d4613a6b4d509af7889bb414 to your computer and use it in GitHub Desktop.
parent child relation json operation with MoveUp, MoveDown in sibling array and Move one level up and down in the Heirarchy
// typescript version
import { Component } from '@angular/core';
import { ButtonViewComponent } from './button-view/button-view.component';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app works!';
private fieldArray: any = {auth:[],postAuthSuccess:[],postAuthFailure:[],accounting:[]};
private newAttribute: any = {};
private dataTemplate : any = {
"selectedModuleId": "",
"selectedModuleValueList": [
{
"id": 15,
"name": "as",
"type": "mysql",
"org_id": 2,
"config": "as"
},
{
"id": 16,
"name": "postgres",
"type": "postgres",
"org_id": 2,
"config": "postgres://postgres@localh"
},
{
"id": 12,
"name": "oracle",
"type": "oracle",
"org_id": 2,
"config": "oracle"
}
],
"selectedModuleValueId": ""
}
private root: node = new node();
traverse(arr: any) {
if(arr.children && arr.children.length) {
return this.traverse(arr.children)
} else {
return arr.map((element, index) => {
element.traversed = true;
console.log('element', element)
// if(element.children && element.children.length) {
// element.children = this.traverse(element.children)
// // var children = this.traverse(element.children)
// // console.log('children', children)
// }
return {
...element,
children:element.children.length?this.traverse(element.children):[],
id:element.id,
parent:element.parent.id
}
})
}
}
reverseTraverse(source, target) {
target = target.children;
console.log('source, target', source, target)
if(source.children && source.children.length) {
return this.reverseTraverse(source.children, target.children)
} else {
return source.map((element, index) => {
element.traversed = true;
target[index].selectedModuleId = element.selectedModuleId;
target[index].selectedModuleValueList = element.selectedModuleValueList;
target[index].selectedModuleValueId = element.selectedModuleValueId;
if(element.children && element.children.length) {
console.log(target, target[index], index)
return this.reverseTraverse(element.children, target[index])
}
return element
})
}
}
traverseAndFind(data, searchIndex) {
if((data.id.toString()) == searchIndex) {
return data;
} else if(data.children && data.children.length) {
let found = false;
let element = null;
for(let i=0;i<data.children.length;i++) {
element = data.children[i];
if(element.id == searchIndex) {
found = true;
break;
}
if(element.children && element.children.length) {
element = this.traverseAndFind(element, searchIndex)
if(element && (element.id == searchIndex)) {
found = true;
break;
}
} else {
console.log('else..element', element, element.id , searchIndex);
}
}
if(found) {
return element
}
}
}
addSubAccountingModule(rowData: any) {
this.reverseTraverse(this.fieldArray.accounting, this.root);
const child = new node();
Object.assign(child, this.dataTemplate);
let parent = this.traverseAndFind(this.root, (rowData && rowData.id) || this.root.id);
console.log(rowData, '------', (rowData && rowData.id) || this.root.id)
child.myparent = parent;
console.log('this.root', this.root)
let root = this.traverse(this.root);
console.log('root', root)
this.fieldArray.accounting = JSON.parse(JSON.stringify(root));
}
indentRight(rowData: any) {
this.reverseTraverse(this.fieldArray.accounting, this.root);
let node = this.traverseAndFind(this.root, (rowData && rowData.id) || this.root.id);
node.indentRight();
let root = this.traverse(this.root);
this.fieldArray.accounting = JSON.parse(JSON.stringify(root));
}
indentLeft(rowData: any) {
this.reverseTraverse(this.fieldArray.accounting, this.root);
let node = this.traverseAndFind(this.root, (rowData && rowData.id) || this.root.id);
node.indentLeft();
let root = this.traverse(this.root);
this.fieldArray.accounting = JSON.parse(JSON.stringify(root));
}
levelUp(rowData: any) {
this.reverseTraverse(this.fieldArray.accounting, this.root);
let node = this.traverseAndFind(this.root, (rowData && rowData.id) || this.root.id);
node.moveUp();
let root = this.traverse(this.root);
this.fieldArray.accounting = JSON.parse(JSON.stringify(root));
}
levelDown(rowData: any) {
this.reverseTraverse(this.fieldArray.accounting, this.root);
let node = this.traverseAndFind(this.root, (rowData && rowData.id) || this.root.id);
node.moveDown();
let root = this.traverse(this.root);
this.fieldArray.accounting = JSON.parse(JSON.stringify(root));
}
}
class node {
private parent:node = null;
private index:number = 0;
children:any = [];
set myparent(val:any) {
if(val) {
// if already a child of someone
if(this.parent) {
// break relation from existing parent
this.parent.children.splice(this.index, 1)
// update index of siblings
for(var i=this.index;i<this.parent.children.length;i++) {
--this.parent.children[i].index
}
}
console.log('set parent', val)
// Assign new parent
this.parent = val
// assign my index as in parent
this.index = this.parent.children.length
// add my ref as child to my new parent
val.children.push(this);
} else {
// remove parent if null/undefined/'' value
// break relation from existing parent
this.parent.children.splice(this.index, 1)
// update index of siblings
for(var i=this.index;i<this.parent.children.length;i++) {
--this.parent.children[i].index
}
// no parent
// this.parent = '';
}
}
get id(): any {
return this.parent?this.parent.id + "." + this.index:this.index
}
moveDown() {
// change position at same parent level between two sibling
var pos = this.index + 1;
if(this.parent && pos < this.parent.children.length) {
this.index ++;
var companion = this.parent.children.splice(pos,1).shift();
companion.index--;
this.parent.children.splice(pos - 1,0,companion)
}
}
moveUp() {
// change position at same parent level between two sibling
var pos = this.index - 1;
if(this.parent && pos >=0) {
this.index --;
var companion = this.parent.children.splice(pos,1).shift();
companion.index++;
this.parent.children.splice(pos + 1,0,companion)
}
}
indentRight() {
// indent right
this.myparent = this.parent.children[this.index - 1]
}
indentLeft() {
// Indent left
this.myparent = this.parent.parent
}
}
function node() {
return {
parent:'',
set myparent(val) {
if(val) {
// if already a child of someone
if(this.parent) {
// break relation from existing parent
this.parent.children.splice(this.index, 1)
// update index of siblings
for(var i=this.index;i<this.parent.children.length;i++) {
--this.parent.children[i].index
}
}
// Assign new parent
this.parent = val
// assign my index as in parent
this.index = this.parent.children.length
// add my ref as child to my new parent
val.children.push(this);
console.log(this.parent, 'parent is')
} else {
// remove parent if null/undefined/'' value
// break relation from existing parent
this.parent.children.splice(this.index, 1)
// update index of siblings
for(var i=this.index;i<this.parent.children.length;i++) {
--this.parent.children[i].index
}
// no parent
this.parent = '';
}
},
index:0,
get id() {return this.parent?this.parent.id + "." + this.index:this.index},
children:[],
moveDown: function() {
// change position at same parent level between two sibling
var pos = this.index + 1;
if(this.parent && pos < this.parent.children.length) {
this.index ++;
var companion = this.parent.children.splice(pos,1).shift();
companion.index--;
this.parent.children.splice(pos - 1,0,companion)
}
},
moveUp: function() {
// change position at same parent level between two sibling
var pos = this.index - 1;
if(this.parent && pos >=0) {
this.index --;
var companion = this.parent.children.splice(pos,1).shift();
companion.index++;
this.parent.children.splice(pos + 1,0,companion)
}
},
indentRight: function() {
// indent right
this.myparent = this.parent.children[this.index - 1]
},
indentLeft: function() {
// Indent left
this.myparent = this.parent.parent
}
}
}
// remove all circular reference to print a clean json
traverse(root)
function traverse(arr) {
if(arr.children && arr.children.length) {
return traverse(arr.children)
} else {
return arr.map(function(element, index) {
element.traversed = true;
if(element.children && element.children.length) {
element.children = traverse(element.children)
}
return {
children:element.children,
id:element.id,
parent:element.parent.id
}
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment