import {Component, OnDestroy, OnInit, ViewChild} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {Title} from '@angular/platform-browser'; import {EnvProperties} from '../openaireLibrary/utils/properties/env-properties'; import {Category, Stakeholder, SubCategory, Topic} from "../utils/entities/stakeholder"; import {StakeholderService} from "../services/stakeholder.service"; import {HelperFunctions} from "../openaireLibrary/utils/HelperFunctions.class"; import {AlertModal} from "../openaireLibrary/utils/modal/alert"; import {Subscriber, Subscription} from "rxjs"; import {FormBuilder, FormGroup, Validators} from "@angular/forms"; import {StakeholderUtils} from "../utils/indicator-utils"; import {StringUtils} from "../openaireLibrary/utils/string-utils.class"; declare var UIkit; @Component({ selector: 'topic', templateUrl: './topic.component.html', }) export class TopicComponent implements OnInit, OnDestroy { public subscriptions: any[] = []; public properties: EnvProperties; public stakeholderUtils: StakeholderUtils = new StakeholderUtils(); public loading: boolean = true; public stakeholder: Stakeholder; /** * Current topic **/ public topicIndex: number = 0; /** * categoryIndex: Current category to be edited, selectedCategoryIndex: selected on menu(opened) */ public categoryIndex: number = 0; public selectedCategoryIndex: number = 0; /** * Current Subcategory to be edited */ public subCategoryIndex: number = 0; /** * Current element and index of topic, category or subcategory to be deleted. */ public form: FormGroup; public element: Topic | Category | SubCategory; public type: 'topic' | 'category' | 'subcategory' = "topic"; public index: number = -1; /** * Check form validity */ public toggle: boolean = false; @ViewChild('deleteModal') deleteModal: AlertModal; @ViewChild('editModal') editModal: AlertModal; constructor( private route: ActivatedRoute, private router: Router, private title: Title, private fb: FormBuilder, private stakeholderService: StakeholderService) { } public ngOnInit() { this.route.data .subscribe((data: { envSpecific: EnvProperties }) => { this.properties = data.envSpecific; let subscription: Subscription; this.route.params.subscribe(params => { if (subscription) { subscription.unsubscribe(); } subscription = this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => { if (stakeholder) { this.stakeholder = HelperFunctions.copy(stakeholder); this.topicIndex = this.stakeholder.topics.findIndex(topic => topic.alias === params['topic']); if (this.topicIndex === -1) { this.navigateToError(); } else { this.title.setTitle(stakeholder.index_shortName + ' | ' + this.stakeholder.topics[this.topicIndex].name); this.toggle = true; } } }); this.subscriptions.push(subscription); }); }); } public ngOnDestroy() { this.subscriptions.forEach(value => { if (value instanceof Subscriber) { value.unsubscribe(); } }); } public saveElement() { if (this.type === "topic") { this.saveTopic(); } else if (this.type === "category") { this.saveCategory(); } else { this.saveSubCategory(); } } public deleteElement() { if (this.type === "topic") { this.deleteTopic(); } else if (this.type === "category") { this.deleteCategory(); } else { this.deleteSubcategory(); } } private buildTopic(topic: Topic) { let topics = this.stakeholder.topics.filter(element => element._id !== topic._id); this.form = this.fb.group({ _id: this.fb.control(topic._id), name: this.fb.control(topic.name, Validators.required), description: this.fb.control(topic.description), alias: this.fb.control(topic.alias, [ Validators.required, this.stakeholderUtils.aliasValidator(topics) ] ), isActive: this.fb.control(topic.isActive), isPublic: this.fb.control(topic.isPublic), isDefault: this.fb.control(topic.isDefault), categories: this.fb.control(topic.categories) }); this.subscriptions.push(this.form.get('name').valueChanges.subscribe(value => { let i = 1; value = this.stakeholderUtils.generateAlias(value); this.form.controls['alias'].setValue(value); while (this.form.get('alias').invalid) { this.form.controls['alias'].setValue(value + i); i++; } })); } public editTopicOpen() { this.index = this.topicIndex; this.type = 'topic'; this.buildTopic(this.stakeholder.topics[this.index]); this.editOpen(); } public saveTopic() { if (!this.form.invalid) { let path = [this.stakeholder._id]; let callback = (topic: Topic): void => { this.stakeholder.topics[this.index] = topic; this.stakeholderService.setStakeholder(this.stakeholder); }; this.save('Topic has been successfully saved', path, this.form.value, callback, true); } } public toggleTopicStatus() { this.index = this.topicIndex; this.type = 'topic'; let path = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id ]; this.toggleStatus(this.stakeholder.topics[this.topicIndex], path); } public toggleTopicAccess() { this.index = this.topicIndex; this.type = 'topic'; let path = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id ]; this.toggleAccess(this.stakeholder.topics[this.topicIndex], path); } public deleteTopicOpen() { this.type = 'topic'; this.index = this.topicIndex; this.element = this.stakeholder.topics[this.index]; this.deleteOpen(); } public deleteTopic() { let path: string[] = [ this.stakeholder._id, this.stakeholder.topics[this.index]._id ]; let callback = (): void => { this.stakeholder.topics.splice(this.index, 1); this.stakeholderService.setStakeholder(this.stakeholder); }; this.delete('Topic has been successfully be deleted', path, callback, true); } public toggleCategory(index: number) { if (this.selectedCategoryIndex !== index) { this.selectedCategoryIndex = index; this.toggle = true; } else { this.toggle = !this.toggle; } } private buildCategory(category: Category) { let categories = this.stakeholder.topics[this.topicIndex].categories.filter(element => element._id !== category._id); this.form = this.fb.group({ _id: this.fb.control(category._id), name: this.fb.control(category.name, Validators.required), description: this.fb.control(category.description), alias: this.fb.control(category.alias, [ Validators.required, this.stakeholderUtils.aliasValidator(categories) ] ), isActive: this.fb.control(category.isActive), isPublic: this.fb.control(category.isPublic), isDefault: this.fb.control(category.isDefault), subCategories: this.fb.control(category.subCategories) }); this.subscriptions.push(this.form.get('name').valueChanges.subscribe(value => { let i = 1; value = this.stakeholderUtils.generateAlias(value); this.form.controls['alias'].setValue(value); while (this.form.get('alias').invalid) { this.form.controls['alias'].setValue(value + i); i++; } })); } public editCategoryOpen(index: number = -1) { this.index = index; this.type = 'category'; if (index === -1) { this.buildCategory(new Category(null, null, null, true, true)); } else { this.buildCategory(this.stakeholder.topics[this.topicIndex].categories[index]); } this.editOpen(); } public saveCategory() { if (!this.form.invalid) { let path = [this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id]; let callback = (category: Category): void => { if (this.index === -1) { this.stakeholder.topics[this.topicIndex].categories.push(category); } else { this.stakeholder.topics[this.topicIndex].categories[this.index] = HelperFunctions.copy(category); } this.stakeholderService.setStakeholder(this.stakeholder); }; if (this.index === -1) { this.save('Category has been successfully created', path, this.form.value, callback); } else { this.save('Category has been successfully saved', path, this.form.value, callback); } } } public toggleCategoryStatus(index: number) { this.index = index; this.type = 'category'; let path = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.index]._id ]; this.toggleStatus(this.stakeholder.topics[this.topicIndex].categories[this.index], path); } public toggleCategoryAccess(index: number) { this.index = index; this.type = 'category'; let path = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.index]._id ]; this.toggleAccess(this.stakeholder.topics[this.topicIndex].categories[this.index], path); } public deleteCategoryOpen(index: number) { this.type = 'category'; this.index = index; this.element = this.stakeholder.topics[this.topicIndex].categories[this.index]; this.deleteOpen(); } public deleteCategory() { let path: string[] = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.index]._id ]; let callback = (): void => { this.stakeholder.topics[this.topicIndex].categories.splice(this.index, 1); this.stakeholderService.setStakeholder(this.stakeholder); }; this.delete('Category has been successfully be deleted', path, callback); } private buildSubcategory(subCategory: SubCategory) { let subCategories = this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories.filter(element => element._id !== subCategory._id); this.form = this.fb.group({ _id: this.fb.control(subCategory._id), name: this.fb.control(subCategory.name, Validators.required), description: this.fb.control(subCategory.description), alias: this.fb.control(subCategory.alias, [ Validators.required, this.stakeholderUtils.aliasValidator(subCategories) ] ), isActive: this.fb.control(subCategory.isActive), isPublic: this.fb.control(subCategory.isPublic), isDefault: this.fb.control(subCategory.isDefault), charts: this.fb.control(subCategory.charts), numbers: this.fb.control(subCategory.numbers) }); this.subscriptions.push(this.form.get('name').valueChanges.subscribe(value => { let i = 1; value = this.stakeholderUtils.generateAlias(value); this.form.controls['alias'].setValue(value); while (this.form.get('alias').invalid) { this.form.controls['alias'].setValue(value + i); i++; } })); } public editSubCategoryOpen(index: number = -1) { this.index = index; this.type = 'subcategory'; if (index === -1) { this.buildSubcategory(new SubCategory(null, null, null, true, true)); } else { this.buildSubcategory(this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[index]); } this.editOpen(); } public saveSubCategory() { if (!this.form.invalid) { let path: string[] = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id, ]; let callback = (subCategory: SubCategory): void => { if (this.index === -1) { this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories.push(subCategory); } else { this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index] = subCategory; } this.stakeholderService.setStakeholder(this.stakeholder); }; if (this.index === -1) { this.save('Subcategory has been successfully created', path, this.form.value, callback); } else { this.save('Subcategory has been successfully saved', path, this.form.value, callback); } } } public toggleSubcategoryStatus(index: number) { this.index = index; this.type = 'subcategory'; let path = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index]._id ]; this.toggleStatus(this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index], path); } public toggleSubcategoryAccess(index: number) { this.index = index; this.type = 'subcategory'; let path = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index]._id ]; this.toggleAccess(this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index], path); } public deleteSubcategoryOpen(index) { this.type = 'subcategory'; this.index = index; this.element = this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index]; this.deleteOpen(); } public deleteSubcategory() { let path: string[] = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories[this.index]._id ]; let callback = (): void => { this.stakeholder.topics[this.topicIndex].categories[this.selectedCategoryIndex].subCategories.splice(this.index, 1); this.stakeholderService.setStakeholder(this.stakeholder); }; this.delete('Subcategory has been successfully be deleted', path, callback); } private navigateToError() { this.router.navigate(['/error'], {queryParams: {'page': this.router.url}}); } private editOpen() { this.editModal.cancelButtonText = 'Cancel'; this.editModal.okButtonLeft = false; this.editModal.alertMessage = false; if (this.index === -1) { this.editModal.alertTitle = 'Create a new ' + this.type; this.editModal.okButtonText = 'Create'; } else { this.editModal.alertTitle = 'Edit ' + this.type + '\'s information '; this.editModal.okButtonText = 'Save'; } this.editModal.open(); } private deleteOpen() { this.deleteModal.alertTitle = 'Delete ' + this.type; this.deleteModal.cancelButtonText = 'No'; this.deleteModal.okButtonText = 'Yes'; this.deleteModal.open(); } private save(message: string, path: string[], saveElement: any, callback: Function, redirect = false) { this.stakeholderService.saveElement(this.properties.monitorServiceAPIURL, saveElement, path).subscribe(saveElement => { callback(saveElement); UIkit.notification(message, { status: 'success', timeout: 3000, pos: 'top-left' }); if (redirect) { this.router.navigate(['../' + saveElement.alias], { relativeTo: this.route }); } }, error => { UIkit.notification(error.error.message, { status: 'danger', timeout: 3000, pos: 'top-left' }); }); } private delete(message: string, path: string[], callback: Function, redirect = false) { this.stakeholderService.deleteElement(this.properties.monitorServiceAPIURL, path).subscribe(() => { callback(); UIkit.notification(message, { status: 'success', timeout: 3000, pos: 'top-left' }); if (redirect) { this.back(); } }, error => { UIkit.notification(error.error.message, { status: 'danger', timeout: 3000, pos: 'top-left' }); }); } private toggleStatus(element: Topic | Category | SubCategory, path: string[]) { this.stakeholderService.toggleStatus(this.properties.monitorServiceAPIURL, path).subscribe(isActive => { element.isActive = isActive; this.stakeholderService.setStakeholder(this.stakeholder); UIkit.notification(StringUtils.capitalize(this.type) + ' has been successfully ' + (isActive ? 'activated' : 'deactivated'), { status: 'success', timeout: 3000, pos: 'top-left' }); }, error => { UIkit.notification(error.error.message, { status: 'danger', timeout: 3000, pos: 'top-left' }); }); } private toggleAccess(element: Topic | Category | SubCategory, path: string[]) { this.stakeholderService.toggleAccess(this.properties.monitorServiceAPIURL, path).subscribe(isPublic => { element.isPublic = isPublic; this.stakeholderService.setStakeholder(this.stakeholder); UIkit.notification(StringUtils.capitalize(this.type) + ' has been successfully changed to ' + (isPublic ? 'public' : 'private'), { status: 'success', timeout: 3000, pos: 'top-left' }); }, error => { UIkit.notification(error.error.message, { status: 'danger', timeout: 3000, pos: 'top-left' }); }); } back() { this.router.navigate(['../'], { relativeTo: this.route }); } chooseSubcategory(categoryIndex: number, subcategoryIndex: number) { this.categoryIndex = categoryIndex; this.subCategoryIndex = subcategoryIndex; } }