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, Visibility} from "../openaireLibrary/monitor/entities/stakeholder"; import {StakeholderService} from "../openaireLibrary/monitor/services/stakeholder.service"; import {HelperFunctions} from "../openaireLibrary/utils/HelperFunctions.class"; import {AlertModal} from "../openaireLibrary/utils/modal/alert"; import {Subject, 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"; import {IDeactivateComponent} from "../openaireLibrary/utils/can-exit.guard"; import {LayoutService} from "../openaireLibrary/dashboard/sharedComponents/sidebar/layout.service"; import {Option} from "../openaireLibrary/sharedComponents/input/input.component"; import {properties} from "../../environments/environment"; import {Session, User} from "../openaireLibrary/login/utils/helper.class"; import {UserManagementService} from "../openaireLibrary/services/user-management.service"; declare var UIkit; @Component({ selector: 'topic', templateUrl: './topic.component.html', }) export class TopicComponent implements OnInit, OnDestroy, IDeactivateComponent { private subscriptions: any[] = []; private paramsSub: any; public properties: EnvProperties = properties; public stakeholderUtils: StakeholderUtils = new StakeholderUtils(); public loading: boolean = true; public stickyPageHeader: boolean = false; public stakeholder: Stakeholder; public user: User; /** * Stakeholder change event * */ public change: Subject = new Subject(); /** * Current topic **/ public topicIndex: number = 0; /** * Current category */ public categoryIndex: number = 0; /** * Current Subcategory */ 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; @ViewChild('deleteModal', {static: true}) deleteModal: AlertModal; @ViewChild('editModal', {static: true}) editModal: AlertModal; public elementChildrenActionOnDelete: string; public filters: FormGroup; public all: Option = { value: 'all', label: 'All' }; constructor( private route: ActivatedRoute, private router: Router, private title: Title, private fb: FormBuilder, private stakeholderService: StakeholderService, private userManagementService: UserManagementService, private layoutService: LayoutService) { } public ngOnInit() { let subscription: Subscription; this.paramsSub = this.route.params.subscribe(params => { if (subscription) { subscription.unsubscribe(); } subscription = this.stakeholderService.getStakeholderAsObservable().subscribe(stakeholder => { if (stakeholder) { this.stakeholder = stakeholder; if (params['topic']) { this.topicIndex = this.stakeholder.topics.findIndex(topic => topic.alias === params['topic']); } else { this.topicIndex = 0; } this.categoryIndex = 0; this.subCategoryIndex = 0; this.filters = this.fb.group({ chartType: this.fb.control('all'), status: this.fb.control('all'), keyword: this.fb.control('') }); if (this.topicIndex === -1) { this.navigateToError(); } else { this.title.setTitle(stakeholder.name + " | Indicators"); } } }); this.subscriptions.push(subscription); }); this.subscriptions.push(this.userManagementService.getUserInfo().subscribe(user => { this.user = user; })) } public ngOnDestroy() { this.subscriptions.forEach(value => { if (value instanceof Subscriber) { value.unsubscribe(); } }); if (this.paramsSub instanceof Subscriber) { this.paramsSub.unsubscribe(); } } canExit(): boolean { this.subscriptions.forEach(value => { if (value instanceof Subscriber) { value.unsubscribe(); } }); this.stakeholderService.setStakeholder(this.stakeholder); return true; } hide(element: any) { UIkit.dropdown(element).hide(); } stakeholderChanged() { this.change.next(); } public saveElement() { if (this.type === "topic") { this.saveTopic(); } else if (this.type === "category") { this.saveCategory(); } else { this.saveSubCategory(); } } // public closeDeleteModal() { // this.deleteModal.cancel(); // } 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), creationDate: this.fb.control(topic.creationDate), alias: this.fb.control(topic.alias, [ Validators.required, this.stakeholderUtils.aliasValidator(topics) ] ), visibility: this.fb.control(topic.visibility), defaultId: this.fb.control(topic.defaultId), categories: this.fb.control(topic.categories), icon: this.fb.control(topic.icon) }); 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(index = -1) { this.index = index; this.type = 'topic'; if (index === -1) { this.buildTopic(new Topic(null, null, null, "PUBLIC")); } else { this.buildTopic(this.stakeholder.topics[index]); } this.editOpen(); } public saveTopic() { if (!this.form.invalid) { let path = [this.stakeholder._id]; let callback = (topic: Topic): void => { if (this.index === -1) { this.stakeholder.topics.push(topic); } else { this.stakeholder.topics[this.index] = HelperFunctions.copy(topic); } }; if (this.index === -1) { this.save('Topic has been successfully created', path, this.form.value, callback); } else { this.save('Topic has been successfully saved', path, this.form.value, callback); } } } public changeTopicStatus(index: number, visibility: Visibility) { this.type = 'topic'; let path = [ this.stakeholder._id, this.stakeholder.topics[index]._id ]; this.changeStatus(this.stakeholder.topics[index], path, visibility); } public deleteTopicOpen(index = this.topicIndex, childrenAction: string = null) { this.type = 'topic'; this.index = index; this.element = this.stakeholder.topics[this.index]; this.deleteOpen(childrenAction); } public deleteTopic() { let path: string[] = [ this.stakeholder._id, this.stakeholder.topics[this.index]._id ]; let callback = (): void => { this.topicIndex = Math.max(0, this.index - 1); this.stakeholder.topics.splice(this.index, 1); }; this.delete('Topic has been successfully be deleted', path, callback, (this.topicIndex === this.index)); } public chooseCategory(index: number) { this.categoryIndex = index; this.subCategoryIndex = 0; } 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), creationDate: this.fb.control(category.creationDate), alias: this.fb.control(category.alias, [ Validators.required, this.stakeholderUtils.aliasValidator(categories) ] ), visibility: this.fb.control(category.visibility), defaultId: this.fb.control(category.defaultId), 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, "PUBLIC")); } 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); } }; 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 changeCategoryStatus(index: number, visibility: Visibility) { 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.changeStatus(this.stakeholder.topics[this.topicIndex].categories[this.index], path, visibility); } public deleteCategoryOpen(index: number, childrenAction: string = null) { this.type = 'category'; this.index = index; this.element = this.stakeholder.topics[this.topicIndex].categories[this.index]; this.deleteOpen(childrenAction); } 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.categoryIndex = Math.max(0, this.index - 1); this.stakeholder.topics[this.topicIndex].categories.splice(this.index, 1); }; this.delete('Category has been successfully be deleted', path, callback); } private buildSubcategory(subCategory: SubCategory) { let subCategories = this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].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), creationDate: this.fb.control(subCategory.creationDate), alias: this.fb.control(subCategory.alias, [ Validators.required, this.stakeholderUtils.aliasValidator(subCategories) ] ), visibility: this.fb.control(subCategory.visibility), defaultId: this.fb.control(subCategory.defaultId), 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, "PUBLIC")); } else { this.buildSubcategory(this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].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.categoryIndex]._id ]; let callback = (subCategory: SubCategory): void => { if (this.index === -1) { this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories.push(subCategory); } else { this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.index] = HelperFunctions.copy(subCategory); } }; 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 changeSubcategoryStatus(index: number, visibility: Visibility) { this.index = index; this.type = 'subcategory'; let path = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.index]._id ]; this.changeStatus(this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.index], path, visibility); } public deleteSubcategoryOpen(index, childrenAction: string = null) { this.type = 'subcategory'; this.index = index; this.element = this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.index]; this.deleteOpen(childrenAction); } public deleteSubcategory() { let path: string[] = [ this.stakeholder._id, this.stakeholder.topics[this.topicIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex]._id, this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories[this.index]._id ]; let callback = (): void => { this.subCategoryIndex = Math.max(0, this.index - 1); this.stakeholder.topics[this.topicIndex].categories[this.categoryIndex].subCategories.splice(this.index, 1); }; this.delete('Subcategory has been successfully be deleted', path, callback); } private navigateToError() { this.router.navigate([this.properties.errorLink], {queryParams: {'page': this.router.url}}); } get isCurator(): boolean { return Session.isPortalAdministrator(this.user) || Session.isCurator(this.stakeholder.type, this.user); } 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(childrenAction: string = null) { this.elementChildrenActionOnDelete = null; if (childrenAction == "delete") { this.elementChildrenActionOnDelete = childrenAction; } else if (childrenAction == "disconnect") { this.elementChildrenActionOnDelete = childrenAction; } this.deleteModal.alertTitle = 'Delete ' + this.type; this.deleteModal.cancelButtonText = 'No'; this.deleteModal.okButtonText = 'Yes'; // this.deleteModal.cancelButton = false; // this.deleteModal.okButton = false; this.deleteModal.open(); } private save(message: string, path: string[], saveElement: any, callback: Function, redirect = false) { this.subscriptions.push(this.stakeholderService.saveElement(this.properties.monitorServiceAPIURL, saveElement, path).subscribe(saveElement => { callback(saveElement); this.stakeholderChanged(); UIkit.notification(message, { status: 'success', timeout: 6000, pos: 'bottom-right' }); if (redirect) { this.router.navigate(['../' + saveElement.alias], { relativeTo: this.route }); } }, error => { UIkit.notification(error.error.message, { status: 'danger', timeout: 6000, pos: 'bottom-right' }); })); } private delete(message: string, path: string[], callback: Function, redirect = false) { this.subscriptions.push(this.stakeholderService.deleteElement(this.properties.monitorServiceAPIURL, path, this.elementChildrenActionOnDelete).subscribe(() => { callback(); this.stakeholderChanged(); UIkit.notification(message, { status: 'success', timeout: 6000, pos: 'bottom-right' }); if (redirect) { this.back(); } }, error => { UIkit.notification(error.error.message, { status: 'danger', timeout: 6000, pos: 'bottom-right' }); })); } private changeStatus(element: Topic | Category | SubCategory, path: string[], visibility: Visibility) { this.subscriptions.push(this.stakeholderService.changeVisibility(this.properties.monitorServiceAPIURL, path, visibility).subscribe(visibility => { element.visibility = visibility; UIkit.notification(StringUtils.capitalize(this.type) + ' has been successfully changed to ' + element.visibility.toLowerCase(), { status: 'success', timeout: 6000, pos: 'bottom-right' }); }, error => { UIkit.notification(error.error.message, { status: 'danger', timeout: 6000, pos: 'bottom-right' }); })); } back() { this.router.navigate(['../'], { relativeTo: this.route }); } chooseSubcategory(subcategoryIndex: number) { this.subCategoryIndex = subcategoryIndex; } public getPluralTypeName(): string { if (this.type == "topic") { return "Topics"; } else if (this.type == "category") { return "Categories"; } else if (this.type == "subcategory") { return "Subcategories"; } else { return this.type; } } public get isSmallScreen() { return this.layoutService.isSmallScreen; } public get open() { return this.layoutService.open; } public toggleOpen(event: MouseEvent) { event.preventDefault(); this.layoutService.setOpen(!this.open); } }