import {Component, ElementRef, OnInit, ViewChild, Input} from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {HelpContentService} from '../../services/help-content.service'; import {FormBuilder, FormGroup, Validators} from '@angular/forms'; import {Portal} from '../../utils/entities/adminTool/portal'; import {EnvProperties} from '../../utils/properties/env-properties'; import {Session} from '../../login/utils/helper.class'; import {UserManagementService} from '../../services/user-management.service'; import {Subscriber, Subscription} from "rxjs"; import {properties} from "../../../../environments/environment"; import {StringUtils} from "../../utils/string-utils.class"; import {Title} from "@angular/platform-browser"; import {AlertModal} from '../../utils/modal/alert'; import {MenuItem} from '../../sharedComponents/menu'; import {SearchInputComponent} from '../../sharedComponents/search-input/search-input.component'; import {Page} from '../../utils/entities/adminTool/page'; import {Option} from '../../sharedComponents/input/input.component'; declare var UIkit; @Component({ selector: 'menuSelector', templateUrl: './menu.component.html' }) export class MenuComponent implements OnInit { @ViewChild('searchInputComponent') searchInputComponent: SearchInputComponent; @ViewChild('editModal') editModal: AlertModal; @ViewChild('deleteModal') deleteModal: AlertModal; public activeRootMenuId: string; public activeRootMenu: MenuItem; public childrenMenuItems: MenuItem[] = []; private index: number; public menuItemForm: FormGroup; public pageForm: FormGroup; public rootMenuItems = []; public allPages = []; public menuRouteStatus: Map = null; public selectedMenuItem: string; public isChild: boolean = false; public communities: Portal[] = []; public portal: string; public newPageWindowOpen: boolean = false; public showLoading = true; public isPortalAdministrator = null; public filterForm: FormGroup; public typeOptions: Option[] = [ {label: 'Internal Link', value: 'internal'}, {label: 'External Link', value: 'external'}, ] public rootOnlyTypeOptions: Option[] = [ {label: 'No Action', value: 'noAction'} ] public keyword: string = ''; public selectedKeyword: string = ''; private searchText: string = ''; public properties: EnvProperties = properties; private subscriptions: any[] = []; private typeSub: Subscription = null; constructor(private element: ElementRef, private route: ActivatedRoute, private _router: Router, private title: Title, private _helpContentService: HelpContentService, private userManagementService: UserManagementService, private _fb: FormBuilder) { } ngOnInit() { this.filterForm = this._fb.group({ keyword: [''], }); this.subscriptions.push(this.filterForm.get('keyword').valueChanges.subscribe(value => { this.searchText = value.toLowerCase(); this.applyFilters(); })); this.userManagementService.getUserInfo().subscribe(user => { this.portal = (this.route.snapshot.data.portal) ? this.route.snapshot.data.portal : this.route.snapshot.params[this.route.snapshot.data.param]; this.getMenuItems(); if (this.route.snapshot.data.portal) { this.title.setTitle(StringUtils.capitalize(this.portal) + ' | Menu'); } else if (this.route.snapshot.params[this.route.snapshot.data.param]) { this.title.setTitle(this.portal.toUpperCase() + ' | Menu'); } else { this.title.setTitle('Administrator Dashboard | Menu'); } this.isPortalAdministrator = Session.isPortalAdministrator(user) && !this.portal; }); } ngOnDestroy(): void { this.subscriptions.forEach(value => { if (value instanceof Subscriber) { value.unsubscribe(); } else if (value instanceof Function) { value(); } }); this.destroyTypeSubscription(); } destroyTypeSubscription() { if(this.typeSub instanceof Subscriber) { this.typeSub.unsubscribe(); } } getMenuItems() { this.subscriptions.push( this._helpContentService.getMenuItems(this.portal).subscribe( data => { this.rootMenuItems = data; if(data && data.length > 0) { this.changeActiveRootMenuItem(data[0]); } this.getPages(); this.showLoading = false; }, error => this.handleError("Server error fetching menu items", error) ) ); } getTypeOptions(isFeatured: boolean = false) { if(this.isChild) { return this.typeOptions; } else { if(isFeatured) { return this.typeOptions; } else { return this.typeOptions.concat(this.rootOnlyTypeOptions); } } } getActiveRootItem(id: string): MenuItem { return this.rootMenuItems.find(element => element['_id'] == id); } changeActiveRootMenuItem(item: MenuItem) { this.activeRootMenuId = item['_id']; this.activeRootMenu = item; this.childrenMenuItems = item.items; this.applyFilters(); } getPages() { this.subscriptions.push( this._helpContentService.getCommunityPagesByType(this.portal, '', this.properties.adminToolsAPIURL).subscribe( data => { let pages = data; this.allPages = []; this.menuRouteStatus = new Map(); for(let i = 0; i < pages.length; i++) { if(pages[i] && pages[i].name && pages[i].route) { this.allPages.push({value: pages[i].route, label: pages[i].name + (pages[i].isEnabled ? '' : ' [disabled]'), isEnabled: pages[i].isEnabled}); this.rootMenuItems.forEach(parent => { if(parent.route == pages[i].route) { this.menuRouteStatus.set(parent._id, pages[i].isEnabled); } if(parent.items) { const found = parent.items.find(child => child.route == pages[i].route); if(found) { this.menuRouteStatus.set(found._id, pages[i].isEnabled); } } }) } } }, error => this.handleError("Server error fetching pages", error) ) ); } public newPageWindow() { this.newPageWindowOpen = !this.newPageWindowOpen; this.pageForm = this._fb.group({ _id: this._fb.control(null), route: this._fb.control('', [Validators.required, StringUtils.validRoute(this.allPages, 'value')]), name: this._fb.control('', Validators.required), isEnabled: this._fb.control(true), portalType: this._fb.control(this.properties.adminToolsPortalType, Validators.required), portalPid: this._fb.control(this.portal), top: this._fb.control(true), bottom: this._fb.control(false), left: this._fb.control(false), right: this._fb.control(false), type: this._fb.control('html', Validators.required), entities: this._fb.control(['']) }); } public createPage() { if(!this.pageForm.value.route.startsWith('/')) { this.pageForm.value.route = '/'.concat(this.pageForm.value.route); } this.showLoading = true; this.subscriptions.push( this._helpContentService.savePage(this.pageForm.value, this.properties.adminToolsAPIURL).subscribe( page => { this.allPages.push({value: page.route, label: page.name}); UIkit.notification('Page ' + page.name + ' has been successfully created', { status: 'success', timeout: 6000, pos: 'bottom-right' }); this.newPageWindowOpen = !this.newPageWindowOpen; this.menuItemForm.get('route').setValue(page.route); this.menuItemForm.get('route').markAsDirty(); this.showLoading = false; }, error => this.handleError('System error creating page', error) ) ); } addValidatorForUrlOrRoute() { this.destroyTypeSubscription(); this.typeSub = this.menuItemForm.get('type').valueChanges.subscribe(value => { setTimeout(() => { this.menuItemForm.controls['route'].clearValidators(); this.menuItemForm.controls['url'].clearValidators(); if(value === "internal") { this.menuItemForm.controls['route'].setValidators([Validators.required]); } else if(value === "external") { this.menuItemForm.controls['url'].setValidators([Validators.required, StringUtils.urlValidator()]); } this.menuItemForm.controls['route'].updateValueAndValidity(); this.menuItemForm.controls['url'].updateValueAndValidity(); }, 0); }); } public newMenuItem(isChild: boolean = false) { this.menuItemForm = this._fb.group({ _id: this._fb.control(""), title: this._fb.control("",Validators.required), type: this._fb.control("",Validators.required), route: this._fb.control(""), url: this._fb.control(""), isEnabled: this._fb.control(""), isFeatured: this._fb.control(false), parentItemId: this._fb.control(isChild ? this.activeRootMenuId : null) }); this.isChild = isChild; this.addValidatorForUrlOrRoute(); this.menuItemsModalOpen('Create Menu Item', 'Create'); } public editMenuItem(menuItem: MenuItem, isChild: boolean = false) { this.menuItemForm = this._fb.group({ _id: this._fb.control(menuItem['_id']), title: this._fb.control(menuItem.title,Validators.required), type: this._fb.control(menuItem['type'],Validators.required), route: this._fb.control(menuItem.route, (menuItem['type'] == "internal") ? [Validators.required] : []), url: this._fb.control(menuItem.url, (menuItem['type'] == "external") ? [Validators.required, StringUtils.urlValidator()] : []), isFeatured: this._fb.control(menuItem.isFeatured), parentItemId: this._fb.control(menuItem['parentItemId']) }); this.isChild = isChild; if(this.isChild) { this.index = this.getActiveRootItem(this.activeRootMenuId).items.findIndex(value => value._id === menuItem['_id']); } else { this.index = this.rootMenuItems.findIndex(value => value._id === menuItem['_id']); } this.addValidatorForUrlOrRoute(); this.menuItemsModalOpen('Edit Menu Item', 'Save Changes'); } public confirmDeleteMenuItem(id: string, isChild: boolean = false) { this.selectedMenuItem = id; this.isChild = isChild; this.confirmModalOpen(); } private confirmModalOpen() { this.deleteModal.alertTitle = 'Delete Confirmation'; this.deleteModal.message = 'Are you sure you want to delete this menu item?'; this.deleteModal.okButtonText = 'Yes'; this.deleteModal.open(); } public confirmedDeleteMenuItem(data: any, isChild: boolean = false) { this.showLoading = true; this.subscriptions.push( this._helpContentService.deleteMenuItem(this.selectedMenuItem, this.portal).subscribe( _ => { this.deleteMenuItemFromArray(this.selectedMenuItem, this.isChild); UIkit.notification('Menu item have been successfully deleted', { status: 'success', timeout: 6000, pos: 'bottom-right' }); this.showLoading = false; }, error => this.handleError("Server error deleting menu item", error) ) ) } private deleteMenuItemFromArray(id: string, isChild: boolean = false) { if(isChild) { let i = this.getActiveRootItem(this.activeRootMenuId).items.findIndex(_ => _._id == id); this.getActiveRootItem(this.activeRootMenuId).items.splice(i, 1); } else { let i = this.rootMenuItems.findIndex(_ => _._id == id); this.rootMenuItems.splice(i, 1); this.changeActiveRootMenuItem(this.rootMenuItems[0]); } if(this.menuRouteStatus != null) { this.menuRouteStatus.delete(id); } this.applyFilters(); } private menuItemsModalOpen(title: string, yesBtn: string) { this.editModal.okButtonLeft = false; this.editModal.alertTitle = title; this.editModal.okButtonText = yesBtn; this.editModal.open(); } public menuItemSaveConfirmed(data: any) { this.destroyTypeSubscription(); this.showLoading = true; if(!this.menuItemForm.value._id) { this.subscriptions.push( this._helpContentService.saveMenuItem(this.menuItemForm.value, this.portal).subscribe( menuItem => { this.menuItemSavedSuccessfully(menuItem, true); UIkit.notification('Menu item ' + menuItem.title + ' has been successfully created', { status: 'success', timeout: 6000, pos: 'bottom-right' }); }, error => this.handleError("System error creating menu item", error) ) ) } else { this.subscriptions.push( this._helpContentService.updateMenuItem(this.menuItemForm.value, this.portal).subscribe( menuItem => { this.menuItemSavedSuccessfully(menuItem, false); UIkit.notification('Menu item ' + menuItem.title + ' has been successfully updated', { status: 'success', timeout: 6000, pos: 'bottom-right' }); }, error => this.handleError("System error updating menu item", error) ) ) } } public menuItemSavedSuccessfully(menuItem: MenuItem, isNew: boolean) { if(isNew) { if(this.isChild) { this.getActiveRootItem(this.activeRootMenuId).items.push(menuItem); } else { this.rootMenuItems.push(menuItem); } } else { if(this.isChild) { this.getActiveRootItem(this.activeRootMenuId).items[this.index] = menuItem; } else { this.rootMenuItems[this.index] = menuItem; } } if(this.menuRouteStatus != null) { const found = this.allPages.find(page => page.route == menuItem.route); if(found) { this.menuRouteStatus.set(menuItem._id, found.isEnabled); } } this.applyFilters(); this.showLoading = false; } handleError(message: string, error) { UIkit.notification(message, { status: 'danger', timeout: 6000, pos: 'bottom-right' }); console.log('Server responded: ' + error); this.showLoading = false; } public applyFilters() { this.childrenMenuItems = this.activeRootMenu.items.filter(item => item.title.toLowerCase().includes(this.searchText) || (item.url||'').toLowerCase().includes(this.searchText) || (item.route||'').toLowerCase().includes(this.searchText)); } public onSearchClose() { this.selectedKeyword = this.filterForm.get('keyword').value; } public reset() { this.selectedKeyword = null; this.searchInputComponent.reset(); } }