feat: failed events (#582)

This commit is contained in:
Max Peintner 2020-08-13 07:42:16 +02:00 committed by GitHub
parent 65058ed17c
commit 2f404be7c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 300 additions and 130 deletions

View File

@ -4,15 +4,15 @@
<p class="desc"> {{'PROJECT.ROLE.EDITDESCRIPTION' | translate}}</p>
<div mat-dialog-content>
<form *ngIf="formGroup" class="full-width" [formGroup]="formGroup" (ngSubmit)="submitForm()">
<mat-form-field class="formfield">
<mat-form-field class="formfield" appearance="outline">
<mat-label>{{ 'PROJECT.ROLE.KEY' | translate }}</mat-label>
<input matInput formControlName="key" />
</mat-form-field>
<mat-form-field class="formfield">
<mat-form-field class="formfield" appearance="outline">
<mat-label>{{ 'PROJECT.ROLE.DISPLAY_NAME' | translate }}</mat-label>
<input matInput formControlName="displayName" />
</mat-form-field>
<mat-form-field class="formfield">
<mat-form-field class="formfield" appearance="outline">
<mat-label>{{ 'PROJECT.ROLE.GROUP' | translate }}</mat-label>
<input matInput formControlName="group" />
</mat-form-field>

View File

@ -0,0 +1,54 @@
<div class="table-wrapper">
<app-refresh-table *ngIf="eventDataSource" (refreshed)="loadEvents()" [dataSize]="eventDataSource.data.length"
[loading]="loading$ | async">
<table [dataSource]="eventDataSource" mat-table class="table background-style" aria-label="Elements">
<ng-container matColumnDef="viewName">
<th mat-header-cell *matHeaderCellDef> {{ 'IAM.FAILEDEVENTS.VIEWNAME' | translate }} </th>
<td mat-cell *matCellDef="let event"> {{event.viewName}} </td>
</ng-container>
<ng-container matColumnDef="database">
<th mat-header-cell *matHeaderCellDef> {{ 'IAM.FAILEDEVENTS.DATABASE' | translate }} </th>
<td mat-cell *matCellDef="let event"> {{event.database}} </td>
</ng-container>
<ng-container matColumnDef="failedSequence">
<th mat-header-cell *matHeaderCellDef> {{ 'IAM.FAILEDEVENTS.FAILEDSEQUENCE' | translate }} </th>
<td mat-cell *matCellDef="let event">
<span class="role app-label">{{event?.failedSequence}}</span>
</td>
</ng-container>
<ng-container matColumnDef="failureCount">
<th mat-header-cell *matHeaderCellDef> {{ 'IAM.FAILEDEVENTS.FAILURECOUNT' | translate }} </th>
<td mat-cell *matCellDef="let event">
<span>{{event?.failureCount }}</span>
</td>
</ng-container>
<ng-container matColumnDef="errorMessage">
<th mat-header-cell *matHeaderCellDef> {{ 'IAM.FAILEDEVENTS.ERRORMESSAGE' | translate }} </th>
<td mat-cell *matCellDef="let event">
<span>{{event?.errorMessage }}</span>
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> {{ 'IAM.FAILEDEVENTS.ACTIONS' | translate }} </th>
<td mat-cell *matCellDef="let event">
<button color="warn" mat-icon-button matTooltip="{{'IAM.FAILEDEVENTS.DELETE' | translate}}"
(click)="cancelEvent(event.viewName, event.database, event.failedSequence)">
<i class="las la-minus-circle"></i>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="eventDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: eventDisplayedColumns;"></tr>
</table>
<mat-paginator class="paginator background-style" [pageSize]="10" #paginator
[pageSizeOptions]="[10, 20, 100, 250]">
</mat-paginator>
</app-refresh-table>
</div>

View File

@ -0,0 +1,33 @@
.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;
}
}
.selection {
width: 50px;
max-width: 50px;
}
}
}
.pointer {
outline: none;
cursor: pointer;
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FailedEventsComponent } from './failed-events.component';
describe('FailedEventsComponent', () => {
let component: FailedEventsComponent;
let fixture: ComponentFixture<FailedEventsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [FailedEventsComponent],
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(FailedEventsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,46 @@
import { Component, ViewChild } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table';
import { BehaviorSubject, from, Observable, of } from 'rxjs';
import { catchError, finalize, map } from 'rxjs/operators';
import { FailedEvent } from 'src/app/proto/generated/admin_pb';
import { AdminService } from 'src/app/services/admin.service';
import { ToastService } from 'src/app/services/toast.service';
@Component({
selector: 'app-iam-failed-events',
templateUrl: './failed-events.component.html',
styleUrls: ['./failed-events.component.scss'],
})
export class FailedEventsComponent {
@ViewChild(MatPaginator) public eventPaginator!: MatPaginator;
public eventDataSource!: MatTableDataSource<FailedEvent.AsObject>;
public eventDisplayedColumns: string[] = ['viewName', 'database', 'failedSequence', 'failureCount', 'errorMessage', 'actions'];
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
constructor(private adminService: AdminService, private toast: ToastService) {
this.loadEvents();
}
public loadEvents(): void {
this.loadingSubject.next(true);
from(this.adminService.GetFailedEvents()).pipe(
map(resp => {
return resp.toObject().failedEventsList;
}),
catchError(() => of([])),
finalize(() => this.loadingSubject.next(false)),
).subscribe(views => {
this.eventDataSource = new MatTableDataSource(views);
this.eventDataSource.paginator = this.eventPaginator;
});
}
public cancelEvent(viewname: string, db: string, seq: number): void {
this.adminService.RemoveFailedEvent(viewname, db, seq).then(() => {
this.toast.showInfo('IAM.FAILEDEVENTS.DELETESUCCESS', true);
});
}
}

View File

@ -1,55 +1,47 @@
<div class="table-header-row">
<div class="col">
<span class="desc">{{'ORG_DETAIL.TABLE.TOTAL' | translate}}</span>
<span class="count">{{dataSource?.data?.length}}</span>
</div>
<span class="fill-space"></span>
</div>
<div class="table-wrapper">
<div class="spinner-container" *ngIf="loading$ | async">
<mat-spinner diameter="50"></mat-spinner>
</div>
<app-refresh-table *ngIf="dataSource" (refreshed)="loadViews()" [dataSize]="dataSource.data.length"
[loading]="loading$ | async">
<table *ngIf="dataSource" [dataSource]="dataSource" mat-table class="table background-style" matSort
aria-label="Elements">
<ng-container matColumnDef="viewName">
<th mat-header-cell mat-sort-header *matHeaderCellDef> {{ 'IAM.VIEWS.VIEWNAME' | translate }} </th>
<td mat-cell *matCellDef="let role"> {{role.viewName}} </td>
</ng-container>
<table [dataSource]="dataSource" mat-table class="table background-style" aria-label="Elements">
<ng-container matColumnDef="viewName">
<th mat-header-cell *matHeaderCellDef> {{ 'IAM.VIEWS.VIEWNAME' | translate }} </th>
<td mat-cell *matCellDef="let view"> {{view.viewName}} </td>
</ng-container>
<ng-container matColumnDef="database">
<th mat-header-cell mat-sort-header *matHeaderCellDef> {{ 'IAM.VIEWS.DATABASE' | translate }} </th>
<td mat-cell *matCellDef="let role"> {{role.database}} </td>
</ng-container>
<ng-container matColumnDef="database">
<th mat-header-cell *matHeaderCellDef> {{ 'IAM.VIEWS.DATABASE' | translate }} </th>
<td mat-cell *matCellDef="let view"> {{view.database}} </td>
</ng-container>
<ng-container matColumnDef="sequence">
<th mat-header-cell mat-sort-header *matHeaderCellDef> {{ 'IAM.VIEWS.SEQUENCE' | translate }} </th>
<td mat-cell *matCellDef="let role">
<span class="role app-label">{{role?.processedSequence}}</span>
</td>
</ng-container>
<ng-container matColumnDef="sequence">
<th mat-header-cell *matHeaderCellDef> {{ 'IAM.VIEWS.SEQUENCE' | translate }} </th>
<td mat-cell *matCellDef="let view">
<span>{{view?.processedSequence}}</span>
</td>
</ng-container>
<ng-container matColumnDef="timestamp">
<th mat-header-cell mat-sort-header *matHeaderCellDef> {{ 'IAM.VIEWS.SEQUENCE' | translate }} </th>
<td mat-cell *matCellDef="let role">
<span>{{role?.viewTimestamp | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }}</span>
</td>
</ng-container>
<ng-container matColumnDef="timestamp">
<th mat-header-cell *matHeaderCellDef> {{ 'IAM.VIEWS.TIMESTAMP' | translate }} </th>
<td mat-cell *matCellDef="let view">
<span>{{view?.viewTimestamp | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }}</span>
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> {{ 'IAM.VIEWS.ACTIONS' | translate }} </th>
<td mat-cell *matCellDef="let role">
<button mat-icon-button matTooltip="{{'IAM.VIEWS.CLEAR' | translate}}"
(click)="cancelView(role.viewName, role.database)">
<mat-icon svgIcon="mdi_broom"></mat-icon>
</button>
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> {{ 'IAM.VIEWS.ACTIONS' | translate }} </th>
<td mat-cell *matCellDef="let view">
<button mat-icon-button matTooltip="{{'IAM.VIEWS.CLEAR' | translate}}"
(click)="cancelView(view.viewName, view.database)">
<mat-icon svgIcon="mdi_broom"></mat-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator class="paginator background-style" #paginator [pageSize]="10" [pageSizeOptions]="[10, 20, 100, 250]">
</mat-paginator>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator class="paginator background-style" [pageSize]="10" #paginator
[pageSizeOptions]="[10, 20, 100, 250]">
</mat-paginator>
</app-refresh-table>
</div>

View File

@ -1,40 +1,7 @@
.table-header-row {
display: flex;
align-items: center;
.col {
display: flex;
flex-direction: column;
.desc {
font-size: .8rem;
color: #8795a1;
}
.count {
font-size: 2rem;
}
}
.fill-space {
flex: 1;
}
.icon-button {
margin-right: .5rem;
}
}
.table-wrapper {
overflow: auto;
.spinner-container {
display: flex;
align-items: center;
justify-content: center;
}
.table,
.paginator {
width: 100%;

View File

@ -1,7 +1,6 @@
import { Component, ViewChild } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTable, MatTableDataSource } from '@angular/material/table';
import { MatTableDataSource } from '@angular/material/table';
import { BehaviorSubject, from, Observable, of } from 'rxjs';
import { catchError, finalize, map } from 'rxjs/operators';
import { View } from 'src/app/proto/generated/admin_pb';
@ -13,15 +12,11 @@ import { AdminService } from 'src/app/services/admin.service';
styleUrls: ['./iam-views.component.scss'],
})
export class IamViewsComponent {
public views: View.AsObject[] = [];
@ViewChild(MatPaginator) public paginator!: MatPaginator;
@ViewChild(MatTable) public table!: MatTable<View.AsObject>;
@ViewChild(MatSort) public sort!: MatSort;
public dataSource!: MatTableDataSource<View.AsObject>;
public displayedColumns: string[] = ['viewName', 'database', 'sequence', 'timestamp', 'actions'];
private loadingSubject: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
public loading$: Observable<boolean> = this.loadingSubject.asObservable();
constructor(private adminService: AdminService) {
@ -39,7 +34,6 @@ export class IamViewsComponent {
).subscribe(views => {
this.dataSource = new MatTableDataSource(views);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
});
}

View File

@ -6,6 +6,11 @@
<app-card title="{{ 'IAM.VIEWS.TITLE' | translate }}" description="{{ 'IAM.VIEWS.DESCRIPTION' | translate }}">
<app-iam-views></app-iam-views>
</app-card>
<app-card title="{{ 'IAM.FAILEDEVENTS.TITLE' | translate }}"
description="{{ 'IAM.FAILEDEVENTS.DESCRIPTION' | translate }}">
<app-iam-failed-events></app-iam-failed-events>
</app-card>
</div>
<div class="side" metainfo>

View File

@ -20,18 +20,19 @@ import { CardModule } from 'src/app/modules/card/card.module';
import { ChangesModule } from 'src/app/modules/changes/changes.module';
import { ContributorsModule } from 'src/app/modules/contributors/contributors.module';
import { MetaLayoutModule } from 'src/app/modules/meta-layout/meta-layout.module';
import { RefreshTableModule } from 'src/app/modules/refresh-table/refresh-table.module';
import { SharedModule } from 'src/app/modules/shared/shared.module';
import { LocalizedDatePipeModule } from 'src/app/pipes/localized-date-pipe.module';
import { TimestampToDatePipeModule } from 'src/app/pipes/timestamp-to-date-pipe.module';
import { FailedEventsComponent } from './failed-events/failed-events.component';
import { IamRoutingModule } from './iam-routing.module';
import { IamViewsComponent } from './iam-views/iam-views.component';
import { IamComponent } from './iam.component';
@NgModule({
declarations: [IamComponent, IamViewsComponent],
declarations: [IamComponent, IamViewsComponent, FailedEventsComponent],
imports: [
CommonModule,
IamRoutingModule,
@ -59,6 +60,7 @@ import { IamComponent } from './iam.component';
LocalizedDatePipeModule,
TimestampToDatePipeModule,
SharedModule,
RefreshTableModule,
],
})
export class IamModule { }

View File

@ -2,7 +2,7 @@
<div mat-dialog-content>
<p class="desc"> {{'ORG.DOMAINS.ADD.DESCRIPTION' | translate}}</p>
<mat-form-field label="Domain" required="true" class="form-field">
<mat-form-field label="Domain" required="true" class="form-field" appearance="outline">
<mat-label>Domain</mat-label>
<input matInput [(ngModel)]="newdomain" />
</mat-form-field>
@ -12,7 +12,8 @@
{{'ACTIONS.CANCEL' | translate}}
</button>
<button color="warn" mat-raised-button class="ok-button" [disabled]="!newdomain" (click)="closeDialogWithSuccess()">
<button color="primary" mat-raised-button class="ok-button" [disabled]="!newdomain"
(click)="closeDialogWithSuccess()">
{{'ACTIONS.ADD' | translate}}
</button>
</div>

View File

@ -26,7 +26,7 @@
<button [disabled]="complexityPolicy" [routerLink]="[ 'policy', PolicyComponentType.COMPLEXITY,'create' ]"
color="primary" mat-raised-button>{{'ORG.POLICY.BTN_INSTALL' | translate}}</button>
<button [disabled]="!complexityPolicy" [routerLink]="[ 'policy', PolicyComponentType.COMPLEXITY ]"
mat-raised-button>{{'ORG.POLICY.BTN_EDIT' | translate}}</button>
mat-stroked-button>{{'ORG.POLICY.BTN_EDIT' | translate}}</button>
</div>
</div>
@ -55,7 +55,7 @@
<button [disabled]="iamPolicy" [routerLink]="[ 'policy', PolicyComponentType.IAM_POLICY,'create' ]"
color="primary" mat-raised-button>{{'ORG.POLICY.BTN_INSTALL' | translate}}</button>
<button [disabled]="!iamPolicy" [routerLink]="[ 'policy', PolicyComponentType.IAM_POLICY ]"
mat-raised-button>{{'ORG.POLICY.BTN_EDIT' | translate}}</button>
mat-stroked-button>{{'ORG.POLICY.BTN_EDIT' | translate}}</button>
</ng-template>
</div>
</div>

View File

@ -34,7 +34,7 @@
<mat-form-field *ngIf="editstate && project?.name" class="formfield"
hintLabel="The name is required!">
<mat-label>{{'PROJECT.NAME' | translate}}</mat-label>
<input matInput [(ngModel)]="project.name" />
<input matInput [(ngModel)]="project.name" name="name" />
</mat-form-field>
<button class="icon-button" *ngIf="editstate" mat-icon-button (click)="updateName()">
<mat-icon>check</mat-icon>

View File

@ -1,11 +1,12 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatRippleModule } from '@angular/material/core';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSelectModule } from '@angular/material/select';
@ -45,7 +46,9 @@ import { ProjectGrantsComponent } from './project-grants/project-grants.componen
FormsModule,
OwnedProjectDetailRoutingModule,
TranslateModule,
ReactiveFormsModule,
HasRoleModule,
MatInputModule,
MatTabsModule,
MatButtonModule,
MatIconModule,

View File

@ -1,25 +1,25 @@
<div class="container">
<div class="abort-container">
<button (click)="close()" mat-icon-button>
<mat-icon>close</mat-icon>
</button>
<span class="abort">{{ 'PROJECT.PAGES.CREATE' | translate }}</span><span class="abort-2">Step
{{ currentCreateStep }} of
{{ createSteps }}</span>
</div>
<h1>{{'PROJECT.PAGES.CREATE_DESC' | translate}}</h1>
<form (ngSubmit)="saveProject()">
<div class="column">
<mat-form-field class="formfield" hintLabel="The name is required!">
<mat-label>{{'PROJECT.NAME' | translate}}</mat-label>
<input matInput autofocus [(ngModel)]="project.name" [ngModelOptions]="{ standalone: true }" />
</mat-form-field>
<div class="abort-container">
<button (click)="close()" mat-icon-button>
<mat-icon>close</mat-icon>
</button>
<span class="abort">{{ 'PROJECT.PAGES.CREATE' | translate }}</span><span class="abort-2">Step
{{ currentCreateStep }} of
{{ createSteps }}</span>
</div>
<button color="primary" mat-raised-button class="continue-button" [disabled]="!project.name" cdkFocusInitial
type="submit">
{{'CONTINUE' | translate}}
</button>
</form>
<h1>{{'PROJECT.PAGES.CREATE_DESC' | translate}}</h1>
<form (ngSubmit)="saveProject()">
<div class="column">
<mat-form-field class="formfield" hintLabel="The name is required!">
<mat-label>{{'PROJECT.NAME' | translate}}</mat-label>
<input matInput autofocus [(ngModel)]="project.name" [ngModelOptions]="{ standalone: true }" />
</mat-form-field>
</div>
<button color="primary" mat-raised-button class="continue-button" [disabled]="!project.name" cdkFocusInitial
type="submit">
{{'CONTINUE' | translate}}
</button>
</form>
</div>

View File

@ -1,22 +1,22 @@
<form [formGroup]="profileForm" *ngIf="profileForm" (ngSubmit)="submitForm()">
<div class="content">
<mat-form-field class="formfield">
<mat-form-field class="formfield" appearance="outline">
<mat-label>{{ 'USER.PROFILE.USERNAME' | translate }}</mat-label>
<input matInput formControlName="userName" />
</mat-form-field>
<mat-form-field class="formfield">
<mat-form-field class="formfield" appearance="outline">
<mat-label>{{ 'USER.PROFILE.FIRSTNAME' | translate }}</mat-label>
<input matInput formControlName="firstName" />
</mat-form-field>
<mat-form-field class="formfield">
<mat-form-field class="formfield" appearance="outline">
<mat-label>{{ 'USER.PROFILE.LASTNAME' | translate }}</mat-label>
<input matInput formControlName="lastName" />
</mat-form-field>
<mat-form-field class="formfield">
<mat-form-field class="formfield" appearance="outline">
<mat-label>{{ 'USER.PROFILE.NICKNAME' | translate }}</mat-label>
<input matInput formControlName="nickName" />
</mat-form-field>
<mat-form-field class="formfield">
<mat-form-field class="formfield" appearance="outline">
<mat-label>{{ 'USER.PROFILE.GENDER' | translate }}</mat-label>
<mat-select formControlName="gender">
<mat-option *ngFor="let gender of genders" [value]="gender">
@ -24,7 +24,7 @@
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="formfield">
<mat-form-field class="formfield" appearance="outline">
<mat-label>{{ 'USER.PROFILE.PREFERRED_LANGUAGE' | translate }}</mat-label>
<mat-select formControlName="preferredLanguage">
<mat-option *ngFor="let language of languages" [value]="language">

View File

@ -8,6 +8,8 @@ import {
ChangeIamMemberRequest,
CreateOrgRequest,
CreateUserRequest,
FailedEventID,
FailedEvents,
IamMember,
IamMemberRoles,
IamMemberSearchQuery,
@ -78,6 +80,14 @@ export class AdminService {
);
}
public async GetFailedEvents(): Promise<FailedEvents> {
return await this.request(
c => c.getFailedEvents,
new Empty(),
f => f,
);
}
public async ClearView(viewname: string, db: string): Promise<Empty> {
const req: ViewID = new ViewID();
req.setDatabase(db);
@ -89,6 +99,18 @@ export class AdminService {
);
}
public async RemoveFailedEvent(viewname: string, db: string, sequence: number): Promise<Empty> {
const req: FailedEventID = new FailedEventID();
req.setDatabase(db);
req.setViewName(viewname);
req.setFailedSequence(sequence);
return await this.request(
c => c.removeFailedEvent,
req,
f => f,
);
}
public async SearchIamMembers(
limit: number,
offset: number,

View File

@ -239,14 +239,27 @@
"DESCRIPTION": "Manger können die Organisation editieren und Projekte verwalten."
},
"VIEWS": {
"TITLE":"Views und Events",
"DESCRIPTION":"Diese Ansicht zeigt die ZITADEL Views, du kannst diese zurücksetzen und fehlgeschlagene Events entfernen.",
"TITLE":"Views",
"DESCRIPTION":"Diese Ansicht zeigt die ZITADEL Views. Diese können bei Bedarf zurückgesetzt werden.",
"VIEWNAME":"Name",
"DATABASE":"Datenbank",
"SEQUENCE":"Sequenz",
"TIMESTAMP":"Zeitstempel",
"ACTIONS":"Aktionen",
"CLEAR":"Aufräumen"
},
"FAILEDEVENTS": {
"TITLE":"Gescheiterte Events",
"DESCRIPTION":"Das sind die gescheiterten Events.",
"VIEWNAME":"Name",
"DATABASE":"Datenbank",
"FAILEDSEQUENCE":"betroffene Sequenz",
"FAILURECOUNT":"Fehleranzahl",
"ERRORMESSAGE":"Meldung",
"ACTIONS":"Aktionen",
"DELETE":"Entfernen",
"DELETESUCCESS":"Gescheiterte Events entfernt!"
},
"TOAST":{
"MEMBERREMOVED":"Manager entfernt!",
"MEMBERSADDED": "Manager hinzugefügt!",

View File

@ -239,14 +239,27 @@
"DESCRIPTION":"Managers can add and edit organisations and make changes to their corresponding projects and apps"
},
"VIEWS": {
"TITLE":"Views and Events",
"DESCRIPTION":"This Card shows your Zitadel Views, you can clear them and remove failed events.",
"TITLE":"Views",
"DESCRIPTION":"This Card shows your Zitadel Views.",
"VIEWNAME":"Name",
"DATABASE":"Database",
"SEQUENCE":"Sequence",
"TIMESTAMP":"Timestamp",
"ACTIONS":"Actions",
"CLEAR":"Clear"
},
"FAILEDEVENTS": {
"TITLE":"Failed Events",
"DESCRIPTION":"This Card shows your failed Events.",
"VIEWNAME":"Name",
"DATABASE":"Database",
"FAILEDSEQUENCE":"Failed Sequence",
"FAILURECOUNT":"Failure Count",
"ERRORMESSAGE":"Error message",
"ACTIONS":"Actions",
"DELETE":"Remove",
"DELETESUCCESS":"Failed Events removed!"
},
"TOAST":{
"MEMBERREMOVED":"Manager removed!",
"MEMBERSADDED": "Managers added!",