From a043a06b38d2ab56efee0747c1682693db8f88c3 Mon Sep 17 00:00:00 2001 From: Janik Endtner Date: Thu, 28 Dec 2023 17:08:27 +0100 Subject: [PATCH] #705 member-list ui --- .../keyresult/keyresult.component.scss | 4 +-- frontend/src/app/services/team.service.ts | 14 +++++++-- frontend/src/app/services/user.service.ts | 13 ++++++-- .../member-list/member-list.component.html | 20 ++++++++++--- .../member-list/member-list.component.scss | 30 +++++++++++++++++++ .../member-list/member-list.component.ts | 29 ++++++++++++++---- .../team-list/team-list.component.scss | 2 ++ .../team-management/team-management.module.ts | 2 ++ frontend/src/style/_variables.scss | 5 ++-- frontend/src/style/styles.scss | 21 +++++++++++++ 10 files changed, 123 insertions(+), 17 deletions(-) diff --git a/frontend/src/app/components/keyresult/keyresult.component.scss b/frontend/src/app/components/keyresult/keyresult.component.scss index 94eabe504a..19f57b5764 100644 --- a/frontend/src/app/components/keyresult/keyresult.component.scss +++ b/frontend/src/app/components/keyresult/keyresult.component.scss @@ -1,7 +1,7 @@ @import "../style/variables"; .key-result { - background-color: $keyResult-bg; - border: 1px solid $keyResult-border; + background-color: $dark-grey; + border: 1px solid $dark-grey-border; word-wrap: break-word; &:hover { diff --git a/frontend/src/app/services/team.service.ts b/frontend/src/app/services/team.service.ts index 4f9ff5b524..a1d6b1ad66 100644 --- a/frontend/src/app/services/team.service.ts +++ b/frontend/src/app/services/team.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Team } from '../shared/types/model/Team'; -import { Observable } from 'rxjs'; +import { Observable, of, take, tap } from 'rxjs'; @Injectable({ providedIn: 'root', @@ -9,8 +9,18 @@ import { Observable } from 'rxjs'; export class TeamService { constructor(private http: HttpClient) {} + private teams: Team[] | undefined; + getAllTeams(): Observable { - return this.http.get('/api/v2/teams'); + if (this.teams) { + return of(this.teams).pipe(take(1)); + } + return this.http.get('/api/v2/teams').pipe(tap((teams) => (this.teams = teams))); + } + + reloadTeams(): Observable { + this.teams = undefined; + return this.getAllTeams(); } createTeam(team: Team): Observable { diff --git a/frontend/src/app/services/user.service.ts b/frontend/src/app/services/user.service.ts index cd20c9cc8d..2b65c83357 100644 --- a/frontend/src/app/services/user.service.ts +++ b/frontend/src/app/services/user.service.ts @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { Observable, of, tap } from 'rxjs'; +import { Observable, of, take, tap } from 'rxjs'; import { HttpClient } from '@angular/common/http'; import { User } from '../shared/types/model/User'; @@ -10,6 +10,7 @@ export class UserService { private readonly API_URL = 'api/v1/users'; private _user: User | undefined; + private users: User[] | undefined; constructor(private httpClient: HttpClient) {} @@ -21,7 +22,15 @@ export class UserService { } public getUsers(): Observable { - return this.httpClient.get(this.API_URL); + if (this.users) { + return of(this.users).pipe(take(1)); + } + return this.httpClient.get(this.API_URL).pipe(tap((users) => (this.users = users))); + } + + public reloadUsers(): Observable { + this.users = undefined; + return this.getUsers(); } public getCurrentUser(): User { diff --git a/frontend/src/app/team-management/member-list/member-list.component.html b/frontend/src/app/team-management/member-list/member-list.component.html index 3f5d4013ee..369f8a66bb 100644 --- a/frontend/src/app/team-management/member-list/member-list.component.html +++ b/frontend/src/app/team-management/member-list/member-list.component.html @@ -1,21 +1,33 @@
- +
+
+

{{ selectedTeam?.name }}

+

Alle Teams

+

Members: {{ dataSource.length }}

+
+
+ +
- + + + + + - -
+ person_outline + Name {{ element.firstname }} {{ element.lastname }} Rolle {{ element.roles | roles }} Teams diff --git a/frontend/src/app/team-management/member-list/member-list.component.scss b/frontend/src/app/team-management/member-list/member-list.component.scss index a7df7c084e..0ab254e153 100644 --- a/frontend/src/app/team-management/member-list/member-list.component.scss +++ b/frontend/src/app/team-management/member-list/member-list.component.scss @@ -1,3 +1,33 @@ +@import "../../../style/_variables.scss"; + div { width: 100%; + + #member-header { + display: flex; + align-items: center; + background-color: $dark-grey; + width: 100%; + min-height: 57px; + + div { + display: flex; + align-items: end; + h3 { + margin: 0 2rem 0 1rem; + } + p { + font-size: 0.75rem; + margin-bottom: 4px; + } + } + } + + .mat-column-icon { + width: 50px; + } + + .mat-column-name { + width: 30%; + } } diff --git a/frontend/src/app/team-management/member-list/member-list.component.ts b/frontend/src/app/team-management/member-list/member-list.component.ts index 78f047217e..3b634a38ee 100644 --- a/frontend/src/app/team-management/member-list/member-list.component.ts +++ b/frontend/src/app/team-management/member-list/member-list.component.ts @@ -4,6 +4,8 @@ import { ActivatedRoute } from '@angular/router'; import { combineLatest, map, ReplaySubject, Subscription } from 'rxjs'; import { User } from '../../shared/types/model/User'; import { convertFromUsers, UserTableEntry } from '../../shared/types/model/UserTableEntry'; +import { TeamService } from '../../services/team.service'; +import { Team } from '../../shared/types/model/Team'; @Component({ selector: 'app-member-list', @@ -12,11 +14,13 @@ import { convertFromUsers, UserTableEntry } from '../../shared/types/model/UserT }) export class MemberListComponent implements OnInit, OnDestroy { dataSource: UserTableEntry[] = []; + selectedTeam: Team | undefined; + private allUsersSubj: ReplaySubject = new ReplaySubject(1); private subscription!: Subscription; - private allColumns = ['name', 'roles', 'teams']; - private teamColumns = ['name', 'roles']; + private allColumns = ['icon', 'name', 'roles', 'teams']; + private teamColumns = ['icon', 'name', 'roles']; displayedColumns: string[] = this.allColumns; @@ -24,14 +28,20 @@ export class MemberListComponent implements OnInit, OnDestroy { private readonly userService: UserService, private readonly route: ActivatedRoute, private readonly cd: ChangeDetectorRef, + private readonly teamService: TeamService, ) {} public ngOnInit(): void { this.userService.getUsers().subscribe((users) => this.allUsersSubj.next(users)); const teamId$ = this.route.paramMap.pipe(map((params) => params.get('teamId'))); - this.subscription = combineLatest([this.allUsersSubj.asObservable(), teamId$]).subscribe(([users, teamIdParam]) => - this.setDataSource(users, teamIdParam), - ); + this.subscription = combineLatest([ + this.allUsersSubj.asObservable(), + teamId$, + this.teamService.getAllTeams(), + ]).subscribe(([users, teamIdParam, teams]) => { + this.setDataSource(users, teamIdParam); + this.setSelectedTeam(teams, teamIdParam); + }); } private setDataSource(users: User[], teamIdParam: string | null) { @@ -50,4 +60,13 @@ export class MemberListComponent implements OnInit, OnDestroy { public ngOnDestroy(): void { this.subscription.unsubscribe(); } + + private setSelectedTeam(teams: Team[], teamIdParam: string | null) { + if (!teamIdParam) { + this.selectedTeam = undefined; + return; + } + this.selectedTeam = teams.find((t) => t.id === parseInt(teamIdParam)); + this.cd.markForCheck(); + } } diff --git a/frontend/src/app/team-management/team-list/team-list.component.scss b/frontend/src/app/team-management/team-list/team-list.component.scss index 07cdc3e2a0..a7199708d4 100644 --- a/frontend/src/app/team-management/team-list/team-list.component.scss +++ b/frontend/src/app/team-management/team-list/team-list.component.scss @@ -6,6 +6,8 @@ div { > mat-nav-list { padding: 0; + background-color: $light-grey; + .selected { background-color: $pz-dark-blue; diff --git a/frontend/src/app/team-management/team-management.module.ts b/frontend/src/app/team-management/team-management.module.ts index 1063240bae..97ca9f86af 100644 --- a/frontend/src/app/team-management/team-management.module.ts +++ b/frontend/src/app/team-management/team-management.module.ts @@ -14,6 +14,7 @@ import { MatListModule } from '@angular/material/list'; import { MatTableModule } from '@angular/material/table'; import { RolesPipe } from './roles.pipe'; import { TeamsPipe } from './teams.pipe'; +import { MatIconModule } from '@angular/material/icon'; @NgModule({ declarations: [ @@ -36,6 +37,7 @@ import { TeamsPipe } from './teams.pipe'; NgOptimizedImage, MatListModule, MatTableModule, + MatIconModule, ], }) export class TeamManagementModule {} diff --git a/frontend/src/style/_variables.scss b/frontend/src/style/_variables.scss index 49ce977a5f..dd34fdee04 100644 --- a/frontend/src/style/_variables.scss +++ b/frontend/src/style/_variables.scss @@ -4,8 +4,9 @@ $pz-dark-blue: #1e5a96; $error: #ba3838; $eggshell: #f6f7f8; -$keyResult-border: #5d6974; -$keyResult-bg: #e5e8eb; +$light-grey: #f8f8f8; +$dark-grey: #e5e8eb; +$dark-grey-border: #5d6974; $top-bar-height: 48px; diff --git a/frontend/src/style/styles.scss b/frontend/src/style/styles.scss index e76a6f8144..8497558e49 100644 --- a/frontend/src/style/styles.scss +++ b/frontend/src/style/styles.scss @@ -300,3 +300,24 @@ mat-form-field.quarter-filter .mat-mdc-text-field-wrapper { app-team-management-banner > #okrBanner { position: relative; } + +table.okr-table { + border-collapse: separate; + border-spacing: 0 0.5rem; + border: none; + box-shadow: none; + tr { + height: 40px; + + > td { + border: none; + background-color: $light-grey; + } + > th { + vertical-align: bottom; + font-size: 0.75rem; + border: none; + background-color: white; + } + } +}