From 0913d090b465f0a1de63b56e8ac9be5640dd94b1 Mon Sep 17 00:00:00 2001 From: Lurkars Date: Sat, 5 Oct 2024 15:14:46 +0200 Subject: [PATCH] improve filter, add url parameter, overview improvements --- .../src/app/app-routing.module.ts | 2 + buntspecht-frontend/src/app/app.module.ts | 8 +- .../app/pages/management/management.page.html | 65 +++++++-- .../app/pages/management/management.page.scss | 44 +++++++ .../app/pages/management/management.page.ts | 124 +++++++++++++++++- .../src/app/pages/profile/profile.page.ts | 2 +- .../src/app/pages/turnover/turnover.page.scss | 6 - .../pages/turnovers/manage/manage.page.html | 11 +- .../pages/turnovers/manage/manage.page.scss | 2 - .../app/pages/turnovers/manage/manage.page.ts | 85 +++++++++++- .../app/pages/turnovers/turnovers.page.html | 10 +- .../app/pages/turnovers/turnovers.page.scss | 1 - .../src/app/pages/turnovers/turnovers.page.ts | 83 +++++++++++- .../pages/users/create/users.create.page.html | 49 +++++++ .../pages/users/create/users.create.page.scss | 21 +++ .../pages/users/create/users.create.page.ts | 84 ++++++++++++ .../src/app/pages/users/users.page.html | 98 ++++++-------- .../src/app/pages/users/users.page.ts | 65 ++------- .../app/services/user.management.service.ts | 4 +- .../src/app/ui/main/main.ui.ts | 1 - .../src/app/ui/turnovers/turnovers.ui.html | 23 ++-- .../src/app/ui/turnovers/turnovers.ui.ts | 5 +- .../src/assets/i18n/de-informal.json | 9 +- 23 files changed, 630 insertions(+), 172 deletions(-) create mode 100644 buntspecht-frontend/src/app/pages/users/create/users.create.page.html create mode 100644 buntspecht-frontend/src/app/pages/users/create/users.create.page.scss create mode 100644 buntspecht-frontend/src/app/pages/users/create/users.create.page.ts diff --git a/buntspecht-frontend/src/app/app-routing.module.ts b/buntspecht-frontend/src/app/app-routing.module.ts index 0b86798..85b4d94 100644 --- a/buntspecht-frontend/src/app/app-routing.module.ts +++ b/buntspecht-frontend/src/app/app-routing.module.ts @@ -12,6 +12,7 @@ import { PageTurnover } from './pages/turnover/turnover.page'; import { PageTurnoversManage } from './pages/turnovers/manage/manage.page'; import { PageTurnovers } from './pages/turnovers/turnovers.page'; import { PageUnavailable } from './pages/unavailable/unavailable.page'; +import { PageUserCreate } from './pages/users/create/users.create.page'; import { PageUsers } from './pages/users/users.page'; import { UiMain } from './ui/main/main.ui'; @@ -28,6 +29,7 @@ const routes: Routes = [ { path: 't', component: PageTurnoversManage, canActivate: [AuthAdminGuard] }, { path: 'm', component: PageManagement, canActivate: [AuthAdminGuard] }, { path: 'u', component: PageUsers, canActivate: [AuthAdminGuard] }, + { path: 'user', component: PageUserCreate, canActivate: [AuthAdminGuard] }, { path: 'u/:username', component: PageProfile, canActivate: [AuthAdminGuard] }, { path: 'unavailable', component: PageUnavailable }, { path: '**', component: PageNotFound, pathMatch: 'full', canActivate: [AuthenticatedGuard] } diff --git a/buntspecht-frontend/src/app/app.module.ts b/buntspecht-frontend/src/app/app.module.ts index cd76c50..1e83a72 100644 --- a/buntspecht-frontend/src/app/app.module.ts +++ b/buntspecht-frontend/src/app/app.module.ts @@ -22,18 +22,19 @@ import { UiMain } from './ui/main/main.ui'; import { I18nEmptyPipe, I18nPipe } from './utils/i18n.pipe'; import { MomentPipe } from './utils/moment.pipe'; +import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field'; import { ServiceWorkerModule } from '@angular/service-worker'; import { environment } from '../environments/environment'; +import { PageManagement } from './pages/management/management.page'; import { PagePassword } from './pages/password/password.page'; import { PageTurnover } from './pages/turnover/turnover.page'; import { PageTurnoversManage } from './pages/turnovers/manage/manage.page'; import { PageTurnovers } from './pages/turnovers/turnovers.page'; +import { PageUserCreate } from './pages/users/create/users.create.page'; import { PageUsers } from './pages/users/users.page'; import { I18nPaginatorIntl, I18nService } from './services/i18n.service'; -import { UiTurnovers } from './ui/turnovers/turnovers.ui'; -import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field'; import { ConfirmDialog } from './ui/confirm/confirm.component'; -import { PageManagement } from './pages/management/management.page'; +import { UiTurnovers } from './ui/turnovers/turnovers.ui'; export function fetchI18n(i18n: I18nService) { @@ -80,6 +81,7 @@ export class XhrInterceptor implements HttpInterceptor { PageProfile, PageUnavailable, PageUsers, + PageUserCreate, UiMain, UiTurnovers, ConfirmDialog diff --git a/buntspecht-frontend/src/app/pages/management/management.page.html b/buntspecht-frontend/src/app/pages/management/management.page.html index 51fd4e6..267c77c 100644 --- a/buntspecht-frontend/src/app/pages/management/management.page.html +++ b/buntspecht-frontend/src/app/pages/management/management.page.html @@ -16,6 +16,12 @@ }
+ + filter_alt + + + @if (filterOpen) {
{{'management.filter.created' | i18n}} @@ -43,19 +49,30 @@
+ }
- @if (entries) { -
- + +

{{'paginator.empty' | i18n}}

+
+ + } + + @if (entries && entries.total) { +
+
- @@ -88,21 +105,40 @@ + + + + + + + + + +
{{'user.username' | - i18n}} + + {{'user.username' | i18n}}
- {{entry[0]}} + {{entry[0]}}
+ @if (entries.filter && entries.filter.username == entry[0]) { + + } + + @if (expanded && entries.total && entries.filter && entries.filter.username == entry[0]) { + + } +
- @if (entries.total == 0) { - - -

{{'paginator.empty' | i18n}}

-
-
- } + @if (!entries.filter || !entries.filter.username) { -
} + } @if (!entries || !entries.results && !entries.error) { diff --git a/buntspecht-frontend/src/app/pages/management/management.page.scss b/buntspecht-frontend/src/app/pages/management/management.page.scss index e69de29..764f41e 100644 --- a/buntspecht-frontend/src/app/pages/management/management.page.scss +++ b/buntspecht-frontend/src/app/pages/management/management.page.scss @@ -0,0 +1,44 @@ +.filter-container { + padding-left: 15px; + justify-content: flex-start; + align-items: center; + + .filter { + justify-content: flex-start; + align-items: center; + + &>* { + margin-top: 5px; + margin-bottom: 5px; + margin-left: 15px; + } + } +} + +.expanded-row { + visibility: hidden; + height: 0; + transition: height 500ms ease-in-out; + + &.visible { + visibility: visible; + height: auto; + } + + td { + padding: 0; + vertical-align: top; + } +} + +a.select-user { + cursor: pointer; + + &.selected { + cursor: not-allowed; + } + + &:hover { + opacity: 0.7; + } +} \ No newline at end of file diff --git a/buntspecht-frontend/src/app/pages/management/management.page.ts b/buntspecht-frontend/src/app/pages/management/management.page.ts index 7649e91..6faf940 100644 --- a/buntspecht-frontend/src/app/pages/management/management.page.ts +++ b/buntspecht-frontend/src/app/pages/management/management.page.ts @@ -2,6 +2,7 @@ import { Component, Input, OnInit } from '@angular/core'; import { FormControl } from '@angular/forms'; import { PageEvent } from '@angular/material/paginator'; import { Sort } from '@angular/material/sort'; +import { ActivatedRoute, Params, Router } from '@angular/router'; import { debounceTime, Observable, switchMap } from 'rxjs'; import { TurnoverManagementService } from 'src/app/services/turnover.management.service'; import { UserManagementService } from 'src/app/services/user.management.service'; @@ -17,41 +18,122 @@ export class PageManagement implements OnInit { pageSizeOptions: number[] = [1, 2, 3, 4, 5, 10, 15, 30, 50, 100]; sort: string = "username"; descending: boolean = false; + filterOpen: boolean = true; - columns: string[] = ['username', 'price', 'timeInvestment']; - + columns: string[] = ['username', 'price', 'timeInvestment', 'menu']; + expanded: boolean = false; users: Observable; usersFormControl = new FormControl(); + turnovers: any; + constructor( private turnoverManagementService: TurnoverManagementService, - private userManagementService: UserManagementService + private userManagementService: UserManagementService, + private router: Router, + private route: ActivatedRoute ) { } ngOnInit(): void { this.entries = {}; - this.update(); + this.turnovers = {}; this.users = this.usersFormControl .valueChanges .pipe( debounceTime(300), switchMap(value => this.userManagementService.pick(value)) ); + + this.route.queryParams.subscribe({ + next: (params) => { + this.entries = { filter: {} }; + this.expanded = false; + if (params['l']) { + this.entries.limit = +params['l']; + if (this.entries.limit < 1) { + this.entries.limit = 1; + } + } + if (params['o']) { + this.entries.offset = +params['o']; + if (this.entries.offset < 0) { + this.entries.offset = 0; + } + } + + if (params['s']) { + this.sort = params['s']; + } + + if (params['a']) { + this.descending = false; + } else { + this.descending = true; + } + + for (const param in params) { + if (param != 'l' && param != 'o' && param != 's' && param != 'a') { + this.entries.filter[param] = params[param]; + } + } + + this.refresh(); + } + }); } - update() { + refresh() { const filter = JSON.parse(JSON.stringify(this.entries.filter || {})); this.turnoverManagementService.overview(this.entries.limit || 15, this.entries.offset || 0, this.sort, this.descending, filter).subscribe({ next: (data: any) => { this.entries = data; this.entries.filter = filter; + if (filter.username) { + this.applyUser(filter.username); + } }, error: (error) => { this.entries = { error: error }; } }) } + update() { + const filter = JSON.parse(JSON.stringify(this.entries.filter || {})); + + const params: Params = { l: null, o: null, s: null, a: null }; + + if ((this.entries.limit || 15) != 15) { + params['l'] = this.entries.limit; + } + + if ((this.entries.offset || 0) != 0) { + params['o'] = this.entries.offset; + } + + if (this.sort != 'username') { + params['s'] = this.sort; + } + + if (!this.descending) { + params['a'] = true; + } + + if (filter) { + for (const param in filter) { + params[param] = filter[param] || null; + } + } + + this.router.navigate( + [], + { + relativeTo: this.route, + queryParams: params, + queryParamsHandling: 'replace' + }); + } + applyPage(event: PageEvent) { this.entries.limit = event.pageSize; this.entries.offset = event.pageSize * event.pageIndex; @@ -76,4 +158,36 @@ export class PageManagement implements OnInit { } } + selectUser(username: string) { + this.router.navigate( + [], + { + relativeTo: this.route, + queryParams: { username: this.entries.filter && this.entries.filter.username == username ? null : username }, + queryParamsHandling: 'merge' + }); + } + + applyUser(username: string) { + this.usersFormControl.setValue(username); + if (this.entries.total) { + this.expanded = true; + const filter = JSON.parse(JSON.stringify(this.entries.filter || {})); + this.turnoverManagementService.fetch(this.turnovers.limit || 100, this.turnovers.offset || 0, 'created', true, filter).subscribe({ + next: (data: any) => { + this.turnovers = data; + this.turnovers.filter = filter; + }, error: (error) => { + this.turnovers = { error: error }; + } + }) + } + } + + applyTurnoverPage(event: PageEvent) { + this.turnovers.limit = event.pageSize; + this.turnovers.offset = event.pageSize * event.pageIndex; + this.applyUser(this.usersFormControl.value); + } + } diff --git a/buntspecht-frontend/src/app/pages/profile/profile.page.ts b/buntspecht-frontend/src/app/pages/profile/profile.page.ts index 06f83e0..e719bab 100644 --- a/buntspecht-frontend/src/app/pages/profile/profile.page.ts +++ b/buntspecht-frontend/src/app/pages/profile/profile.page.ts @@ -166,7 +166,7 @@ export class PageProfile implements OnInit, OnDestroy { if (result) { this.userManagementService.deleteUser(this.user.username).subscribe({ next: () => { - this.router.navigateByUrl('/'); + this.router.navigateByUrl('/u'); } }); } diff --git a/buntspecht-frontend/src/app/pages/turnover/turnover.page.scss b/buntspecht-frontend/src/app/pages/turnover/turnover.page.scss index 97d55fe..0a1cb70 100644 --- a/buntspecht-frontend/src/app/pages/turnover/turnover.page.scss +++ b/buntspecht-frontend/src/app/pages/turnover/turnover.page.scss @@ -2,12 +2,6 @@ mat-form-field { display: block; margin: 20px 0 !important; } - -mat-chip mat-icon.mat-icon-inline { - margin-top: -12px; - margin-right: -2px; -} - form { margin: 5px; min-width: 390px; diff --git a/buntspecht-frontend/src/app/pages/turnovers/manage/manage.page.html b/buntspecht-frontend/src/app/pages/turnovers/manage/manage.page.html index 4330cd2..240dc16 100644 --- a/buntspecht-frontend/src/app/pages/turnovers/manage/manage.page.html +++ b/buntspecht-frontend/src/app/pages/turnovers/manage/manage.page.html @@ -5,7 +5,8 @@ filter_alt -
+ @if(filterOpen) { + {{'turnovers.filter.created' | i18n}} @@ -24,6 +25,7 @@ {{'turnovers.filter.username' | i18n}} @for (user of users | async; track user.username) { @@ -34,14 +36,17 @@ {{'turnovers.filter.customer' | i18n}} - + {{'turnovers.filter.motif' | i18n}} - + + } * { margin-top: 5px; diff --git a/buntspecht-frontend/src/app/pages/turnovers/manage/manage.page.ts b/buntspecht-frontend/src/app/pages/turnovers/manage/manage.page.ts index 60b3ebf..091a1a3 100644 --- a/buntspecht-frontend/src/app/pages/turnovers/manage/manage.page.ts +++ b/buntspecht-frontend/src/app/pages/turnovers/manage/manage.page.ts @@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core'; import { FormControl } from '@angular/forms'; import { PageEvent } from '@angular/material/paginator'; import { Sort } from '@angular/material/sort'; +import { ActivatedRoute, Params, Router } from '@angular/router'; import { debounceTime, Observable, switchMap } from 'rxjs'; import { TurnoverManagementService } from 'src/app/services/turnover.management.service'; import { UserManagementService } from 'src/app/services/user.management.service'; @@ -23,24 +24,64 @@ export class PageTurnoversManage implements OnInit { constructor( private turnoverManagementService: TurnoverManagementService, - private userManagementService: UserManagementService + private userManagementService: UserManagementService, + private router: Router, + private route: ActivatedRoute ) { } ngOnInit(): void { this.turnovers = {}; - this.update(); this.users = this.usersFormControl .valueChanges .pipe( debounceTime(300), switchMap(value => this.userManagementService.pick(value)) ); + this.route.queryParams.subscribe({ + next: (params) => { + this.turnovers = { filter: {} }; + if (params['l']) { + this.turnovers.limit = +params['l']; + if (this.turnovers.limit < 1) { + this.turnovers.limit = 1; + } + } + if (params['o']) { + this.turnovers.offset = +params['o']; + if (this.turnovers.offset < 0) { + this.turnovers.offset = 0; + } + } + + if (params['s']) { + this.sort = params['s']; + } + + if (params['a']) { + this.descending = false; + } else { + this.descending = true; + } + + for (const param in params) { + if (param != 'l' && param != 'o' && param != 's' && param != 'a') { + this.filterOpen = true; + this.turnovers.filter[param] = params[param]; + if (param == 'username') { + this.usersFormControl.setValue(params[param]); + } + } + } + + this.refresh(); + } + }); } - update() { + refresh() { const filter = JSON.parse(JSON.stringify(this.turnovers.filter || {})); - this.turnoverManagementService.fetch(this.turnovers.limit || 15, this.turnovers.offset || 0, this.sort, this.descending, this.turnovers.filter).subscribe({ + this.turnoverManagementService.fetch(this.turnovers.limit || 15, this.turnovers.offset || 0, this.sort, this.descending, filter).subscribe({ next: (data: any) => { this.turnovers = data; this.turnovers.filter = filter; @@ -50,6 +91,42 @@ export class PageTurnoversManage implements OnInit { }) } + update() { + const filter = JSON.parse(JSON.stringify(this.turnovers.filter || {})); + + const params: Params = { l: null, o: null, s: null, a: null }; + + if ((this.turnovers.limit || 15) != 15) { + params['l'] = this.turnovers.limit; + } + + if ((this.turnovers.offset || 0) != 0) { + params['o'] = this.turnovers.offset; + } + + if (this.sort != 'created') { + params['s'] = this.sort; + } + + if (!this.descending) { + params['a'] = true; + } + + if (filter) { + for (const param in filter) { + params[param] = filter[param] || null; + } + } + + this.router.navigate( + [], + { + relativeTo: this.route, + queryParams: params, + queryParamsHandling: 'replace' + }); + } + applyPage(event: PageEvent) { this.turnovers.limit = event.pageSize; this.turnovers.offset = event.pageSize * event.pageIndex; diff --git a/buntspecht-frontend/src/app/pages/turnovers/turnovers.page.html b/buntspecht-frontend/src/app/pages/turnovers/turnovers.page.html index 3d08079..4575cde 100644 --- a/buntspecht-frontend/src/app/pages/turnovers/turnovers.page.html +++ b/buntspecht-frontend/src/app/pages/turnovers/turnovers.page.html @@ -5,7 +5,8 @@ filter_alt -
+ @if (filterOpen) { + {{'turnovers.filter.created' | i18n}} @@ -22,14 +23,17 @@ {{'turnovers.filter.customer' | i18n}} - + {{'turnovers.filter.motif' | i18n}} - + + } * { margin-top: 5px; diff --git a/buntspecht-frontend/src/app/pages/turnovers/turnovers.page.ts b/buntspecht-frontend/src/app/pages/turnovers/turnovers.page.ts index 384a6ca..afa318d 100644 --- a/buntspecht-frontend/src/app/pages/turnovers/turnovers.page.ts +++ b/buntspecht-frontend/src/app/pages/turnovers/turnovers.page.ts @@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core'; import { FormControl } from '@angular/forms'; import { PageEvent } from '@angular/material/paginator'; import { Sort } from '@angular/material/sort'; +import { ActivatedRoute, Params, Router } from '@angular/router'; import { debounceTime, Observable, switchMap } from 'rxjs'; import { TurnoverService } from 'src/app/services/turnover.service'; import { UserManagementService } from 'src/app/services/user.management.service'; @@ -18,20 +19,54 @@ export class PageTurnovers implements OnInit { sort: string = "created"; descending: boolean = true; filterOpen: boolean = false; - - users: Observable; - usersFormControl = new FormControl(); + init: boolean = true; constructor( - private turnoverService: TurnoverService + private turnoverService: TurnoverService, + private router: Router, + private route: ActivatedRoute ) { } ngOnInit(): void { this.turnovers = {}; - this.update(); + this.route.queryParams.subscribe({ + next: (params) => { + this.turnovers = { filter: {} }; + if (params['l']) { + this.turnovers.limit = +params['l']; + if (this.turnovers.limit < 1) { + this.turnovers.limit = 1; + } + } + if (params['o']) { + this.turnovers.offset = +params['o']; + if (this.turnovers.offset < 0) { + this.turnovers.offset = 0; + } + } + + if (params['s']) { + this.sort = params['s']; + } + + if (params['a']) { + this.descending = false; + } else { + this.descending = true; + } + + for (const param in params) { + if (param != 'l' && param != 'o' && param != 's' && param != 'a') { + this.filterOpen = true; + this.turnovers.filter[param] = params[param]; + } + } + this.refresh(); + } + }); } - update() { + refresh() { const filter = JSON.parse(JSON.stringify(this.turnovers.filter || {})); this.turnoverService.fetch(this.turnovers.limit || 15, this.turnovers.offset || 0, this.sort, this.descending, this.turnovers.filter).subscribe({ next: (data: any) => { @@ -54,6 +89,42 @@ export class PageTurnovers implements OnInit { }) } + update() { + const filter = JSON.parse(JSON.stringify(this.turnovers.filter || {})); + + const params: Params = { l: null, o: null, s: null, a: null }; + + if ((this.turnovers.limit || 15) != 15) { + params['l'] = this.turnovers.limit; + } + + if ((this.turnovers.offset || 0) != 0) { + params['o'] = this.turnovers.offset; + } + + if (this.sort != 'created') { + params['s'] = this.sort; + } + + if (!this.descending) { + params['a'] = true; + } + + if (filter) { + for (const param in filter) { + params[param] = filter[param] || null; + } + } + + this.router.navigate( + [], + { + relativeTo: this.route, + queryParams: params, + queryParamsHandling: 'replace' + }); + } + applyPage(event: PageEvent) { this.turnovers.limit = event.pageSize; this.turnovers.offset = event.pageSize * event.pageIndex; diff --git a/buntspecht-frontend/src/app/pages/users/create/users.create.page.html b/buntspecht-frontend/src/app/pages/users/create/users.create.page.html new file mode 100644 index 0000000..c9965e8 --- /dev/null +++ b/buntspecht-frontend/src/app/pages/users/create/users.create.page.html @@ -0,0 +1,49 @@ +
+
+ + + + {{'profile.username' | i18n}} + + + {{'user.error.' + error.key | i18n}} + + + + + {{'profile.name' | i18n}} + + + {{'user.error.' + error.key | i18n}} + + + + + {{'profile.email' | i18n}} + + + {{'user.error.' + error.key | i18n}} + + + + + {{'user.password' | i18n}} + + + {{'password.error.' + error.key | i18n}} + + + + + {{'user.admin' | i18n}} + + + + @if (!working) { + + } + + +
+
\ No newline at end of file diff --git a/buntspecht-frontend/src/app/pages/users/create/users.create.page.scss b/buntspecht-frontend/src/app/pages/users/create/users.create.page.scss new file mode 100644 index 0000000..ee839a3 --- /dev/null +++ b/buntspecht-frontend/src/app/pages/users/create/users.create.page.scss @@ -0,0 +1,21 @@ +mat-form-field { + display: block; + margin: 20px 0 !important; + } + form { + margin: 5px; + min-width: 390px; + + @media screen and (min-width: 576px) { + max-width: 100%; + } + + @media screen and (min-width: 768px) { + max-width: 80%; + margin: 15px; + } + + @media screen and (min-width: 992px) { + max-width: 50%; + } + } \ No newline at end of file diff --git a/buntspecht-frontend/src/app/pages/users/create/users.create.page.ts b/buntspecht-frontend/src/app/pages/users/create/users.create.page.ts new file mode 100644 index 0000000..dcbe44f --- /dev/null +++ b/buntspecht-frontend/src/app/pages/users/create/users.create.page.ts @@ -0,0 +1,84 @@ +import { Component, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { Router } from '@angular/router'; +import { UserManagementService } from 'src/app/services/user.management.service'; + +@Component({ + selector: 'page-user-create', + templateUrl: './users.create.page.html', + styleUrls: ['./users.create.page.scss'] +}) +export class PageUserCreate implements OnInit { + + form: FormGroup; + isAdmin: boolean = false; + working: boolean = false; + + constructor( + private userManagementService: UserManagementService, + private formBuilder: FormBuilder, + private router: Router) { } + + ngOnInit(): void { + this.form = this.formBuilder.group({ + username: ['', Validators.required], + name: ['', Validators.nullValidator], + email: ['', Validators.nullValidator], + password: ['', Validators.required] + }); + } + + createUser() { + this.working = true; + const user = { + username: this.form.get("username").value, + name: this.form.get("name").value, + email: this.form.get("email").value, + roles: this.isAdmin ? ['ROLE_ADMIN'] : [] + } + + const request = this.form.get("username").disabled ? this.userManagementService.update(user) : this.userManagementService.create(user); + + request.subscribe({ + next: (result: any) => { + this.userManagementService.setPassword(result.username, this.form.get("password").value).subscribe({ + next: (result) => { + this.working = false; + this.router.navigateByUrl('/u'); + }, + error: (error) => { + this.form.get("username").disable(); + + this.working = false; + if (error.status == 409) { + let errors = {}; + for (let code of error.error) { + errors[code.field] = errors[code.field] || {}; + errors[code.field][code.code] = true; + } + + for (let code in errors) { + this.form.get(code).setErrors(errors[code]); + } + } + } + }); + }, + error: (error) => { + this.working = false; + if (error.status == 409) { + let errors = {}; + for (let code of error.error) { + errors[code.field] = errors[code.field] || {}; + errors[code.field][code.code] = true; + } + + for (let code in errors) { + this.form.get(code).setErrors(errors[code]); + } + } + } + }) + } + +} diff --git a/buntspecht-frontend/src/app/pages/users/users.page.html b/buntspecht-frontend/src/app/pages/users/users.page.html index 2cf3a25..e08a976 100644 --- a/buntspecht-frontend/src/app/pages/users/users.page.html +++ b/buntspecht-frontend/src/app/pages/users/users.page.html @@ -1,21 +1,38 @@ -@if (users && users.error) {
- - - {{ 'users.error.' + users.error.status | i18n}} - {{'users.error' | i18n}} - - -

- {{ 'users.error.' + users.error.status + '.text' | i18n}} -

-
-
-
-} + @if (users && users.error) { +
+ + + {{ 'users.error.' + users.error.status | i18n}} + {{'users.error' | i18n}} + + +

+ {{ 'users.error.' + users.error.status + '.text' | i18n}} +

+
+
+
+ } -@if (users) { -
+
+ + filter_alt + + + @if (filterOpen) { +
+ + {{'users.filter.search' | i18n}} + + +
+ } +
+ + @if (users) {
@@ -51,7 +68,8 @@ - + +
@if (users.total == 0) { @@ -64,47 +82,17 @@ - -
-
- - {{'profile.username' | i18n}} - - - - - {{'profile.name' | i18n}} - - - - - {{'profile.email' | i18n}} - - - - - {{'user.password' | i18n}} - - - - - {{'user.admin' | i18n}} - - - -
-
- - -} + } -@if (!users || !users.results && !users.error) { - -} \ No newline at end of file + @if (!users || !users.results && !users.error) { + + } +
\ No newline at end of file diff --git a/buntspecht-frontend/src/app/pages/users/users.page.ts b/buntspecht-frontend/src/app/pages/users/users.page.ts index 1e58406..a678eba 100644 --- a/buntspecht-frontend/src/app/pages/users/users.page.ts +++ b/buntspecht-frontend/src/app/pages/users/users.page.ts @@ -1,11 +1,9 @@ import { Component, HostListener, Input, OnInit } from '@angular/core'; -import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { MatDialog } from '@angular/material/dialog'; +import { FormBuilder } from '@angular/forms'; import { PageEvent } from '@angular/material/paginator'; import { Sort } from '@angular/material/sort'; import { AuthService } from 'src/app/services/auth.service'; import { UserManagementService } from 'src/app/services/user.management.service'; -import { ConfirmDialog } from 'src/app/ui/confirm/confirm.component'; @Component({ selector: 'ui-users', @@ -18,12 +16,10 @@ export class PageUsers implements OnInit { pageSizeOptions: number[] = [1, 2, 3, 4, 5, 10, 15, 30, 50, 100]; sort: string = "username"; descending: boolean = false; + filterOpen: boolean = true; columns: string[] = []; - form: FormGroup; - isAdmin: boolean = false; - username: string = ""; constructor( @@ -35,12 +31,6 @@ export class PageUsers implements OnInit { this.users = {}; this.update(); this.applyResize(window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth); - this.form = this.formBuilder.group({ - username: ['', Validators.required], - name: ['', Validators.nullValidator], - email: ['', Validators.nullValidator], - password: ['', Validators.required] - }); this.authService.auth.subscribe({ next: (auth) => { @@ -66,9 +56,11 @@ export class PageUsers implements OnInit { } update() { - this.userManagementService.fetch(this.users.limit || 15, this.users.offset || 0, this.sort, this.descending).subscribe({ + const filter = this.users.filter || ""; + this.userManagementService.fetch(this.users.limit || 15, this.users.offset || 0, this.sort, this.descending, filter).subscribe({ next: (data: any) => { this.users = data; + this.users.filter = filter; }, error: (error) => { this.users = { error: error }; } @@ -87,48 +79,13 @@ export class PageUsers implements OnInit { this.update(); } - createUser() { - const user = { - username: this.form.get("username").value, - name: this.form.get("name").value, - email: this.form.get("email").value, - roles: this.isAdmin ? ['ROLE_ADMIN'] : [] + setFilter(target: EventTarget) { + const value = (target as HTMLInputElement).value; + if (value != this.users.filter) { + this.users.filter = value; + this.users.offset = 0; + this.update(); } - this.userManagementService.create(user).subscribe({ - next: (result: any) => { - this.userManagementService.setPassword(result.username, this.form.get("password").value).subscribe({ - next: (result) => { - this.update(); - }, - error: (error) => { - if (error.status == 422) { - let errors = {}; - for (let code of error.error) { - errors[code.field] = errors[code.field] || {}; - errors[code.field][code.code] = true; - } - - for (let code in errors) { - this.form.get(code).setErrors(errors[code]); - } - } - } - }); - }, - error: (error) => { - if (error.status == 422) { - let errors = {}; - for (let code of error.error) { - errors[code.field] = errors[code.field] || {}; - errors[code.field][code.code] = true; - } - - for (let code in errors) { - this.form.get(code).setErrors(errors[code]); - } - } - } - }) } } diff --git a/buntspecht-frontend/src/app/services/user.management.service.ts b/buntspecht-frontend/src/app/services/user.management.service.ts index 5ac4ca1..9ed899b 100644 --- a/buntspecht-frontend/src/app/services/user.management.service.ts +++ b/buntspecht-frontend/src/app/services/user.management.service.ts @@ -12,8 +12,8 @@ export class UserManagementService { constructor(private http: HttpClient, private abstractService: AbstractService) { } - fetch(limit: number, offset: number, sort: string, descending: boolean, filter: string = "") { - return this.abstractService.fetch("/users/manage", limit, offset, sort, descending, filter); + fetch(limit: number, offset: number, sort: string, descending: boolean, search: string = "") { + return this.abstractService.fetch("/users/manage", limit, offset, sort, descending, { filter: search }); } pick(search: string) { diff --git a/buntspecht-frontend/src/app/ui/main/main.ui.ts b/buntspecht-frontend/src/app/ui/main/main.ui.ts index 7ac8832..44ca97c 100644 --- a/buntspecht-frontend/src/app/ui/main/main.ui.ts +++ b/buntspecht-frontend/src/app/ui/main/main.ui.ts @@ -239,7 +239,6 @@ export class UiMain { } random() { - console.log("Random?"); this.debugService.random().subscribe({ next: () => { window.location.reload(); diff --git a/buntspecht-frontend/src/app/ui/turnovers/turnovers.ui.html b/buntspecht-frontend/src/app/ui/turnovers/turnovers.ui.html index c309dd6..03d5b5e 100644 --- a/buntspecht-frontend/src/app/ui/turnovers/turnovers.ui.html +++ b/buntspecht-frontend/src/app/ui/turnovers/turnovers.ui.html @@ -15,10 +15,19 @@ } @if (turnovers) { -@if(turnovers.results) { + +@if (turnovers.total == 0) { + + +

{{'paginator.empty' | i18n}}

+
+
+} + +@if(turnovers.total) {
- +
@@ -114,13 +123,7 @@ } -@if (turnovers.total == 0) { - - -

{{'paginator.empty' | i18n}}

-
-
-} + diff --git a/buntspecht-frontend/src/app/ui/turnovers/turnovers.ui.ts b/buntspecht-frontend/src/app/ui/turnovers/turnovers.ui.ts index 3e9631b..1029b87 100644 --- a/buntspecht-frontend/src/app/ui/turnovers/turnovers.ui.ts +++ b/buntspecht-frontend/src/app/ui/turnovers/turnovers.ui.ts @@ -15,6 +15,7 @@ export class UiTurnovers implements OnInit { @Input() showFilter: boolean = true; @Input() linkTurnover: boolean = true; @Input() username: boolean = false; + @Input() enableSort: boolean = true; @Output() page: EventEmitter = new EventEmitter(); @Output() sort: EventEmitter = new EventEmitter(); @@ -35,12 +36,14 @@ export class UiTurnovers implements OnInit { applyResize(width: number) { if (width < 992) { - this.columns = ['customer', 'motif']; + this.columns = ['customer', 'price']; } else { this.columns = ['customer', 'motif', 'price', 'timeInvestment', 'remark', 'materialConsumption', 'updated']; } if (this.username) { this.columns.unshift('username'); + } else { + this.columns.push('motif'); } this.columns.unshift('created'); } diff --git a/buntspecht-frontend/src/assets/i18n/de-informal.json b/buntspecht-frontend/src/assets/i18n/de-informal.json index 748ba58..b111d8e 100644 --- a/buntspecht-frontend/src/assets/i18n/de-informal.json +++ b/buntspecht-frontend/src/assets/i18n/de-informal.json @@ -152,11 +152,18 @@ "confirmDelete": "Möchtest du den User '{0}' wirklich löschen? ALLE Buchungen dieses Users werden ebenfalls gelöscht!", "create": "Neuen User erstellen", "delete": "User löschen", + "error": { + "ALREADY_EXISTS": "User existiert bereits" + }, "manage": "Verwalten", "password": "Passwort", "username": "User" }, "users": { - ".": "User verwalten" + ".": "User verwalten", + "filter": { + ".": "Filter", + "search": "Nach Username filtern" + } } } \ No newline at end of file
{{'turnover.username' | i18n}}