diff --git a/smp-angular/src/app/app.routes.ts b/smp-angular/src/app/app.routes.ts index 7942823f94785b6670652e1ad1eb8ce56c688dc4..698dd2eabee4e85b1c368c5139517970b597b990 100644 --- a/smp-angular/src/app/app.routes.ts +++ b/smp-angular/src/app/app.routes.ts @@ -19,6 +19,7 @@ import {EditResourceComponent} from "./edit/edit-resources/edit-resource.compone import {ResourceDocumentPanelComponent} from "./edit/edit-resources/resource-document-panel/resource-document-panel.component"; import {SubresourceDocumentPanelComponent} from "./edit/edit-resources/subresource-document-panel/subresource-document-panel.component"; import {authorizeChildSystemAdminGuard} from "./guards/authorize-child-system-admin.guard"; +import {activateChildResourceGuard} from "./guards/activate-child-document.guard"; const appRoutes: Routes = [ @@ -34,11 +35,10 @@ const appRoutes: Routes = [ {path: 'edit-group', component: EditGroupComponent, canDeactivate: [dirtyDeactivateGuard]}, { path: 'edit-resource', - canDeactivate: [dirtyDeactivateGuard], children: [ - {path: 'resource-document', component: ResourceDocumentPanelComponent, canDeactivate: [dirtyDeactivateGuard]}, - {path: 'subresource-document', component: SubresourceDocumentPanelComponent, canDeactivate: [dirtyDeactivateGuard]}, + {path: 'resource-document', canActivate: [activateChildResourceGuard], component: ResourceDocumentPanelComponent, canDeactivate: [dirtyDeactivateGuard]}, + {path: 'subresource-document', canActivate: [activateChildResourceGuard], component: SubresourceDocumentPanelComponent, canDeactivate: [dirtyDeactivateGuard]}, {path: '', component: EditResourceComponent, canDeactivate: [dirtyDeactivateGuard]}, ] } diff --git a/smp-angular/src/app/common/dialogs/password-change-dialog/password-change-dialog.component.html b/smp-angular/src/app/common/dialogs/password-change-dialog/password-change-dialog.component.html index a91d88f85fb2ab69ff00a78559b206a039ff1318..1c85aec01e7546083c530e77522e72b8c52fdb34 100644 --- a/smp-angular/src/app/common/dialogs/password-change-dialog/password-change-dialog.component.html +++ b/smp-angular/src/app/common/dialogs/password-change-dialog/password-change-dialog.component.html @@ -1,5 +1,5 @@ <h2 mat-dialog-title>{{formTitle}}</h2> -<mat-dialog-content style="width:500px"> +<mat-dialog-content style="width:500px;padding-bottom: 0"> <div *ngIf="message" [ngClass]="{ 'alert-message': message, 'alert-message-success': messageType === 'success', 'alert-message-error':messageType === 'error' }" @@ -8,14 +8,14 @@ {{message}} </div> <form [formGroup]="dialogForm"> - <div style="display:flex;flex-direction: column"> + <div style="display:flex;flex-direction: column;"> <mat-form-field style="width:100%"> <mat-label>Change password for Username</mat-label> <input matInput formControlName="username" id="un_id" readonly="true"> </mat-form-field> - <div class="password-panel" style="display: flex;flex-direction: column"> + <div class="password-panel" style="display: flex;flex-direction: column;"> <mat-form-field *ngIf="showCurrentPasswordField" style="width:100%"> <mat-label>{{getPasswordTitle}}</mat-label> @@ -48,11 +48,12 @@ </mat-form-field> </div> + <div class="required-fields">* required fields</div> </div> </form> </mat-dialog-content> -<div class="required-fields">* required fields</div> + <mat-dialog-actions> <button id="changeCurrentUserPasswordButton" mat-raised-button color="primary" (click)="changeCurrentUserPassword()" diff --git a/smp-angular/src/app/edit/edit-resources/resource-document-panel/resource-document-panel.component.ts b/smp-angular/src/app/edit/edit-resources/resource-document-panel/resource-document-panel.component.ts index 83c317d50022603674a39f4ab1212110b8aeab67..ceebfd4ad02f521c6606b8a2465f0cb5f3c90eca 100644 --- a/smp-angular/src/app/edit/edit-resources/resource-document-panel/resource-document-panel.component.ts +++ b/smp-angular/src/app/edit/edit-resources/resource-document-panel/resource-document-panel.component.ts @@ -79,9 +79,8 @@ export class ResourceDocumentPanelComponent implements AfterViewInit, BeforeLeav @Input() set resource(value: ResourceRo) { this._resource = value; - if (!this._resource) { - this.navigationService.reset(); + this.navigationService.navigateToHome(); return; } diff --git a/smp-angular/src/app/guards/activate-child-document.guard.ts b/smp-angular/src/app/guards/activate-child-document.guard.ts new file mode 100644 index 0000000000000000000000000000000000000000..c244d19497c3eeb00702807f818c517a37ed2137 --- /dev/null +++ b/smp-angular/src/app/guards/activate-child-document.guard.ts @@ -0,0 +1,20 @@ +import {inject} from '@angular/core'; +import {SecurityService} from '../security/security.service'; +import {AlertMessageService} from "../common/alert-message/alert-message.service"; +import {Authority} from "../security/authority.model"; +import {ActivatedRouteSnapshot, CanActivateChildFn, CanActivateFn, RouterStateSnapshot} from "@angular/router"; +import {EditResourceService} from "../edit/edit-resources/edit-resource.service"; + + +export const activateChildResourceGuard: CanActivateFn = + (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) => { + console.log("Is user is authorized"); + const alertService: AlertMessageService = inject(AlertMessageService); + const editResourceService: EditResourceService = inject(EditResourceService); + + let resourceUndefined:boolean = !editResourceService.selectedResource; + if (resourceUndefined) { + alertService.error('Resource/Subresource is not selected! Please select resource from resource edit panel.', true); + } + return !resourceUndefined; + }; diff --git a/smp-angular/src/app/login/login.component.html b/smp-angular/src/app/login/login.component.html index 36416885fdddc3e965cc831a02cbecf73946a21e..0f96e24f200a87de1d47bfe86def7b78f4607bf1 100644 --- a/smp-angular/src/app/login/login.component.html +++ b/smp-angular/src/app/login/login.component.html @@ -33,7 +33,6 @@ <mat-icon>input</mat-icon> <span> Login</span> </button> - </form> </mat-card-content> </mat-card> diff --git a/smp-angular/src/app/security/security.service.ts b/smp-angular/src/app/security/security.service.ts index 464a3ecfcd6ed06d1e949379239b1a8424767d2d..f5f4c0b50d0fa967d398304272d356e01612152a 100644 --- a/smp-angular/src/app/security/security.service.ts +++ b/smp-angular/src/app/security/security.service.ts @@ -166,7 +166,7 @@ export class SecurityService { return localStorage.getItem(this.LOCAL_STORAGE_KEY_CURRENT_USER); } - private clearLocalStorage() { + public clearLocalStorage() { localStorage.removeItem(this.LOCAL_STORAGE_KEY_CURRENT_USER); } diff --git a/smp-angular/src/app/window/sidenav/nav-tree/nav-tree.component.html b/smp-angular/src/app/window/sidenav/nav-tree/nav-tree.component.html index b7239becea5365023d60e8aa185ca52bd0425a34..132776fe69ccff47632b989a5a19afd280dc85a9 100644 --- a/smp-angular/src/app/window/sidenav/nav-tree/nav-tree.component.html +++ b/smp-angular/src/app/window/sidenav/nav-tree/nav-tree.component.html @@ -2,8 +2,8 @@ [treeControl]="treeControl" class="nav-tree"> <!-- Leaf nodes --> - <mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle> - <li class="mat-tree-node nav-tree-leaf" [ngClass]="{ 'navigation-selected': navigationModel.selected === node}"> + <mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle> + <li *ngIf="!node.transient" class="mat-tree-node nav-tree-leaf" [ngClass]="{ 'navigation-selected': navigationModel.selected === node}"> <button [id]="node.code+'Button'" mat-menu-item (click)="menuClickHandler(node)"> <mat-icon *ngIf="node.icon">{{node.icon}}</mat-icon> <span *ngIf="fullMenu">{{node.name}}</span> diff --git a/smp-angular/src/app/window/sidenav/navigation-model.service.ts b/smp-angular/src/app/window/sidenav/navigation-model.service.ts index fc96ae3a53a21e6f0ba74d28113de9ec89f7ae48..ec61e088a7c09706d3f92eb49d3e4a14ac702772 100644 --- a/smp-angular/src/app/window/sidenav/navigation-model.service.ts +++ b/smp-angular/src/app/window/sidenav/navigation-model.service.ts @@ -5,8 +5,9 @@ import {SecurityEventService} from "../../security/security-event.service"; import {SmpConstants} from "../../smp.constants"; import {HttpClient} from "@angular/common/http"; import {User} from "../../security/user.model"; -import {Router} from "@angular/router"; +import {NavigationEnd, Router} from "@angular/router"; import {Observable, Subject} from "rxjs"; +import {filter, map} from "rxjs/operators"; /** * The smp navigation tree @@ -50,7 +51,6 @@ export interface NavigationNode { tooltip?: string; routerLink?: string; children?: NavigationNode[]; - selected?: boolean; transient?: boolean; // if true then node must be ignored } @@ -58,6 +58,20 @@ export interface NavigationNode { @Injectable() export class NavigationService extends MatTreeNestedDataSource<NavigationNode> { + private sub = this.router.events + .pipe( + filter(event => event instanceof NavigationEnd), + map(event => event as NavigationEnd), // appease typescript + ) + .subscribe( + event => { + console.log('NavigationService: ' + event.url) + let path: string[] = event.url.split('/'); + this.setNavigationTreeByPath(path, this.rootNode); + } + ); + + private selectedPathSubject = new Subject<NavigationNode[]>(); selected: NavigationNode; @@ -93,8 +107,11 @@ export class NavigationService extends MatTreeNestedDataSource<NavigationNode> { this.refreshNavigationTree(); } ); + } - + ngOnDestroy() { + console.log('>> STOP listening to route events '); + this.sub.unsubscribe(); } select(node: NavigationNode) { @@ -325,16 +342,45 @@ export class NavigationService extends MatTreeNestedDataSource<NavigationNode> { } public navigateToLogin(): void { + this.securityService.clearLocalStorage() this.reset(); - this.router.navigate(['/login'], {queryParams: {returnUrl: this.router.url}}); - this.router.parseUrl('/login'); + let node: NavigationNode = this.createNew(); + this.rootNode.children.push(node); + this.select(node); + + //this.reset(); + //this.router.navigate(['/login'], {queryParams: {returnUrl: this.router.url}}); + //this.router.parseUrl('/login'); } public navigateToHome(): void { this.select(this.rootNode); } + public navigateUp(): void { + this.selectedPath?.pop(); + if (this.selectedPath?.length > 0) { + this.select(this.selectedPath[this.selectedPath.length - 1]); + } + + + } + public navigateToUserDetails(): void { this.setNavigationTreeByPath(['user-settings', 'user-profile'], this.rootNode) } + + + public createNew(): NavigationNode { + return { + code: "login", + icon: "login", + name: "Login", + routerLink: "login", + selected: true, + tooltip: "", + transient: true, + } + } + } diff --git a/smp-angular/src/app/window/toolbar/toolbar.component.html b/smp-angular/src/app/window/toolbar/toolbar.component.html index d8db49ff050aae8be0f42bf20c362a39931cb3d5..641a16c4ed5cd9bd5c45a99b552a6471f37f2eb7 100644 --- a/smp-angular/src/app/window/toolbar/toolbar.component.html +++ b/smp-angular/src/app/window/toolbar/toolbar.component.html @@ -6,8 +6,8 @@ [attr.width]="fullMenu ? '180px' : '50px'"/> </div> <span class="window-toolbar-spacer"></span> - <a id="login_id" class="window-toolbar-item" *ngIf="!currentUser" [routerLink]="['/login']" - (click)="clearWarning()"> Login </a> + <a id="login_id" class="window-toolbar-item" *ngIf="!currentUser" + (click)="navigateToLogin()"> Login </a> <span class="window-toolbar-item" *ngIf="currentUser">{{currentUserRoleDescription}}: {{currentUser}} </span> <button class="window-toolbar-item" [mat-menu-trigger-for]="settingsMenu" id="settingsmenu_id" matTooltip="Menu"> diff --git a/smp-angular/src/app/window/toolbar/toolbar.component.ts b/smp-angular/src/app/window/toolbar/toolbar.component.ts index cc0bc9a2262734dd1d025e92949b27f052ce9199..2cd76be9767572c48599e4281de798f5736d5903 100644 --- a/smp-angular/src/app/window/toolbar/toolbar.component.ts +++ b/smp-angular/src/app/window/toolbar/toolbar.component.ts @@ -56,6 +56,10 @@ export class ToolbarComponent { return this.securityService.isCurrentUserInRole([Authority.SERVICE_GROUP_ADMIN]); } + navigateToLogin(): void { + this.clearWarning(); + this.navigation.navigateToLogin(); + } logout(event: Event): void { event.preventDefault(); diff --git a/smp-angular/src/styles.css b/smp-angular/src/styles.css index 2b2cd3c2a693af292d92b119599a593ce3723196..cee796e558d422b19a1a79295cf5c3c0d9eee7eb 100644 --- a/smp-angular/src/styles.css +++ b/smp-angular/src/styles.css @@ -112,6 +112,7 @@ ngx-datatable span:before { text-align: left; font-size: 65%; margin: 0 3px; + padding: 0; } .mat-toolbar-multiple-rows {