mirror of
https://github.com/andwati/zitadel.git
synced 2026-11-08 23:25:12 +00:00
feat: rehauled console (#3525)
* new console * move npm ci to angular build * rel path for assets * local grpc copy * login policy, rm clear views, features rel path * lock Co-authored-by: Livio Amstutz <[email protected]>
This commit is contained in:
co-authored by
Livio Amstutz
parent
00f7dbe875
commit
08ae39ae19
@@ -1,97 +1,102 @@
|
||||
<cnsl-refresh-table *ngIf="dataSource" (refreshed)="changePage()" [dataSize]="dataSource.totalResult"
|
||||
[timestamp]="dataSource.viewTimestamp" [selection]="selection" [loading]="dataSource?.loading$ | async">
|
||||
[timestamp]="dataSource.viewTimestamp" [selection]="selection" [loading]="dataSource?.loading$ | async">
|
||||
|
||||
<ng-container actions *ngIf="selection.hasValue()">
|
||||
<ng-content select="[selectactions]"></ng-content>
|
||||
</ng-container>
|
||||
<ng-container actions *ngIf="selection.hasValue()">
|
||||
<ng-content select="[selectactions]"></ng-content>
|
||||
</ng-container>
|
||||
|
||||
<div actions>
|
||||
<ng-content select="[writeactions]"></ng-content>
|
||||
</div>
|
||||
<div actions *ngIf="!selection.hasValue()">
|
||||
<ng-content select="[writeactions]"></ng-content>
|
||||
</div>
|
||||
|
||||
<div class="table-wrapper">
|
||||
<table mat-table class="table" aria-label="Elements" [dataSource]="dataSource">
|
||||
<ng-container matColumnDef="select">
|
||||
<th class="selection" mat-header-cell *matHeaderCellDef>
|
||||
<mat-checkbox [disabled]="!canWrite" color="primary" (change)="$event ? masterToggle() : null"
|
||||
[checked]="selection.hasValue() && isAllSelected()"
|
||||
[indeterminate]="selection.hasValue() && !isAllSelected()">
|
||||
</mat-checkbox>
|
||||
</th>
|
||||
<td class="selection" mat-cell *matCellDef="let row">
|
||||
<mat-checkbox [disabled]="!canWrite" color="primary" (click)="$event.stopPropagation()"
|
||||
(change)="$event ? selection.toggle(row) : null" [checked]="selection.isSelected(row)">
|
||||
<cnsl-avatar *ngIf="row?.displayName && row.firstName && row.lastName; else cog" class="avatar"
|
||||
[name]="row.displayName" [avatarUrl]="row.avatarUrl || ''" [avatarUrl]="row.avatarUrl|| ''" [forColor]="row?.preferredLoginName" [size]="32">
|
||||
</cnsl-avatar>
|
||||
<ng-template #cog>
|
||||
<div class="sa-icon">
|
||||
<i class="las la-user-cog"></i>
|
||||
</div>
|
||||
</ng-template>
|
||||
</mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
<div class="table-wrapper">
|
||||
<table mat-table class="table" aria-label="Elements" [dataSource]="dataSource">
|
||||
<ng-container matColumnDef="select">
|
||||
<th class="selection" mat-header-cell *matHeaderCellDef>
|
||||
<mat-checkbox [disabled]="!canWrite" color="primary" (change)="$event ? masterToggle() : null"
|
||||
[checked]="selection.hasValue() && isAllSelected()"
|
||||
[indeterminate]="selection.hasValue() && !isAllSelected()">
|
||||
</mat-checkbox>
|
||||
</th>
|
||||
<td class="selection" mat-cell *matCellDef="let row">
|
||||
<mat-checkbox [disabled]="!canWrite" color="primary" (click)="$event.stopPropagation()"
|
||||
(change)="$event ? selection.toggle(row) : null" [checked]="selection.isSelected(row)">
|
||||
<cnsl-avatar *ngIf="row?.displayName && row.firstName && row.lastName; else cog" class="avatar"
|
||||
[name]="row.displayName" [avatarUrl]="row.avatarUrl || ''" [avatarUrl]="row.avatarUrl|| ''"
|
||||
[forColor]="row?.preferredLoginName" [size]="32">
|
||||
</cnsl-avatar>
|
||||
<ng-template #cog>
|
||||
<cnsl-avatar [forColor]="row.preferredLoginName" [isMachine]="true">
|
||||
<i class="las la-robot"></i>
|
||||
</cnsl-avatar>
|
||||
</ng-template>
|
||||
</mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="userId">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'PROJECT.MEMBER.USERID' | translate }} </th>
|
||||
<td class="pointer" [routerLink]="['/users', member.userId]" mat-cell *matCellDef="let member">
|
||||
{{member.userId}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="userId">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'PROJECT.MEMBER.USERID' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let member">
|
||||
{{member.userId}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="firstname">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'PROJECT.MEMBER.FIRSTNAME' | translate }} </th>
|
||||
<td class="pointer" [routerLink]="['/users', member.userId]" mat-cell *matCellDef="let member">
|
||||
{{member.firstName}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="displayName">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'PROJECT.MEMBER.DISPLAYNAME' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let member">
|
||||
{{member.displayName}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="lastname">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'PROJECT.MEMBER.LASTNAME' | translate }} </th>
|
||||
<td class="pointer" [routerLink]="['/users', member.userId]" mat-cell *matCellDef="let member">
|
||||
{{member.lastName}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="loginname">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'PROJECT.MEMBER.LOGINNAME' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let member">
|
||||
{{member.preferredLoginName}} </td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="loginname">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'PROJECT.MEMBER.LOGINNAME' | translate }} </th>
|
||||
<td class="pointer" [routerLink]="['/users', member.userId]" mat-cell *matCellDef="let member">
|
||||
{{member.preferredloginname}} </td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="email">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'PROJECT.MEMBER.EMAIL' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let member">
|
||||
{{member.email}}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="email">
|
||||
<th mat-header-cell *matHeaderCellDef> {{ 'PROJECT.MEMBER.EMAIL' | translate }} </th>
|
||||
<td class="pointer" [routerLink]="['/users', member.userId]" mat-cell *matCellDef="let member">
|
||||
{{member.email}}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="actions" stickyEnd>
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *matCellDef="let member" class="member-action-tr">
|
||||
<cnsl-table-actions [hasActions]="true">
|
||||
<button actions matTooltip="{{'ACTIONS.REMOVE' | translate}}" color="warn"
|
||||
(click)="triggerDeleteMember(member)" mat-icon-button><i class="las la-trash"></i></button>
|
||||
|
||||
<ng-container matColumnDef="actions" stickyEnd>
|
||||
<th mat-header-cell *matHeaderCellDef></th>
|
||||
<td mat-cell *matCellDef="let view">
|
||||
<button matTooltip="{{'ACTIONS.REMOVE' | translate}}" color="warn"
|
||||
(click)="triggerDeleteMember(view)" mat-icon-button><i class="las la-trash"></i></button>
|
||||
</td>
|
||||
</ng-container>
|
||||
<button menuActions mat-menu-item [routerLink]="['/users', member.userId]">
|
||||
{{'ACTIONS.TABLE.SHOWUSER' | translate : ({value: member.displayName})}}
|
||||
</button>
|
||||
</cnsl-table-actions>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="roles">
|
||||
<th mat-header-cell *matHeaderCellDef class="role-row"> {{ 'ROLESLABEL' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let member" class="role-row">
|
||||
<cnsl-form-field class="form-field" appearance="outline">
|
||||
<mat-select [(ngModel)]="member.rolesList" multiple [disabled]="!canWrite"
|
||||
(selectionChange)="updateRoles.emit({member: member, change: $event})">
|
||||
<mat-option *ngFor="let role of memberRoleOptions" [value]="role">
|
||||
{{ role }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</cnsl-form-field>
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="roles">
|
||||
<th mat-header-cell *matHeaderCellDef class="role-row"> {{ 'ROLESLABEL' | translate }} </th>
|
||||
<td mat-cell *matCellDef="let member" class="role-row">
|
||||
<mat-chip-list class="cnsl-chip-list" aria-label="role selection">
|
||||
<mat-chip class="cnsl-chip" *ngFor="let role of member.rolesList" [removable]="true" [selectable]="false"
|
||||
(removed)="removeRole(member, role)">
|
||||
<div class="cnsl-chip-dot" [style.background]="getColor(role)"></div>
|
||||
<span>{{role | roletransform}}</span>
|
||||
<button matChipRemove>
|
||||
<mat-icon>cancel</mat-icon>
|
||||
</button>
|
||||
</mat-chip>
|
||||
</mat-chip-list>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns;">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<cnsl-paginator *ngIf="dataSource" class="paginator" #paginator [timestamp]="dataSource?.viewTimestamp" [pageSize]="INITIALPAGESIZE"
|
||||
[length]="dataSource.totalResult" [pageSizeOptions]="[25, 50, 100, 250]" (page)="changePage($event)">
|
||||
</cnsl-paginator>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr class="highlight pointer" (click)="addRole(member)" mat-row
|
||||
*matRowDef="let member; columns: displayedColumns;">
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<cnsl-paginator *ngIf="dataSource" class="paginator" #paginator [timestamp]="dataSource?.viewTimestamp"
|
||||
[pageSize]="INITIALPAGESIZE" [length]="dataSource.totalResult" [pageSizeOptions]="[25, 50, 100, 250]"
|
||||
(page)="changePage($event)">
|
||||
</cnsl-paginator>
|
||||
</cnsl-refresh-table>
|
||||
@@ -1,53 +1,36 @@
|
||||
.icon-button {
|
||||
margin-right: .5rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
.table-wrapper {
|
||||
overflow-x: auto;
|
||||
td,
|
||||
th {
|
||||
padding: 0.5rem;
|
||||
|
||||
.table,
|
||||
.paginator {
|
||||
width: 100%;
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: .5rem;
|
||||
|
||||
&:first-child {
|
||||
padding-left: 0;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.action {
|
||||
width: 40px;
|
||||
}
|
||||
&:first-child {
|
||||
padding-left: 0;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
|
||||
tr {
|
||||
button {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
button {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
&:last-child {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.sa-icon {
|
||||
display: block;
|
||||
width: 32px;
|
||||
margin: 0 .5rem;
|
||||
.action {
|
||||
width: 40px;
|
||||
}
|
||||
|
||||
i {
|
||||
margin: auto;
|
||||
}
|
||||
.member-action-tr {
|
||||
max-width: 100px;
|
||||
}
|
||||
|
||||
.sa-icon {
|
||||
display: block;
|
||||
width: 32px;
|
||||
margin: 0 0.5rem;
|
||||
|
||||
i {
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { MatPaginatorModule } from '@angular/material/paginator';
|
||||
import { MatSortModule } from '@angular/material/sort';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
@@ -7,28 +6,25 @@ import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { MembersTableComponent } from './members-table.component';
|
||||
|
||||
describe('MembersTableComponent', () => {
|
||||
let component: MembersTableComponent;
|
||||
let fixture: ComponentFixture<MembersTableComponent>;
|
||||
let component: MembersTableComponent;
|
||||
let fixture: ComponentFixture<MembersTableComponent>;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [MembersTableComponent],
|
||||
imports: [
|
||||
NoopAnimationsModule,
|
||||
MatPaginatorModule,
|
||||
MatSortModule,
|
||||
MatTableModule,
|
||||
],
|
||||
}).compileComponents();
|
||||
}));
|
||||
beforeEach(
|
||||
waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [MembersTableComponent],
|
||||
imports: [NoopAnimationsModule, MatSortModule, MatTableModule],
|
||||
}).compileComponents();
|
||||
}),
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(MembersTableComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(MembersTableComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should compile', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
it('should compile', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { SelectionModel } from '@angular/cdk/collections';
|
||||
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core';
|
||||
import { MatSelectChange } from '@angular/material/select';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatTable } from '@angular/material/table';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
@@ -10,11 +10,18 @@ import {
|
||||
ProjectGrantMembersDataSource,
|
||||
} from 'src/app/pages/projects/owned-projects/project-grant-detail/project-grant-members-datasource';
|
||||
import { Member } from 'src/app/proto/generated/zitadel/member_pb';
|
||||
import { getMembershipColor } from 'src/app/utils/color';
|
||||
|
||||
import { AddMemberRolesDialogComponent } from '../add-member-roles-dialog/add-member-roles-dialog.component';
|
||||
import { PageEvent, PaginatorComponent } from '../paginator/paginator.component';
|
||||
import { ProjectMembersDataSource } from '../project-members/project-members-datasource';
|
||||
import { WarnDialogComponent } from '../warn-dialog/warn-dialog.component';
|
||||
|
||||
type MemberDatasource = OrgMembersDataSource | ProjectMembersDataSource | ProjectGrantMembersDataSource | IamMembersDataSource;
|
||||
type MemberDatasource =
|
||||
| OrgMembersDataSource
|
||||
| ProjectMembersDataSource
|
||||
| ProjectGrantMembersDataSource
|
||||
| IamMembersDataSource;
|
||||
|
||||
@Component({
|
||||
selector: 'cnsl-members-table',
|
||||
@@ -32,17 +39,15 @@ export class MembersTableComponent implements OnInit, OnDestroy {
|
||||
@Input() public memberRoleOptions: string[] = [];
|
||||
@Input() public factoryLoadFunc!: Function;
|
||||
@Input() public refreshTrigger!: Observable<void>;
|
||||
@Output() public updateRoles: EventEmitter<{ member: Member.AsObject, change: MatSelectChange; }> = new EventEmitter();
|
||||
@Output() public updateRoles: EventEmitter<{ member: Member.AsObject; change: string[] }> = new EventEmitter();
|
||||
@Output() public changedSelection: EventEmitter<any[]> = new EventEmitter();
|
||||
@Output() public deleteMember: EventEmitter<Member.AsObject> = new EventEmitter();
|
||||
|
||||
private destroyed: Subject<void> = new Subject();
|
||||
public displayedColumns: string[] = ['select', 'userId', 'displayName', 'loginname', 'email', 'roles'];
|
||||
|
||||
/** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */
|
||||
public displayedColumns: string[] = ['select', 'userId', 'firstname', 'lastname', 'loginname', 'email', 'roles'];
|
||||
|
||||
constructor() {
|
||||
this.selection.changed.pipe(takeUntil(this.destroyed)).subscribe(_ => {
|
||||
constructor(private dialog: MatDialog) {
|
||||
this.selection.changed.pipe(takeUntil(this.destroyed)).subscribe((_) => {
|
||||
this.changedSelection.emit(this.selection.selected);
|
||||
});
|
||||
}
|
||||
@@ -52,7 +57,7 @@ export class MembersTableComponent implements OnInit, OnDestroy {
|
||||
this.changePage(this.paginator);
|
||||
});
|
||||
|
||||
if (this.canDelete) {
|
||||
if (this.canDelete || this.canWrite) {
|
||||
this.displayedColumns.push('actions');
|
||||
}
|
||||
}
|
||||
@@ -61,6 +66,52 @@ export class MembersTableComponent implements OnInit, OnDestroy {
|
||||
this.destroyed.next();
|
||||
}
|
||||
|
||||
public getColor(role: string) {
|
||||
return getMembershipColor(role)[500];
|
||||
}
|
||||
|
||||
public removeRole(member: Member.AsObject, role: string) {
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
confirmKey: 'ACTIONS.DELETE',
|
||||
cancelKey: 'ACTIONS.CANCEL',
|
||||
titleKey: 'GRANTS.DIALOG.DELETE_TITLE',
|
||||
descriptionKey: 'GRANTS.DIALOG.DELETE_DESCRIPTION',
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((resp) => {
|
||||
if (resp) {
|
||||
const newRoles = Object.assign([], member.rolesList);
|
||||
const index = newRoles.findIndex((r) => r === role);
|
||||
if (index > -1) {
|
||||
newRoles.splice(index);
|
||||
member.rolesList = newRoles;
|
||||
this.updateRoles.emit({ member: member, change: newRoles });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public addRole(member: Member.AsObject) {
|
||||
const dialogRef = this.dialog.open(AddMemberRolesDialogComponent, {
|
||||
data: {
|
||||
user: member.displayName,
|
||||
allRoles: this.memberRoleOptions,
|
||||
selectedRoles: member.rolesList,
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((resp) => {
|
||||
if (resp && resp.length) {
|
||||
member.rolesList = resp;
|
||||
this.updateRoles.emit({ member: member, change: resp });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public isAllSelected(): boolean {
|
||||
const numSelected = this.selection.selected.length;
|
||||
const numRows = this.dataSource.membersSubject.value.length;
|
||||
@@ -68,9 +119,9 @@ export class MembersTableComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public masterToggle(): void {
|
||||
this.isAllSelected() ?
|
||||
this.selection.clear() :
|
||||
this.dataSource.membersSubject.value.forEach(row => this.selection.select(row));
|
||||
this.isAllSelected()
|
||||
? this.selection.clear()
|
||||
: this.dataSource.membersSubject.value.forEach((row) => this.selection.select(row));
|
||||
}
|
||||
|
||||
public changePage(event?: PageEvent): any {
|
||||
@@ -79,6 +130,20 @@ export class MembersTableComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
public triggerDeleteMember(member: any): void {
|
||||
this.deleteMember.emit(member);
|
||||
const dialogRef = this.dialog.open(WarnDialogComponent, {
|
||||
data: {
|
||||
confirmKey: 'ACTIONS.DELETE',
|
||||
cancelKey: 'ACTIONS.CANCEL',
|
||||
titleKey: 'MEMBER.DIALOG.DELETE_TITLE',
|
||||
descriptionKey: 'MEMBER.DIALOG.DELETE_DESCRIPTION',
|
||||
},
|
||||
width: '400px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((resp) => {
|
||||
if (resp) {
|
||||
this.deleteMember.emit(member);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatChipsModule } from '@angular/material/chips';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatSortModule } from '@angular/material/sort';
|
||||
@@ -11,35 +12,40 @@ import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { InputModule } from 'src/app/modules/input/input.module';
|
||||
import { RoleTransformPipeModule } from 'src/app/pipes/role-transform/role-transform.module';
|
||||
|
||||
import { AddMemberRolesDialogModule } from '../add-member-roles-dialog/add-member-roles-dialog.module';
|
||||
import { AvatarModule } from '../avatar/avatar.module';
|
||||
import { PaginatorModule } from '../paginator/paginator.module';
|
||||
import { RefreshTableModule } from '../refresh-table/refresh-table.module';
|
||||
import { TableActionsModule } from '../table-actions/table-actions.module';
|
||||
import { WarnDialogModule } from '../warn-dialog/warn-dialog.module';
|
||||
import { MembersTableComponent } from './members-table.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
MembersTableComponent,
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
InputModule,
|
||||
MatSelectModule,
|
||||
MatCheckboxModule,
|
||||
MatIconModule,
|
||||
MatTableModule,
|
||||
PaginatorModule,
|
||||
MatSortModule,
|
||||
MatTooltipModule,
|
||||
FormsModule,
|
||||
TranslateModule,
|
||||
RefreshTableModule,
|
||||
RouterModule,
|
||||
AvatarModule,
|
||||
MatButtonModule,
|
||||
],
|
||||
exports: [
|
||||
MembersTableComponent,
|
||||
],
|
||||
declarations: [MembersTableComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
InputModule,
|
||||
MatSelectModule,
|
||||
MatCheckboxModule,
|
||||
MatIconModule,
|
||||
MatTableModule,
|
||||
MatChipsModule,
|
||||
RoleTransformPipeModule,
|
||||
PaginatorModule,
|
||||
AddMemberRolesDialogModule,
|
||||
MatSortModule,
|
||||
MatTooltipModule,
|
||||
FormsModule,
|
||||
TranslateModule,
|
||||
WarnDialogModule,
|
||||
RefreshTableModule,
|
||||
TableActionsModule,
|
||||
RouterModule,
|
||||
AvatarModule,
|
||||
MatButtonModule,
|
||||
],
|
||||
exports: [MembersTableComponent],
|
||||
})
|
||||
export class MembersTableModule { }
|
||||
export class MembersTableModule {}
|
||||
|
||||
Reference in New Issue
Block a user