import { Injectable } from "@angular/core" import { RippleRef } from "@angular/material/core"; import { BehaviorSubject, Subject } from "rxjs"; import { map } from "rxjs/operators"; import { CreateRuleDto, Rule, RulesService } from "../../../../../api"; import { environment } from "../../../../environments/environment"; import { RuleFlatNode } from "./rule-flat-node"; @Injectable({ providedIn: 'root' }) export class DynamicDatabase { dataChange = new BehaviorSubject([]); childAdded = new Subject(); get data(): Rule[] { return this.dataChange.value; } get count(): number { return this.dataChange.value.length }; protected addData(rule: Rule) { this.dataChange.next([...this.dataChange.value, rule]) } constructor(protected rulesService: RulesService) { this.rulesService.configuration.basePath = environment.apiUrl; this.rulesService.findAll() .subscribe( (rules: Rule[]) => this.dataChange.next( rules .filter(this.filterRuleWithParentFromRootLayer) .sort(this.compareRulesByParagraph) ) ), (err) => { //TODO add toaster } } getParagraphOfNextChild = (parentRule): string => `${parentRule.paragraph}.${parentRule.subRule.length + 1}`; filterRuleWithParentFromRootLayer = (rootLayerRule: Rule) => typeof rootLayerRule.parentRule !== 'number'; compareRulesByParagraph = (ruleA: Rule, ruleB: Rule) => this.compareParahraph(ruleA.paragraph, ruleB.paragraph); compareParahraph(paragraphA: string, paragraphB: string): 0 | 1 | -1 { if (paragraphA === paragraphB) { return 0; } const paragrapASections = paragraphA.split('.'); const paragrapBSections = paragraphB.split('.'); if (+paragrapASections[0] > +paragrapBSections[0]) { return 1; } if (+paragrapASections[0] < +paragrapBSections[0]) { return -1; } if (+paragrapASections[0] === +paragrapBSections[0]) { let shiftedParagraphASections = paragrapASections; shiftedParagraphASections.shift(); let shiftedParagraphBSections = paragrapBSections; shiftedParagraphBSections.shift(); return this.compareParahraph( shiftedParagraphASections.join('.'), shiftedParagraphBSections.join('.'), ) } } getParentById = (ruleId: string) => this.data.find(rule => rule.id === ruleId) insertEmptyChild(parent: Rule) { parent.subRule.push( { text: '', id: '0', parentRule: parent, paragraph: this.getParagraphOfNextChild(parent) } ) this.dataChange.next(this.data); this.childAdded.next(parent); } insertEmptyParent() { this.addData({ text: '', id: '0', parentRule: null, paragraph: `${this.count + 2}` }) } insertChild(parent: Rule, subRule: Rule) { const createSubRule: CreateRuleDto = { paragraph: subRule.paragraph, text: subRule.text, subRuleIds: null, parentId: parent.id } this.rulesService.create(createSubRule).subscribe( newSubRule => { if (typeof newSubRule.id !== 'undefined' && typeof newSubRule.parentRule?.id !== 'undefined') { const updateParentRule: CreateRuleDto = { paragraph: parent.paragraph, text: parent.text, subRuleIds: [...parent.subRule ? parent.subRule.map(rule => rule.id) : [], newSubRule.id] } as CreateRuleDto; this.rulesService.update(parent.id, updateParentRule).subscribe((updated) => { //TODO Push updated message this.update(parent.id, { paragraph: parent.paragraph, subRuleIds: [ ...parent.subRule .filter(rule => rule.id === "0") .map(rule => rule.id) ?? [], subRule.id, ], text: parent.text }).subscribe( (updated) => { //todo add update message }, (err) => { //TODO Push error message console.error(err); } ) }, (err) => { //TODO Push error message console.error(err); } ) return; } //TODO Push error message } ) if (!parent.subRule) { parent.subRule = []; } const lastIndex = parent.subRule.indexOf(subRule); parent.subRule[lastIndex] = subRule; this.dataChange.next(this.data); this.childAdded.next(parent); } update(id: string, changedData: Partial) { return this.rulesService.update(id, changedData); } insertParent(newRule: Rule) { const createNewRule: CreateRuleDto = { paragraph: `${this.count + 1}`, text: newRule.text, subRuleIds: null, parentId: null } this.rulesService.create(createNewRule).subscribe( () => { //TODO created message }, (err) => { //TODO Error message } ) this.dataChange.next(this.data); } removeChild(parent: Rule, subRule: Rule) { if (parent.subRule) { const subRuleToRemove = this.findSubRuleFromParent(parent, subRule); const indexIfSubRule = parent.subRule.indexOf(subRuleToRemove); if (indexIfSubRule > -1) { parent.subRule.splice(indexIfSubRule, 1); } this.dataChange.next(this.data); } } findSubRuleFromParent = (parent: Rule, subRule: Rule): Rule | null => parent.subRule.find(rules => rules.paragraph === subRule.paragraph && rules.id === subRule.id); }