From eb739eeed36a82130276ad17757760c08a92ffa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Kov=C3=A1=C4=8Dik?= Date: Tue, 20 May 2025 07:22:40 +0200 Subject: [PATCH 1/4] [NAE-2072] Workspaces - add changing workspaces to doubledrawer menu --- .../authentication/models/user.transformer.ts | 1 + .../abstract-navigation-double-drawer.ts | 11 +++++- .../engine-endpoint/user-resource.service.ts | 13 +++++++ .../src/lib/user/models/iuser.ts | 2 ++ .../src/lib/user/models/user.ts | 1 + .../src/lib/user/models/workspace.ts | 5 +++ .../src/lib/user/services/user.service.ts | 35 +++++++++++++++++-- .../mock-authentication-method-service.ts | 2 +- .../mocks/mock-authentication.service.ts | 3 +- .../tests/mocks/mock-user-resource.service.ts | 2 +- .../navigation-double-drawer.component.html | 15 ++++++++ 11 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 projects/netgrif-components-core/src/lib/user/models/workspace.ts diff --git a/projects/netgrif-components-core/src/lib/authentication/models/user.transformer.ts b/projects/netgrif-components-core/src/lib/authentication/models/user.transformer.ts index 8a61e5ddde..5f8ea055f7 100644 --- a/projects/netgrif-components-core/src/lib/authentication/models/user.transformer.ts +++ b/projects/netgrif-components-core/src/lib/authentication/models/user.transformer.ts @@ -21,6 +21,7 @@ export class UserTransformer implements Transformer { user.email, user.name, user.surname, + user.workspaceId, this.transformAuthorities(user.authorities), user.processRoles, groups, diff --git a/projects/netgrif-components-core/src/lib/navigation/navigation-double-drawer/abstract-navigation-double-drawer.ts b/projects/netgrif-components-core/src/lib/navigation/navigation-double-drawer/abstract-navigation-double-drawer.ts index 10f2b20684..e3cefc928e 100644 --- a/projects/netgrif-components-core/src/lib/navigation/navigation-double-drawer/abstract-navigation-double-drawer.ts +++ b/projects/netgrif-components-core/src/lib/navigation/navigation-double-drawer/abstract-navigation-double-drawer.ts @@ -3,7 +3,7 @@ import {Component, Input, OnDestroy, OnInit, TemplateRef} from '@angular/core'; import {MatDrawerMode} from '@angular/material/sidenav'; import {ActivatedRoute, Router} from '@angular/router'; import {ResizeEvent} from 'angular-resizable-element'; -import {Observable, of, Subscription} from 'rxjs'; +import {Observable, of, Subject, Subscription} from 'rxjs'; import {map} from 'rxjs/operators'; import {RoleAccess, View} from '../../../commons/schema'; import {AccessService} from '../../authorization/permission/access.service'; @@ -117,6 +117,7 @@ export abstract class AbstractNavigationDoubleDrawerComponent implements OnInit, }; protected _childCustomViews: { [uri: string]: { [key: string]: NavigationItem } }; + public userWorkspaces$: Observable>; protected constructor(protected _router: Router, protected _activatedRoute: ActivatedRoute, @@ -229,6 +230,14 @@ export abstract class AbstractNavigationDoubleDrawerComponent implements OnInit, return this._configRightMenu; } + setWorkspace(workspace: string) { + this._userService.changeWorkspace(workspace); + } + + activeWorkspace() { + return this._userService.user.workspaceId; + } + toggleMenu() { this.toggleRightMenu(); if (this.allClosable) { diff --git a/projects/netgrif-components-core/src/lib/resources/engine-endpoint/user-resource.service.ts b/projects/netgrif-components-core/src/lib/resources/engine-endpoint/user-resource.service.ts index 90f9d6d02e..9d5089ac31 100644 --- a/projects/netgrif-components-core/src/lib/resources/engine-endpoint/user-resource.service.ts +++ b/projects/netgrif-components-core/src/lib/resources/engine-endpoint/user-resource.service.ts @@ -10,6 +10,7 @@ import {Page} from '../interface/page'; import {GroupsInterface} from '../interface/group'; import {AbstractResourceService} from '../abstract-endpoint/abstract-resource.service'; import {UserResource} from '../interface/user-resource'; +import {Workspace} from "../../user/models/workspace"; @Injectable({ providedIn: 'root' @@ -69,6 +70,18 @@ export class UserResourceService extends AbstractResourceService { .pipe(map(r => this.getResourcePage(r, 'users'))); } + /** + * Get all workspaces + * + * **Request Type:** GET + * + * **Request URL:** {{baseUrl}}/api/user/workspaces + */ + public getAllWorkspaces(params?: Params): Observable> { + return this._resourceProvider.get$('user/workspaces', this.SERVER_URL, params) + .pipe(map(r => this.changeType(r, undefined))); + } + /** * Get all users with specified roles * diff --git a/projects/netgrif-components-core/src/lib/user/models/iuser.ts b/projects/netgrif-components-core/src/lib/user/models/iuser.ts index 30c2696177..284bc5b588 100644 --- a/projects/netgrif-components-core/src/lib/user/models/iuser.ts +++ b/projects/netgrif-components-core/src/lib/user/models/iuser.ts @@ -16,4 +16,6 @@ export interface IUser { * **Example:** Netgrif */ surname: string; + + workspaceId: string; } diff --git a/projects/netgrif-components-core/src/lib/user/models/user.ts b/projects/netgrif-components-core/src/lib/user/models/user.ts index 4f3a09b50e..4e35f2e69f 100644 --- a/projects/netgrif-components-core/src/lib/user/models/user.ts +++ b/projects/netgrif-components-core/src/lib/user/models/user.ts @@ -11,6 +11,7 @@ export class User implements IUser { public email: string, public firstName: string, public lastName: string, + public workspaceId: string, public authorities: Array, public roles: Array, public groups?: Array, diff --git a/projects/netgrif-components-core/src/lib/user/models/workspace.ts b/projects/netgrif-components-core/src/lib/user/models/workspace.ts new file mode 100644 index 0000000000..e5572da65e --- /dev/null +++ b/projects/netgrif-components-core/src/lib/user/models/workspace.ts @@ -0,0 +1,5 @@ + +export interface Workspace { + id: string; + defaultWorkspace: boolean; +} diff --git a/projects/netgrif-components-core/src/lib/user/services/user.service.ts b/projects/netgrif-components-core/src/lib/user/services/user.service.ts index e122a07d17..480bc398b9 100644 --- a/projects/netgrif-components-core/src/lib/user/services/user.service.ts +++ b/projects/netgrif-components-core/src/lib/user/services/user.service.ts @@ -1,5 +1,5 @@ import {Injectable, OnDestroy} from '@angular/core'; -import {Observable, ReplaySubject, Subscription} from 'rxjs'; +import {BehaviorSubject, Observable, ReplaySubject, Subscription} from 'rxjs'; import {ProcessRole} from '../../resources/interface/process-role'; import {User} from '../models/user'; import {Credentials} from '../../authentication/models/credentials'; @@ -12,6 +12,7 @@ import {HttpErrorResponse} from '@angular/common/http'; import {SessionService} from '../../authentication/session/services/session.service'; import {UserResource} from '../../resources/interface/user-resource'; import {AnonymousService} from '../../authentication/anonymous/anonymous.service'; +import {Workspace} from "../models/workspace"; @Injectable({ providedIn: 'root' @@ -25,6 +26,7 @@ export class UserService implements OnDestroy { protected _subAuth: Subscription; protected _subAnonym: Subscription; private _publicLoadCalled: boolean; + protected _workspaces: BehaviorSubject>; public readonly GLOBAL_ROLE_PREFIX = 'global_'; @@ -66,6 +68,14 @@ export class UserService implements OnDestroy { return this._userChange$.asObservable(); } + get workspaces() { + return this._workspaces.getValue(); + } + + get workspaces$(): Observable> { + return this._workspaces.asObservable(); + } + get anonymousUser(): User { return this.anonymousUser; } @@ -177,7 +187,7 @@ export class UserService implements OnDestroy { } protected emptyUser() { - return new User('', '', '', '', [], [], [], []); + return new User('', '', '', '', '', [], [], [], []); } protected loadUser(): void { @@ -186,6 +196,7 @@ export class UserService implements OnDestroy { const backendUser = {...user, id: user.id.toString()}; this._user = this._userTransform.transform(backendUser); this.publishUserChange(); + this.loadWorkspaces(); } }, error => { if (error instanceof HttpErrorResponse && error.status === 401) { @@ -210,6 +221,26 @@ export class UserService implements OnDestroy { }); } + public loadWorkspaces() { + this._userResource.getAllWorkspaces().pipe(take(1)).subscribe(workspaces => { + if (workspaces) { + this._workspaces.next(workspaces) + } + }, error => { + this._log.error('Loading workspaces has failed!', error); + }); + } + + public changeWorkspace(workspaceId: string) { + this._userResource.updateUser(this.user.id, {workspaceId}).subscribe(user => { + if (user) { + const backendUser = {...user, id: user.id.toString()}; + this._user = this._userTransform.transform(backendUser); + this.publishUserChange(); + } + }); + } + public clearUser() { this._user = this.emptyUser(); } diff --git a/projects/netgrif-components-core/src/lib/utility/tests/mocks/mock-authentication-method-service.ts b/projects/netgrif-components-core/src/lib/utility/tests/mocks/mock-authentication-method-service.ts index 632356d356..a091d1ce89 100644 --- a/projects/netgrif-components-core/src/lib/utility/tests/mocks/mock-authentication-method-service.ts +++ b/projects/netgrif-components-core/src/lib/utility/tests/mocks/mock-authentication-method-service.ts @@ -5,7 +5,7 @@ import {UserResource} from '../../../resources/interface/user-resource'; export class MockAuthenticationMethodService extends AuthenticationMethodService { login(credentials: Credentials): Observable { - return of({email: 'mail', id: 'id', name: 'name', surname: 'surname', fullName: 'name surname', + return of({email: 'mail', id: 'id', name: 'name', surname: 'surname', fullName: 'name surname', workspaceId: '', groups: [], authorities: [], nextGroups: [], processRoles: []}); } diff --git a/projects/netgrif-components-core/src/lib/utility/tests/mocks/mock-authentication.service.ts b/projects/netgrif-components-core/src/lib/utility/tests/mocks/mock-authentication.service.ts index a35e81d04c..879d3b3431 100644 --- a/projects/netgrif-components-core/src/lib/utility/tests/mocks/mock-authentication.service.ts +++ b/projects/netgrif-components-core/src/lib/utility/tests/mocks/mock-authentication.service.ts @@ -18,9 +18,8 @@ export class MockAuthenticationService extends AuthenticationService { super(_auth, _config, _sessionService, _userTransformer); } - login(credentials: Credentials): Observable { - return of(new User('id', 'mail', 'name', 'surname', ['ADMIN'], [{stringId: 'id', name: 'id', importId: 'id'}])); + return of(new User('id', 'mail', 'name', 'surname', '', ['ADMIN'], [{stringId: 'id', name: 'id', importId: 'id'}])); } logout(): Observable { diff --git a/projects/netgrif-components-core/src/lib/utility/tests/mocks/mock-user-resource.service.ts b/projects/netgrif-components-core/src/lib/utility/tests/mocks/mock-user-resource.service.ts index 76b760fc12..be555b02cf 100644 --- a/projects/netgrif-components-core/src/lib/utility/tests/mocks/mock-user-resource.service.ts +++ b/projects/netgrif-components-core/src/lib/utility/tests/mocks/mock-user-resource.service.ts @@ -21,7 +21,7 @@ export class MockUserResourceService { } public getLoggedUser(): Observable { - return of({email: 'mail', id: 'id', name: 'name', surname: 'surname', fullName: 'name surname', + return of({email: 'mail', id: 'id', name: 'name', surname: 'surname', fullName: 'name surname', workspaceId: '', groups: [], authorities: [], nextGroups: [], processRoles: []}); } diff --git a/projects/netgrif-components/src/lib/navigation/navigation-double-drawer/navigation-double-drawer.component.html b/projects/netgrif-components/src/lib/navigation/navigation-double-drawer/navigation-double-drawer.component.html index 2d4c530c7a..af8c4ec97d 100644 --- a/projects/netgrif-components/src/lib/navigation/navigation-double-drawer/navigation-double-drawer.component.html +++ b/projects/netgrif-components/src/lib/navigation/navigation-double-drawer/navigation-double-drawer.component.html @@ -114,6 +114,21 @@ + + + + + + -