add changes for pages and dynamic menus - dev only

This commit is contained in:
Alex Martzios 2022-01-11 12:05:40 +02:00
parent ae970394e9
commit 97fc6f033a
6 changed files with 168 additions and 74 deletions

View File

@ -4,12 +4,12 @@
<div *ngIf="!showLoading" class="uk-grid" uk-grid>
<div class="uk-width-1-1">
<ul *ngIf="!isPortalAdministrator" class="uk-subnav uk-subnav-pill uk-flex uk-flex-middle">
<li *ngFor="let item of rootMenuItems; let i=index" [class.uk-active]="activeRootMenu==item['_id']" class="uk-visible-toggle uk-position-relative uk-padding-remove-horizontal">
<li *ngFor="let item of rootMenuItems; let i=index" [class.uk-active]="activeRootMenuId==item['_id']" class="uk-visible-toggle uk-position-relative uk-padding-remove-horizontal">
<span>
<a (click)="activeRootMenu=item['_id']">
<a (click)="changeActiveRootMenuItem(item)">
<span class="title">{{item.title}}</span>
</a>
<span class="uk-invisible-hover uk-position-center-right color">
<span class="uk-invisible-hover uk-position-center-right color z-index-2">
<span class="clickable" uk-icon="more-vertical"></span>
<div #element uk-dropdown="mode: click; pos: bottom-right; offset: 10; delay-hide: 0; flip: false">
<ul class="uk-nav uk-dropdown-nav">
@ -30,7 +30,7 @@
<span class="uk-icon-button small portal-icon-button">
<icon name="add"></icon>
</span>
<span class="space uk-hidden-hover">
<span class="space" [class.uk-hidden-hover]="rootMenuItems.length != 0">
Create new root menu
</span>
</span>
@ -60,18 +60,18 @@
<loading></loading>
</div>
<div *ngIf="!showLoading">
<ul *ngIf='activeRootMenu' class="uk-list submenu-items">
<li *ngFor="let child of getActiveRootItem(activeRootMenu).items" class="uk-card uk-card-default uk-margin-bottom">
<ul *ngIf='activeRootMenuId' class="uk-list submenu-items">
<li *ngFor="let child of childrenMenuItems" class="uk-card uk-card-default uk-margin-bottom">
<div class="uk-grid uk-grid-divider uk-padding" uk-grid>
<div class="uk-width-4-5">
<div class="uk-grid uk-flex uk-flex-middle">
<div class="uk-width-expand uk-margin-medium-bottom">
{{child.title}}
</div>
<div *ngIf="child.url" class="uk-grid uk-width-1-1 uk-margin-left">
<div *ngIf="child.url && child.type == 'external'" class="uk-grid uk-width-1-1 uk-margin-left">
<span class="title uk-padding-remove">URL: </span><a href="{{child.url}}" target="_blank" class="uk-padding-remove uk-margin-left">{{child.url}}</a>
</div>
<div *ngIf="child.route" class="uk-grid uk-width-1-1 uk-margin-left">
<div *ngIf="child.route && child.type == 'internal'" class="uk-grid uk-width-1-1 uk-margin-left">
<span class="title uk-padding-remove">Route: </span><span class="uk-padding-remove uk-margin-left">{{child.route}}</span>
</div>
</div>
@ -93,7 +93,7 @@
</div>
</li>
</ul>
<div *ngIf="!getActiveRootItem(activeRootMenu) || !getActiveRootItem(activeRootMenu).items || getActiveRootItem(activeRootMenu).items.length == 0"
<div *ngIf="childrenMenuItems.length == 0"
class="uk-card uk-card-default uk-padding-large uk-text-center uk-margin-bottom uk-text-bold">
<div>No menu items found</div>
</div>
@ -104,9 +104,9 @@
[okDisabled]="menuItemForm && (menuItemForm.invalid || !menuItemForm.dirty)">
<form *ngIf="menuItemForm" [formGroup]="menuItemForm" class="uk grid uk-child-width-1-1" uk-grid>
<div dashboard-input [formInput]="menuItemForm.get('title')" type="text" label="Name" placeholder="Write a name"></div>
<div dashboard-input [formInput]="menuItemForm.get('type')" type="select" label="Type" placeholder="Choose a type" [options]="typeOptions"></div>
<div dashboard-input [formInput]="menuItemForm.get('type')" type="select" label="Type" placeholder="Choose a type" [options]="getTypeOptions()"></div>
<!-- Workflow for EXTERNAL -->
<div dashboard-input *ngIf="menuItemForm.get('type').value === 'external'" [formInput]="menuItemForm.get('url')" type="URL" label="URL" placeholder="Write a URL"></div>
<div dashboard-input *ngIf="menuItemForm.get('type').value === 'external'" [formInput]="menuItemForm.get('url')" type="URL" label="URL *" placeholder="Write a URL"></div>
<!-- Workflow for INTERNAL -->
<div *ngIf="menuItemForm.get('type').value === 'internal'">
<div class="uk-text-center">Select one of the pages</div>
@ -118,17 +118,17 @@
<button (click)="newPageWindow()" class="uk-close uk-icon uk-float-right" uk-close></button>
<h6 class="uk-text-bold uk-margin-remove-top">Create New Page</h6>
</div>
<form *ngIf="menuItemForm" [formGroup]="menuItemForm" class="uk grid uk-child-width-1-1" uk-grid>
<div dashboard-input [formInput]="menuItemForm.get('title')" type="text" label="Name" placeholder="Write a name"></div>
<div dashboard-input [formInput]="menuItemForm.get('title')" type="text" label="Route" placeholder="Write a route"></div>
<div>
<form *ngIf="pageForm" [formGroup]="pageForm" class="uk grid uk-child-width-1-1" uk-grid>
<div dashboard-input [formInput]="pageForm.get('name')" type="text" label="Name" placeholder="Write a name"></div>
<div dashboard-input [formInput]="pageForm.get('route')" type="text" label="Route" placeholder="Write a route"></div>
<!-- <div>
<div class="uk-text-bold uk-form-label uk-margin-small-bottom">Enable/disable</div>
<mat-slide-toggle
<mat-slide-toggle [checked]="pageForm.get('isEnabled')"
uk-tooltip="title:<div class='uk-padding-small uk-width-large'><div class='uk-text-bold '>Disable a page to hide it from community dashboard portal.</div><div class=' uk-margin-top'>If the page is disabled, a message 'Can't find that page' will appear in case the url of that page is loaded. If the disabled page belongs to the menu, the link will be removed from menu, too.</div></div>">
</mat-slide-toggle>
</div>
</div> -->
<div class="uk-flex uk-flex-right">
<button class="uk-button uk-button-default">Create Page</button>
<button class="uk-button uk-button-default" (click)="createPage()">Create Page</button>
</div>
</form>
</div>

View File

@ -6,19 +6,26 @@ 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} from "rxjs";
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 {CheckMenuItem, MenuItem} from '../../sharedComponents/menu';
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 {
@ -26,10 +33,13 @@ export class MenuComponent implements OnInit {
@ViewChild('editModal') editModal: AlertModal;
@ViewChild('deleteModal') deleteModal: AlertModal;
public activeRootMenu: string;
public activeRootMenuId: string;
public activeRootMenu: MenuItem;
public childrenMenuItems: MenuItem[] = [];
private index: number;
public menuItemForm: FormGroup;
public pageForm: FormGroup;
public rootMenuItems = [];
public menuItems = [];
public allPages = [];
@ -44,9 +54,12 @@ export class MenuComponent implements OnInit {
public showLoading = true;
public isPortalAdministrator = null;
public filterForm: FormGroup;
public typeOptions = [
public typeOptions: Option[] = [
{label: 'Internal Link', value: 'internal'},
{label: 'External Link', value: 'external'}
{label: 'External Link', value: 'external'},
]
public rootOnlyTypeOptions: Option[] = [
{label: 'No Action', value: 'noAction'}
]
public keyword: string = '';
@ -55,6 +68,7 @@ export class MenuComponent implements OnInit {
public properties: EnvProperties = properties;
private subscriptions: any[] = [];
private typeSub: Subscription = null;
constructor(private element: ElementRef, private route: ActivatedRoute,
private _router: Router, private title: Title,
@ -94,15 +108,23 @@ export class MenuComponent implements OnInit {
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.activeRootMenu = data[0]['_id'];
// this.activeRootMenuId = data[0]['_id'];
this.changeActiveRootMenuItem(data[0]);
}
},
err => console.error("Server error fetching menu items: ", err)
@ -110,10 +132,25 @@ export class MenuComponent implements OnInit {
);
}
getTypeOptions() {
if(this.isChild) {
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.getAllPages(this.properties.adminToolsAPIURL,this.portal).subscribe(
@ -133,19 +170,71 @@ export class MenuComponent implements OnInit {
public newPageWindow() {
this.newPageWindowOpen = !this.newPageWindowOpen;
this.pageForm = this._fb.group({
_id: this._fb.control(null),
route: this._fb.control('', Validators.required),
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);
}
)
);
}
addValidatorForUrlOrRoute() {
this.destroyTypeSubscription();
this.typeSub = this.menuItemForm.get('type').valueChanges.subscribe(value => {
setTimeout(() => {
// console.log(value);
if(value === "internal") {
this.menuItemForm.controls['route'].setValidators([Validators.required]);
this.menuItemForm.controls['route'].updateValueAndValidity();
} else if(value === "external") {
this.menuItemForm.controls['url'].setValidators([Validators.required]);
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(""),
type: this._fb.control("",Validators.required),
route: this._fb.control(""),
url: this._fb.control(""),
isEnabled: this._fb.control(""),
parentItemId: this._fb.control(isChild ? this.activeRootMenu : null)
parentItemId: this._fb.control(isChild ? this.activeRootMenuId : null)
});
this.isChild = isChild;
this.addValidatorForUrlOrRoute();
this.menuItemsModalOpen('Create Menu Item', 'Create');
}
@ -153,21 +242,21 @@ export class MenuComponent implements OnInit {
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']),
type: this._fb.control(menuItem['type'],Validators.required),
route: this._fb.control(menuItem.route),
url: this._fb.control(menuItem.url),
parentItemId: this._fb.control(menuItem['parentItemId'])
});
this.isChild = isChild;
if(this.isChild) {
this.index = this.getActiveRootItem(this.activeRootMenu).items.findIndex(value => value._id === menuItem['_id']);
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;
@ -202,12 +291,14 @@ export class MenuComponent implements OnInit {
private deleteMenuItemFromArray(id: string, isChild: boolean = false) {
if(isChild) {
let i = this.getActiveRootItem(this.activeRootMenu).items.findIndex(_ => _._id == id);
this.getActiveRootItem(this.activeRootMenu).items.splice(i, 1);
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]);
}
this.applyFilters();
}
private menuItemsModalOpen(title: string, yesBtn: string) {
@ -220,6 +311,7 @@ export class MenuComponent implements OnInit {
}
public menuItemSaveConfirmed(data: any) {
this.destroyTypeSubscription();
this.showLoading = true;
if(!this.menuItemForm.value._id) {
this.subscriptions.push(
@ -253,23 +345,23 @@ export class MenuComponent implements OnInit {
public menuItemSavedSuccessfully(menuItem: MenuItem, isNew: boolean) {
if(isNew) {
if(this.isChild) {
this.getActiveRootItem(this.activeRootMenu).items.push(menuItem);
this.getActiveRootItem(this.activeRootMenuId).items.push(menuItem);
} else {
this.rootMenuItems.push(menuItem);
}
} else {
if(this.isChild) {
this.getActiveRootItem(this.activeRootMenu).items[this.index] = menuItem;
this.getActiveRootItem(this.activeRootMenuId).items[this.index] = menuItem;
} else {
this.rootMenuItems[this.index] = menuItem;
}
}
this.applyFilters();
this.showLoading = false;
}
public applyFilters() {
console.log(this.searchText);
this.getActiveRootItem(this.activeRootMenu).items = this.getActiveRootItem(this.activeRootMenu).items.filter(item => item.title.toLowerCase().includes(this.searchText));
this.childrenMenuItems = this.activeRootMenu.items.filter(item => item.title.toLowerCase().includes(this.searchText));
}
public onSearchClose() {

View File

@ -80,7 +80,7 @@
<span class="title">Portal type: </span>{{check.page.portalType}}
</div>
</div>
<div *ngIf="isPortalAdministrator" class="uk-width-1-4">
<div *ngIf="isPortalAdministrator || (check.page.portalType == properties.adminToolsPortalType && check.page.portalPid == portal)" class="uk-width-1-4">
<div class="title uk-margin-medium-bottom">Actions</div>
<div class="actions" href="#">
<i class="clickable " (click)="editPage(i)" uk-icon="pencil"></i>
@ -136,39 +136,42 @@
type="text" placeholder="Write a name"
label="Page Name">
</div>
<div dashboard-input [formInput]="pageForm.get('type')"
type="select" placeholder="Choose a page Type"
label="Type" [options]="typeOptions">
</div>
<div dashboard-input [formInput]="pageForm.get('entities')" placeholder="Add an entity"
type="chips" [options]="allEntities" label="Entities">
</div>
<div dashboard-input type="select" label="Portal Type" placeholder="Choose a type"
[formInput]="pageForm.get('portalType')" [options]="portalUtils.portalTypes"></div>
<div class="form-group">
<div class="uk-form-label uk-text-bold uk-margin-small-bottom"> Select if this page have helptext at:</div>
<div class="uk-grid uk-grid-small uk-child-width-1-4" uk-grid>
<div dashboard-input [formInput]="pageForm.get('top')"
type="checkbox"
label="Top">
</div>
<div dashboard-input [formInput]="pageForm.get('right')"
type="checkbox"
label="Right">
</div>
<div dashboard-input [formInput]="pageForm.get('bottom')"
type="checkbox"
label="Bottom">
</div>
<div dashboard-input [formInput]="pageForm.get('left')"
type="checkbox"
label="Left">
</div>
</div>
<label class="uk-text-danger">
By disabling a position, all contents in this position will be deleted.
</label>
</div>
<ng-template [ngIf]="isPortalAdministrator">
<div dashboard-input [formInput]="pageForm.get('type')"
type="select" placeholder="Choose a page Type"
label="Type" [options]="typeOptions">
</div>
<div dashboard-input [formInput]="pageForm.get('entities')" placeholder="Add an entity"
type="chips" [options]="allEntities" label="Entities">
</div>
<div dashboard-input type="select" label="Portal Type" placeholder="Choose a type"
[formInput]="pageForm.get('portalType')" [options]="portalUtils.portalTypes">
</div>
<div class="form-group">
<div class="uk-form-label uk-text-bold uk-margin-small-bottom"> Select if this page have helptext at:</div>
<div class="uk-grid uk-grid-small uk-child-width-1-4" uk-grid>
<div dashboard-input [formInput]="pageForm.get('top')"
type="checkbox"
label="Top">
</div>
<div dashboard-input [formInput]="pageForm.get('right')"
type="checkbox"
label="Right">
</div>
<div dashboard-input [formInput]="pageForm.get('bottom')"
type="checkbox"
label="Bottom">
</div>
<div dashboard-input [formInput]="pageForm.get('left')"
type="checkbox"
label="Left">
</div>
</div>
<label class="uk-text-danger">
By disabling a position, all contents in this position will be deleted.
</label>
</div>
</ng-template>
</form>
</modal-alert>

View File

@ -246,6 +246,7 @@ export class PagesComponent implements OnInit {
name: this._fb.control(page.name, Validators.required),
isEnabled: this._fb.control(page.isEnabled),
portalType: this._fb.control(page.portalType, Validators.required),
portalPid: this._fb.control(page.portalPid),
top: this._fb.control(page.top),
bottom: this._fb.control(page.bottom),
left: this._fb.control(page.left),
@ -271,6 +272,7 @@ export class PagesComponent implements OnInit {
name: this._fb.control('', Validators.required),
isEnabled: this._fb.control(true),
portalType: this._fb.control('', Validators.required),
portalPid: this._fb.control(null),
top: this._fb.control(true),
bottom: this._fb.control(true),
left: this._fb.control(true),

View File

@ -1,6 +1,7 @@
export class MenuItem {
_id: string = ""; // for root menu in order to close the dropdown when clicked
title: string = "";
type: string = "internal";
url: string = ""; // external url
route: string = ""; // internal url - using angular routing and components
routeActive: string = ""; // route to check if it is active
@ -82,8 +83,3 @@ export class SideMenuItem {
items: RootMenuItem[] = [];
ukIcon: string = '';
}
export interface CheckMenuItem {
menuItem: MenuItem;
checked: boolean;
}

View File

@ -7,6 +7,7 @@ export interface Page {
type: string;
isEnabled: boolean;
portalType: string;
portalPid: string;
entities: Entity[] | string[];
top: boolean;
bottom: boolean;