openaire-library/dashboard/menu/menu.component.ts

416 lines
14 KiB
TypeScript

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',
styles: [`
.z-index-2 {
z-index: 2;
}
`]
})
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<string,boolean> = 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(<Page>this.pageForm.value, this.properties.adminToolsAPIURL).subscribe(
page => {
this.allPages.push({value: page.route, label: page.name});
UIkit.notification('Page <b>' + page.name + '</b> has been <b>successfully created</b>', {
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 <b>successfully deleted</b>', {
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(<MenuItem>this.menuItemForm.value, this.portal).subscribe(
menuItem => {
this.menuItemSavedSuccessfully(menuItem, true);
UIkit.notification('Menu item <b>' + menuItem.title + '</b> has been <b>successfully created</b>', {
status: 'success',
timeout: 6000,
pos: 'bottom-right'
});
},
error => this.handleError("System error creating menu item", error)
)
)
} else {
this.subscriptions.push(
this._helpContentService.updateMenuItem(<MenuItem>this.menuItemForm.value, this.portal).subscribe(
menuItem => {
this.menuItemSavedSuccessfully(menuItem, false);
UIkit.notification('Menu item <b>' + menuItem.title + '</b> has been <b>successfully updated</b>', {
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();
}
}