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:
Max Peintner
2022-04-28 10:35:02 +00:00
committed by GitHub
co-authored by Livio Amstutz
parent 00f7dbe875
commit 08ae39ae19
668 changed files with 47746 additions and 19117 deletions
@@ -1,70 +1,72 @@
<cnsl-refresh-table [loading]="loading$ | async" (refreshed)="refreshPage()" [dataSize]="dataSource.data.length"
[timestamp]="keyResult?.details?.viewTimestamp" [selection]="selection">
<div actions>
<a [disabled]="([('user.write:' + userId), 'user.write'] | hasRole | async) === false" color="primary"
mat-raised-button (click)="openAddKey()">
<mat-icon class="icon">add</mat-icon>{{ 'ACTIONS.NEW' | translate }}
</a>
</div>
[timestamp]="keyResult?.details?.viewTimestamp" [selection]="selection">
<div actions>
<a [disabled]="([('user.write:' + userId), 'user.write'] | hasRole | async) === false" color="primary"
mat-raised-button (click)="openAddKey()">
<mat-icon class="icon">add</mat-icon>{{ 'ACTIONS.NEW' | translate }}
</a>
</div>
<div class="table-wrapper">
<table class="table" mat-table [dataSource]="dataSource">
<ng-container matColumnDef="select">
<th mat-header-cell *matHeaderCellDef>
<mat-checkbox color="primary" (change)="$event ? masterToggle() : null"
[checked]="selection.hasValue() && isAllSelected()"
[indeterminate]="selection.hasValue() && !isAllSelected()">
</mat-checkbox>
</th>
<td mat-cell *matCellDef="let key">
<mat-checkbox color="primary" (click)="$event.stopPropagation()"
(change)="$event ? selection.toggle(key) : null" [checked]="selection.isSelected(key)">
</mat-checkbox>
</td>
</ng-container>
<div class="table-wrapper">
<table class="table" mat-table [dataSource]="dataSource">
<ng-container matColumnDef="select">
<th mat-header-cell *matHeaderCellDef>
<mat-checkbox color="primary" (change)="$event ? masterToggle() : null"
[checked]="selection.hasValue() && isAllSelected()"
[indeterminate]="selection.hasValue() && !isAllSelected()">
</mat-checkbox>
</th>
<td mat-cell *matCellDef="let key">
<mat-checkbox color="primary" (click)="$event.stopPropagation()"
(change)="$event ? selection.toggle(key) : null" [checked]="selection.isSelected(key)">
</mat-checkbox>
</td>
</ng-container>
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef> {{ 'USER.MACHINE.ID' | translate }} </th>
<td mat-cell *matCellDef="let key"> {{key?.id}} </td>
</ng-container>
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef> {{ 'USER.MACHINE.ID' | translate }} </th>
<td mat-cell *matCellDef="let key"> {{key?.id}} </td>
</ng-container>
<ng-container matColumnDef="type">
<th mat-header-cell *matHeaderCellDef> {{ 'USER.MACHINE.TYPE' | translate }} </th>
<td mat-cell *matCellDef="let key"> {{'USER.MACHINE.KEYTYPES.'+key?.type | translate}} </td>
</ng-container>
<ng-container matColumnDef="type">
<th mat-header-cell *matHeaderCellDef> {{ 'USER.MACHINE.TYPE' | translate }} </th>
<td mat-cell *matCellDef="let key"> {{'USER.MACHINE.KEYTYPES.'+key?.type | translate}} </td>
</ng-container>
<ng-container matColumnDef="creationDate">
<th mat-header-cell *matHeaderCellDef> {{ 'USER.MACHINE.CREATIONDATE' | translate }} </th>
<td mat-cell *matCellDef="let key">
{{key.details?.creationDate | timestampToDate | localizedDate: 'EEE dd. MMM YYYY, HH:mm'}}
</td>
</ng-container>
<ng-container matColumnDef="creationDate">
<th mat-header-cell *matHeaderCellDef> {{ 'USER.MACHINE.CREATIONDATE' | translate }} </th>
<td mat-cell *matCellDef="let key">
{{key.details?.creationDate | timestampToDate | localizedDate: 'fromNow'}}
</td>
</ng-container>
<ng-container matColumnDef="expirationDate">
<th mat-header-cell *matHeaderCellDef> {{ 'USER.MACHINE.EXPIRATIONDATE' | translate }} </th>
<td mat-cell *matCellDef="let key">
{{key.expirationDate | timestampToDate | localizedDate: 'EEE dd. MMM YYYY, HH:mm'}}
</td>
</ng-container>
<ng-container matColumnDef="expirationDate">
<th mat-header-cell *matHeaderCellDef> {{ 'USER.MACHINE.EXPIRATIONDATE' | translate }} </th>
<td mat-cell *matCellDef="let key">
{{key.expirationDate | timestampToDate | localizedDate: 'fromNow'}}
</td>
</ng-container>
<ng-container matColumnDef="actions" stickyEnd>
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let key">
<button [disabled]="([('user.write:' + userId), 'user.write'] | hasRole | async) === false"
mat-icon-button color="warn" matTooltip="{{'ACTIONS.DELETE' | translate}}"
(click)="deleteKey(key)">
<i class="las la-trash"></i>
</button>
</td>
</ng-container>
<ng-container matColumnDef="actions" stickyEnd>
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let key">
<cnsl-table-actions>
<button actions [disabled]="([('user.write:' + userId), 'user.write'] | hasRole | async) === false"
mat-icon-button color="warn" matTooltip="{{'ACTIONS.DELETE' | translate}}" (click)="deleteKey(key)">
<i class="las la-trash"></i>
</button>
</cnsl-table-actions>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns;">
</tr>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr class="highlight" mat-row *matRowDef="let row; columns: displayedColumns;">
</tr>
</table>
</div>
<cnsl-paginator #paginator class="paginator" [timestamp]="keyResult?.details?.viewTimestamp"
[length]="keyResult?.details?.totalResult || 0" [pageSize]="20" [pageSizeOptions]="[10, 20, 50, 100]"
(page)="changePage()"></cnsl-paginator>
</table>
<cnsl-paginator #paginator class="paginator" [timestamp]="keyResult?.details?.viewTimestamp" [length]="keyResult?.details?.totalResult || 0" [pageSize]="10"
[pageSizeOptions]="[5, 10, 20]" (page)="changePage($event)"></cnsl-paginator>
</div>
</cnsl-refresh-table>
@@ -1,27 +1,3 @@
.table-wrapper {
overflow: auto;
.table,
.paginator {
width: 100%;
td,
th {
padding: 0 1rem;
&:first-child {
padding-left: 0;
padding-right: 1rem;
}
&:last-child {
padding-right: 0;
}
}
}
}
tr {
outline: none;
@@ -13,7 +13,8 @@ import { ListMachineKeysResponse } from 'src/app/proto/generated/zitadel/managem
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
import { PageEvent, PaginatorComponent } from '../paginator/paginator.component';
import { PaginatorComponent } from '../paginator/paginator.component';
import { WarnDialogComponent } from '../warn-dialog/warn-dialog.component';
@Component({
selector: 'cnsl-machine-keys',
@@ -29,12 +30,16 @@ export class MachineKeysComponent implements OnInit {
public keyResult!: ListMachineKeysResponse.AsObject;
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
@Input() public displayedColumns: string[] = ['select', 'id', 'type', 'creationDate', 'expirationDate', 'actions'];
@Input() public displayedColumns: string[] = ['id', 'type', 'creationDate', 'expirationDate', 'actions'];
@Output() public changedSelection: EventEmitter<Array<Key.AsObject>> = new EventEmitter();
constructor(public translate: TranslateService, private mgmtService: ManagementService, private dialog: MatDialog,
private toast: ToastService) {
constructor(
public translate: TranslateService,
private mgmtService: ManagementService,
private dialog: MatDialog,
private toast: ToastService,
) {
this.selection.changed.subscribe(() => {
this.changedSelection.emit(this.selection.selected);
});
@@ -44,7 +49,6 @@ export class MachineKeysComponent implements OnInit {
this.getData(10, 0);
}
public isAllSelected(): boolean {
const numSelected = this.selection.selected.length;
const numRows = this.dataSource.data.length;
@@ -52,23 +56,36 @@ export class MachineKeysComponent implements OnInit {
}
public masterToggle(): void {
this.isAllSelected() ?
this.selection.clear() :
this.dataSource.data.forEach(row => this.selection.select(row));
this.isAllSelected() ? this.selection.clear() : this.dataSource.data.forEach((row) => this.selection.select(row));
}
public changePage(event: PageEvent): void {
this.getData(event.pageSize, event.pageIndex * event.pageSize);
public changePage(): void {
this.getData(this.paginator.pageSize, this.paginator.pageIndex * this.paginator.pageSize);
}
public deleteKey(key: Key.AsObject): void {
this.mgmtService.removeMachineKey(key.id, this.userId).then(() => {
this.selection.clear();
this.toast.showInfo('USER.TOAST.SELECTEDKEYSDELETED', true);
this.getData(10, 0);
}).catch(error => {
this.toast.showError(error);
const dialogRef = this.dialog.open(WarnDialogComponent, {
data: {
confirmKey: 'ACTIONS.DELETE',
cancelKey: 'ACTIONS.CANCEL',
titleKey: 'USER.MACHINE.DIALOG.DELETE_KEY.TITLE',
descriptionKey: 'USER.MACHINE.DIALOG.DELETE_KEY.DESCRIPTION',
},
width: '400px',
});
dialogRef.afterClosed().subscribe((resp) => {
if (resp) {
this.mgmtService
.removeMachineKey(key.id, this.userId)
.then(() => {
this.selection.clear();
this.toast.showInfo('USER.TOAST.SELECTEDKEYSDELETED', true);
this.changePage();
})
.catch((error) => {
this.toast.showError(error);
});
}
});
}
@@ -78,7 +95,7 @@ export class MachineKeysComponent implements OnInit {
width: '400px',
});
dialogRef.afterClosed().subscribe(resp => {
dialogRef.afterClosed().subscribe((resp) => {
if (resp) {
const type: KeyType = resp.type;
@@ -95,23 +112,26 @@ export class MachineKeysComponent implements OnInit {
}
if (type) {
this.mgmtService.addMachineKey(this.userId, type, date).then((response) => {
if (response) {
setTimeout(() => {
this.refreshPage();
}, 1000);
this.mgmtService
.addMachineKey(this.userId, type, date)
.then((response) => {
if (response) {
setTimeout(() => {
this.refreshPage();
}, 1000);
this.dialog.open(ShowKeyDialogComponent, {
data: {
key: response,
type: AddKeyDialogType.MACHINE,
},
width: '400px',
});
}
}).catch((error: any) => {
this.toast.showError(error);
});
this.dialog.open(ShowKeyDialogComponent, {
data: {
key: response,
type: AddKeyDialogType.MACHINE,
},
width: '400px',
});
}
})
.catch((error: any) => {
this.toast.showError(error);
});
}
}
});
@@ -121,16 +141,19 @@ export class MachineKeysComponent implements OnInit {
this.loadingSubject.next(true);
if (this.userId) {
this.mgmtService.listMachineKeys(this.userId, limit, offset).then(resp => {
this.keyResult = resp;
if (resp.resultList) {
this.dataSource.data = resp.resultList;
}
this.loadingSubject.next(false);
}).catch((error: any) => {
this.toast.showError(error);
this.loadingSubject.next(false);
});
this.mgmtService
.listMachineKeys(this.userId, limit, offset)
.then((resp) => {
this.keyResult = resp;
if (resp.resultList) {
this.dataSource.data = resp.resultList;
}
this.loadingSubject.next(false);
})
.catch((error: any) => {
this.toast.showError(error);
this.loadingSubject.next(false);
});
}
}
@@ -21,38 +21,37 @@ import { InputModule } from '../input/input.module';
import { PaginatorModule } from '../paginator/paginator.module';
import { RefreshTableModule } from '../refresh-table/refresh-table.module';
import { ShowKeyDialogModule } from '../show-key-dialog/show-key-dialog.module';
import { TableActionsModule } from '../table-actions/table-actions.module';
import { WarnDialogModule } from '../warn-dialog/warn-dialog.module';
import { MachineKeysComponent } from './machine-keys.component';
@NgModule({
declarations: [
MachineKeysComponent,
],
imports: [
CommonModule,
RouterModule,
FormsModule,
MatButtonModule,
MatDialogModule,
HasRoleModule,
CardModule,
MatTableModule,
PaginatorModule,
MatIconModule,
MatProgressSpinnerModule,
MatCheckboxModule,
MatTooltipModule,
HasRolePipeModule,
TimestampToDatePipeModule,
LocalizedDatePipeModule,
TranslateModule,
RefreshTableModule,
InputModule,
ShowKeyDialogModule,
AddKeyDialogModule,
],
exports: [
MachineKeysComponent,
],
declarations: [MachineKeysComponent],
imports: [
CommonModule,
RouterModule,
FormsModule,
MatButtonModule,
MatDialogModule,
HasRoleModule,
CardModule,
MatTableModule,
PaginatorModule,
MatIconModule,
MatProgressSpinnerModule,
MatCheckboxModule,
TableActionsModule,
WarnDialogModule,
MatTooltipModule,
HasRolePipeModule,
TimestampToDatePipeModule,
LocalizedDatePipeModule,
TranslateModule,
RefreshTableModule,
InputModule,
ShowKeyDialogModule,
AddKeyDialogModule,
],
exports: [MachineKeysComponent],
})
export class MachineKeysModule { }
export class MachineKeysModule {}