File
Description
This component is an example for the manage members view
All users are displayed in a paginated list. The list can be filtered.
The members are hardcoded
If the backend offers an interface to get all users the mockUsers list schould be replaced
Implements
Metadata
selector |
app-project-members |
styleUrls |
./project-members.component.scss |
templateUrl |
./project-members.component.html |
Methods
applyFilter
|
applyFilter(filterValue: string)
|
|
On every key pressed in the filter-field this method is triggered and reduces the shown users in the list (table)
Parameters :
Name |
Type |
Optional |
filterValue |
string
|
No
|
|
onAddClick
|
onAddClick()
|
|
This method adds a user to the project members list without processing a task in the back-end
|
onDeleteClick
|
onDeleteClick()
|
|
This method deletes a user to the project members list without processing a task in the back-end
|
addableUsers
|
Type : Array<userMock>
|
Default value : [
{id: '7', displayName: 'AddedUser1', email: 'AddedUser1.de'},
{id: '8', displayName: 'AddedUser2', email: 'AddedUser2.de'},
{id: '9', displayName: 'AddedUser3', email: 'AddedUser3.de'}
]
|
|
columnsToDisplay
|
Type : []
|
Default value : ['Name', 'Role', 'email']
|
|
dataSource
|
Type : MatTableDataSource<any>
|
|
mockUsers
|
Type : Array<userMock>
|
Default value : [
{id: '1', displayName: 'User1', email: 'User1.de'},
{id: '2', displayName: 'User2', email: 'User2.de'},
{id: '3', displayName: 'User3', email: 'User3.de'},
{id: '4', displayName: 'User4', email: 'User4.de'},
{id: '5', displayName: 'User5', email: 'User5.de'},
{id: '6', displayName: 'User6', email: 'User6.de'}
]
|
|
paginator
|
Type : MatPaginator
|
Decorators :
@ViewChild(MatPaginator)
|
|
paginatorModule
|
Type : MatPaginatorModule
|
Decorators :
@ViewChild(MatPaginatorModule)
|
|
Public
project
|
Type : GetFullProjectQuery
|
|
Public
project$
|
Type : Observable<GetFullProjectQuery>
|
|
Public
projectId
|
Type : string
|
|
sort
|
Type : MatSort
|
Decorators :
@ViewChild(MatSort)
|
|
validationFilter
|
Default value : new FormControl('')
|
|
import {Component, OnInit, ViewChild} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {ProjectStoreService} from '@app/data/project/project-store.service';
import {GetFullProjectQuery} from 'src/generated/graphql';
import {Observable} from 'rxjs';
import {FormControl} from '@angular/forms';
import {MatTableDataSource} from '@angular/material/table';
import {MatSort, MatSortable} from '@angular/material/sort';
import {MatPaginator, MatPaginatorModule} from '@angular/material/paginator';
import {AddProjectMemberDialogComponent} from '@app/dialogs/add-project-member-dialog/add-project-member-dialog.component';
import {MatDialog} from '@angular/material/dialog';
import {RemoveProjectMemberComponentComponent} from '@app/dialogs/remove-project-member-component/remove-project-member-component.component';
/**
* This component is an example for the manage members view
* All users are displayed in a paginated list. The list can be filtered.
* The members are hardcoded
* If the backend offers an interface to get all users the mockUsers list schould be replaced
*/
@Component({
selector: 'app-project-members',
templateUrl: './project-members.component.html',
styleUrls: ['./project-members.component.scss']
})
export class ProjectMembersComponent implements OnInit {
@ViewChild(MatPaginator) paginator: MatPaginator;
@ViewChild(MatPaginatorModule) paginatorModule: MatPaginatorModule;
@ViewChild(MatSort) sort: MatSort;
public projectId: string;
public project$: Observable<GetFullProjectQuery>;
public project: GetFullProjectQuery;
validationFilter = new FormControl('');
columnsToDisplay = ['Name', 'Role', 'email'];
dataSource: MatTableDataSource<any>;
//users
mockUsers: Array<userMock> = [
{id: '1', displayName: 'User1', email: 'User1.de'},
{id: '2', displayName: 'User2', email: 'User2.de'},
{id: '3', displayName: 'User3', email: 'User3.de'},
{id: '4', displayName: 'User4', email: 'User4.de'},
{id: '5', displayName: 'User5', email: 'User5.de'},
{id: '6', displayName: 'User6', email: 'User6.de'}
];
// list of users who can be added to the project
//hardcoded
addableUsers: Array<userMock> = [
{id: '7', displayName: 'AddedUser1', email: 'AddedUser1.de'},
{id: '8', displayName: 'AddedUser2', email: 'AddedUser2.de'},
{id: '9', displayName: 'AddedUser3', email: 'AddedUser3.de'}
];
constructor(private dialog: MatDialog, private projectStore: ProjectStoreService, private route: ActivatedRoute) {}
ngOnInit(): void {
this.projectId = this.route.snapshot.paramMap.get('id');
this.project$ = this.projectStore.getFullProject(this.projectId);
this.project$.subscribe((project) => {
this.project = project;
// MOCK DATA for table
// FIXME Api change
// project.node.users.nodes.forEach(u => this.mockUsers.push(u));
this.dataSource = new MatTableDataSource<any>(this.mockUsers);
// sort data in table
this.sort.sort({id: 'Name', start: 'asc'} as MatSortable);
this.dataSource.sort = this.sort;
//paginator
this.dataSource.paginator = this.paginator;
});
}
/**
* This method adds a user to the project members list without processing a task in the back-end
*/
onAddClick(): void {
const addMemberDialogRef = this.dialog.open(AddProjectMemberDialogComponent, {
data: {addableMembers: this.addableUsers, projectId: this.projectId}
});
addMemberDialogRef.afterClosed().subscribe((data) => {
if (data) {
for (const user of data.usersToAdd) {
this.addableUsers.forEach((addableUser) => {
if (addableUser.id == user) {
this.mockUsers.push(addableUser);
}
});
}
this.dataSource = new MatTableDataSource<any>(this.mockUsers);
}
});
}
/**
* This method deletes a user to the project members list without processing a task in the back-end
*/
onDeleteClick(): void {
const deleteMemberDialogRef = this.dialog.open(RemoveProjectMemberComponentComponent, {
data: {mockMembers: this.mockUsers, projectId: this.projectId}
});
deleteMemberDialogRef.afterClosed().subscribe((data) => {
if (data) {
for (const user of data.usersToDelete) {
for (let i = 0; i < this.mockUsers.length; i++) {
if (this.mockUsers[i].id === user) {
this.mockUsers.splice(i, 1);
}
}
}
this.dataSource = new MatTableDataSource<any>(this.mockUsers);
}
});
}
/**
* On every key pressed in the filter-field this method is triggered and reduces the shown users in the list (table)
*/
applyFilter(filterValue: string): void {
filterValue = filterValue.trim(); // Remove whitespace
filterValue = filterValue.toLowerCase(); // MatTableDataSource defaults to lowercase matches
this.dataSource.filter = filterValue;
}
}
// defines the structure of a user
export interface userMock {
id: string;
displayName?: string;
username?: string;
email?: string;
}
<div style="display: flex; flex-direction: column" class="margin-left-top p-3">
<div *ngIf="!!project">
<app-project-header [projectId]="projectId" [projectName]="project.node.name"></app-project-header>
</div>
<div>
<div matSort matSortActive="Name">
<button class="button-add" mat-fab color="primary" (click)="this.onAddClick()">
<mat-icon>add</mat-icon>
</button>
<button class="button-remove" mat-fab color="warn" (click)="this.onDeleteClick()">
<mat-icon>remove</mat-icon>
</button>
<div class="component-title">
<mat-form-field appearance="outline">
<mat-label>Filter</mat-label>
<input [formControl]="this.validationFilter" matInput (keyup)="applyFilter($event.target.value)" />
</mat-form-field>
</div>
<div class="table-container mat-elevation-z8">
<!-- Table of Members -->
<table *ngIf="(project$ | async)?.node as project" mat-table style="width: 100%; min-width: 50%" [dataSource]="this.dataSource">
<!-- Name Column -->
<ng-container matColumnDef="Name">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Name</th>
<td mat-cell style="text-align: left" *matCellDef="let element">{{ element.displayName }}</td>
</ng-container>
<!-- Role Column -->
<ng-container matColumnDef="Role">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Role</th>
<td mat-cell style="text-align: left" *matCellDef="let element">Administrator</td>
</ng-container>
<!-- Mail Column -->
<ng-container matColumnDef="email">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Email</th>
<td mat-cell style="text-align: left" *matCellDef="let element">{{ element.email }}</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
<tr mat-row *matRowDef="let rowData; columns: columnsToDisplay"></tr>
</table>
</div>
<!-- TODO fix paginator -->
<mat-paginator [length]="mockUsers.length" [pageSize]="3" [pageSizeOptions]="[3, 5, 10]"> </mat-paginator>
</div>
<!-- Table of Members New -->
</div>
</div>
.project-title-row {
width: 100%;
margin-bottom: 12px;
align-items: center;
height: 85px;
}
.box {
float: left;
//display: inline-block;
vertical-align: top;
width: 85px;
height: auto;
margin-right: 5px;
}
.content {
//display: inline-block;
float: left;
}
.title,
.sub-title {
margin: 0;
padding: 3px 10px 3px 0;
}
.title {
font-size: 17px;
font-weight: bold;
}
.sub-title {
font-weight: bold;
color: #3f3f3f;
}
img {
width: 100%;
}
.pagefill {
width: 100%;
height: 300px;
}
.margin-left-top {
margin-top: 3px;
margin-left: 3px;
}
.text-left {
text-align: left;
}
.mat-row:hover {
box-shadow: inset 0 0 43px -17px rgba(201, 195, 201, 1);
cursor: pointer;
}
.button-add {
margin: 10px 5px 10px 10px;
float: left;
}
.button-remove {
margin: 10px 15px 10px 5px;
float: left;
}
.table-container {
max-height: 500px;
overflow: auto;
}
.center-horizontal {
width: 100%;
text-align: center;
margin-top: 15px;
}
Legend
Html element with directive