mirror of
https://github.com/GNS3/gns3-web-ui.git
synced 2025-02-08 12:20:14 +00:00
user management, add paginator
This commit is contained in:
parent
11029db956
commit
596a11210f
@ -1,3 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Software Name : GNS3 Web UI
|
||||||
|
* Version: 3
|
||||||
|
* SPDX-FileCopyrightText: Copyright (c) 2022 Orange Business Services
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* This software is distributed under the GPL-3.0 or any later version,
|
||||||
|
* the text of which is available at https://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
|
* or see the "LICENSE" file for more details.
|
||||||
|
*
|
||||||
|
* Author: Sylvain MATHIEU, Elise LEBEAU
|
||||||
|
*/
|
||||||
import {Server} from "../../../models/server";
|
import {Server} from "../../../models/server";
|
||||||
import {UserService} from "../../../services/user.service";
|
import {UserService} from "../../../services/user.service";
|
||||||
import {FormControl} from "@angular/forms";
|
import {FormControl} from "@angular/forms";
|
||||||
|
@ -1,3 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* Software Name : GNS3 Web UI
|
||||||
|
* Version: 3
|
||||||
|
* SPDX-FileCopyrightText: Copyright (c) 2022 Orange Business Services
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* This software is distributed under the GPL-3.0 or any later version,
|
||||||
|
* the text of which is available at https://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
|
* or see the "LICENSE" file for more details.
|
||||||
|
*
|
||||||
|
* Author: Sylvain MATHIEU, Elise LEBEAU
|
||||||
|
*/
|
||||||
import {Server} from "../../../models/server";
|
import {Server} from "../../../models/server";
|
||||||
import {FormControl} from "@angular/forms";
|
import {FormControl} from "@angular/forms";
|
||||||
import {timer} from "rxjs";
|
import {timer} from "rxjs";
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
<form>
|
<form>
|
||||||
<mat-form-field class="full-width">
|
<mat-form-field class="full-width">
|
||||||
<input matInput placeholder="Search by name" [(ngModel)]="searchText" [ngModelOptions]="{ standalone: true }" />
|
<input matInput placeholder="Search by username, full name or email" [(ngModel)]="searchText" [ngModelOptions]="{ standalone: true }" />
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
@ -44,7 +44,7 @@
|
|||||||
<ng-container matColumnDef="full_name">
|
<ng-container matColumnDef="full_name">
|
||||||
<mat-header-cell *matHeaderCellDef mat-sort-header> Full Name </mat-header-cell>
|
<mat-header-cell *matHeaderCellDef mat-sort-header> Full Name </mat-header-cell>
|
||||||
<mat-cell *matCellDef="let row">
|
<mat-cell *matCellDef="let row">
|
||||||
<div [matTooltip]="row.full_name" class="overflow-col">{{ row.full_name }}</div>
|
<div [matTooltip]="row.full_name" matTooltipClass="custom-tooltip" class="overflow-col">{{ row.full_name }}</div>
|
||||||
</mat-cell>
|
</mat-cell>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container matColumnDef="email">
|
<ng-container matColumnDef="email">
|
||||||
@ -74,6 +74,11 @@
|
|||||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||||
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
|
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
|
||||||
</mat-table>
|
</mat-table>
|
||||||
|
|
||||||
|
<mat-paginator [pageSizeOptions]="[5, 10, 20]"
|
||||||
|
showFirstLastButtons
|
||||||
|
aria-label="Select page">
|
||||||
|
</mat-paginator>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
import {Component, OnInit, ViewChild} from '@angular/core';
|
import {Component, OnInit, ViewChild} from '@angular/core';
|
||||||
import {ActivatedRoute, Router} from "@angular/router";
|
import {ActivatedRoute, Router} from "@angular/router";
|
||||||
import {Server} from "@models/server";
|
import {Server} from "@models/server";
|
||||||
import {MatSort, MatSortable} from "@angular/material/sort";
|
import {MatSort, MatSortable, Sort} from "@angular/material/sort";
|
||||||
import {UserService} from "@services/user.service";
|
import {UserService} from "@services/user.service";
|
||||||
import {ProgressService} from "../../common/progress/progress.service";
|
import {ProgressService} from "../../common/progress/progress.service";
|
||||||
import {User} from "@models/users/user";
|
import {User} from "@models/users/user";
|
||||||
@ -24,6 +24,8 @@ import {AddUserDialogComponent} from "@components/user-management/add-user-dialo
|
|||||||
import {MatDialog} from "@angular/material/dialog";
|
import {MatDialog} from "@angular/material/dialog";
|
||||||
import {DeleteUserDialogComponent} from "@components/user-management/delete-user-dialog/delete-user-dialog.component";
|
import {DeleteUserDialogComponent} from "@components/user-management/delete-user-dialog/delete-user-dialog.component";
|
||||||
import {ToasterService} from "@services/toaster.service";
|
import {ToasterService} from "@services/toaster.service";
|
||||||
|
import {MatPaginator} from "@angular/material/paginator";
|
||||||
|
import {MatTableDataSource} from "@angular/material/table";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-user-management',
|
selector: 'app-user-management',
|
||||||
@ -32,12 +34,12 @@ import {ToasterService} from "@services/toaster.service";
|
|||||||
})
|
})
|
||||||
export class UserManagementComponent implements OnInit {
|
export class UserManagementComponent implements OnInit {
|
||||||
server: Server;
|
server: Server;
|
||||||
dataSource: UserDataSource;
|
dataSource = new MatTableDataSource<User>();
|
||||||
userDatabase = new UserDatabase();
|
|
||||||
displayedColumns = ['select', 'username', 'full_name', 'email', 'is_active', 'last_login', 'updated_at', 'delete'];
|
displayedColumns = ['select', 'username', 'full_name', 'email', 'is_active', 'last_login', 'updated_at', 'delete'];
|
||||||
selection = new SelectionModel<User>(true, []);
|
selection = new SelectionModel<User>(true, []);
|
||||||
searchText: string = '';
|
searchText: string = '';
|
||||||
|
|
||||||
|
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||||
@ViewChild(MatSort, { static: true }) sort: MatSort;
|
@ViewChild(MatSort, { static: true }) sort: MatSort;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -53,17 +55,27 @@ export class UserManagementComponent implements OnInit {
|
|||||||
if (!this.server) this.router.navigate(['/servers']);
|
if (!this.server) this.router.navigate(['/servers']);
|
||||||
|
|
||||||
this.refresh();
|
this.refresh();
|
||||||
this.sort.sort(<MatSortable>{
|
}
|
||||||
id: 'name',
|
|
||||||
start: 'asc',
|
ngAfterViewInit() {
|
||||||
});
|
this.dataSource.paginator = this.paginator;
|
||||||
this.dataSource = new UserDataSource(this.userDatabase, this.sort);
|
this.dataSource.sort = this.sort;
|
||||||
|
this.dataSource.sortingDataAccessor = (item, property) => {
|
||||||
|
switch (property) {
|
||||||
|
case 'username':
|
||||||
|
case 'full_name':
|
||||||
|
case 'email':
|
||||||
|
return item[property] ? item[property].toLowerCase() : '';
|
||||||
|
default:
|
||||||
|
return item[property];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
this.userService.list(this.server).subscribe(
|
this.userService.list(this.server).subscribe(
|
||||||
(users: User[]) => {
|
(users: User[]) => {
|
||||||
this.userDatabase.addUsers(users);
|
this.dataSource.data = users;
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
this.progressService.setError(error);
|
this.progressService.setError(error);
|
||||||
@ -98,16 +110,18 @@ export class UserManagementComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
isAllSelected() {
|
isAllSelected() {
|
||||||
const numSelected = this.selection.selected.length;
|
const numSelected = this.selection.selected.length;
|
||||||
const numRows = this.userDatabase.data.length;
|
const numRows = this.dataSource.data.length;
|
||||||
return numSelected === numRows;
|
return numSelected === numRows;
|
||||||
}
|
}
|
||||||
|
|
||||||
masterToggle() {
|
masterToggle() {
|
||||||
this.isAllSelected() ?
|
this.isAllSelected() ?
|
||||||
this.selection.clear() :
|
this.selection.clear() :
|
||||||
this.userDatabase.data.forEach(row => this.selection.select(row));
|
this.dataSource.data.forEach(row => this.selection.select(row));
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteMultiple() {
|
deleteMultiple() {
|
||||||
@ -130,53 +144,3 @@ export class UserManagementComponent implements OnInit {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UserDatabase {
|
|
||||||
dataChange: BehaviorSubject<User[]> = new BehaviorSubject<User[]>([]);
|
|
||||||
|
|
||||||
get data(): User[] {
|
|
||||||
return this.dataChange.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public addUsers(users: User[]) {
|
|
||||||
this.dataChange.next(users);
|
|
||||||
}
|
|
||||||
|
|
||||||
public remove(user: User) {
|
|
||||||
const index = this.data.indexOf(user);
|
|
||||||
if (index >= 0) {
|
|
||||||
this.data.splice(index, 1);
|
|
||||||
this.dataChange.next(this.data.slice());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class UserDataSource extends DataSource<any> {
|
|
||||||
constructor(public userDatabase: UserDatabase, private sort: MatSort) {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
connect(): Observable<User[]> {
|
|
||||||
const displayDataChanges = [this.userDatabase.dataChange, this.sort.sortChange];
|
|
||||||
|
|
||||||
return merge(...displayDataChanges).pipe(
|
|
||||||
map(() => {
|
|
||||||
if (!this.sort.active || this.sort.direction === '') {
|
|
||||||
return this.userDatabase.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.userDatabase.data.sort((a, b) => {
|
|
||||||
const propertyA = a[this.sort.active];
|
|
||||||
const propertyB = b[this.sort.active];
|
|
||||||
|
|
||||||
const valueA = isNaN(+propertyA) ? propertyA : +propertyA;
|
|
||||||
const valueB = isNaN(+propertyB) ? propertyB : +propertyB;
|
|
||||||
|
|
||||||
return (valueA < valueB ? -1 : 1) * (this.sort.direction === 'asc' ? 1 : -1);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
disconnect() {}
|
|
||||||
}
|
|
||||||
|
@ -11,18 +11,19 @@
|
|||||||
* Author: Sylvain MATHIEU, Elise LEBEAU
|
* Author: Sylvain MATHIEU, Elise LEBEAU
|
||||||
*/
|
*/
|
||||||
import { Pipe, PipeTransform } from '@angular/core';
|
import { Pipe, PipeTransform } from '@angular/core';
|
||||||
import {UserDataSource} from "@components/user-management/user-management.component";
|
import {User} from "@models/users/user";
|
||||||
|
import {MatTableDataSource} from "@angular/material/table";
|
||||||
|
|
||||||
@Pipe({
|
@Pipe({
|
||||||
name: 'userFilter'
|
name: 'userFilter'
|
||||||
})
|
})
|
||||||
export class UserFilterPipe implements PipeTransform {
|
export class UserFilterPipe implements PipeTransform {
|
||||||
|
|
||||||
transform(items: UserDataSource, searchText: string) {
|
transform(items: MatTableDataSource<User>, searchText: string) {
|
||||||
if (!items) return [];
|
if (!items) return [];
|
||||||
if (!searchText) return items;
|
if (!searchText) return items;
|
||||||
searchText = searchText.toLowerCase();
|
searchText = searchText.toLowerCase();
|
||||||
return items.userDatabase.data.filter((item) => {
|
return items.data.filter((item: User) => {
|
||||||
return (item.username && item.username.toLowerCase().includes(searchText))
|
return (item.username && item.username.toLowerCase().includes(searchText))
|
||||||
|| (item.full_name && item.full_name.toLowerCase().includes(searchText))
|
|| (item.full_name && item.full_name.toLowerCase().includes(searchText))
|
||||||
|| (item.email && item.email.toLowerCase().includes(searchText));
|
|| (item.email && item.email.toLowerCase().includes(searchText));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user