feat: console flat navigation, settings (#3581)

* instance routing

* instance naming

* org list

* rm isonsystem

* breadcrumb  type

* routing

* instance members

* fragment refresh org

* settings pages

* settings list, sidenav grouping, i18n

* org-settings, policy changes

* lint

* grid

* rename grid

* fallback to general

* cleanup

* general settings, remove cards

* sidenav for settings, label policy

* i18n

* header, nav backbuild

* general, project nav rehaul

* login text background adapt

* org nav anim

* org, instance settings, fix policy layout, roles

* i18n, active route for project

* lint
This commit is contained in:
Max Peintner
2022-05-09 15:01:36 +02:00
committed by GitHub
parent 94e420bb24
commit 06e3330d2e
188 changed files with 4046 additions and 3639 deletions
@@ -1,77 +1,64 @@
<cnsl-detail-layout
[hasBackButton]="true"
[title]="'POLICY.MESSAGE_TEXTS.TITLE' | translate"
[description]="'POLICY.MESSAGE_TEXTS.DESCRIPTION' | translate"
>
<p class="policy-applied-to" sub>
{{ 'POLICY.APPLIEDTO' | translate }}:
<strong *ngIf="orgName; else iam">{{ orgName }}</strong>
<ng-template #iam
><strong>{{ 'MENU.INSTANCE' | translate }}</strong>
</ng-template>
</p>
<h2>{{ 'POLICY.MESSAGE_TEXTS.TITLE' | translate }}</h2>
<p class="cnsl-secondary-text">{{ 'POLICY.MESSAGE_TEXTS.DESCRIPTION' | translate }}</p>
<div class="message-texts-top-actions">
<cnsl-form-field class="type">
<cnsl-label>{{ 'POLICY.MESSAGE_TEXTS.TYPE' | translate }}</cnsl-label>
<mat-select [(ngModel)]="currentType" name="currentSubMap" (selectionChange)="changedCurrentType()">
<mat-option *ngFor="let type of MESSAGETYPES | keyvalue" [value]="type.value">
{{ 'POLICY.MESSAGE_TEXTS.TYPES.' + type.value | translate }}
</mat-option>
</mat-select>
</cnsl-form-field>
<div class="message-texts-top-actions">
<cnsl-form-field class="type">
<cnsl-label>{{ 'POLICY.MESSAGE_TEXTS.TYPE' | translate }}</cnsl-label>
<mat-select [(ngModel)]="currentType" name="currentSubMap" (selectionChange)="changedCurrentType()">
<mat-option *ngFor="let type of MESSAGETYPES | keyvalue" [value]="type.value">
{{ 'POLICY.MESSAGE_TEXTS.TYPES.' + type.value | translate }}
</mat-option>
</mat-select>
</cnsl-form-field>
<cnsl-form-field class="language">
<cnsl-label>{{ 'POLICY.LOGIN_TEXTS.LOCALE' | translate }}</cnsl-label>
<mat-select [(ngModel)]="locale" name="locale" (selectionChange)="changeLocale($event)">
<mat-option *ngFor="let loc of LOCALES" [value]="loc">
<div class="centerline">
<span
>{{ loc }}
<span class="lighter cnsl-secondary-text"
>|&nbsp;{{ 'POLICY.LOGIN_TEXTS.LOCALES.' + loc | translate }}</span
></span
>
</div>
</mat-option>
</mat-select>
</cnsl-form-field>
</div>
<cnsl-form-field class="language">
<cnsl-label>{{ 'POLICY.LOGIN_TEXTS.LOCALE' | translate }}</cnsl-label>
<mat-select [(ngModel)]="locale" name="locale" (selectionChange)="changeLocale($event)">
<mat-option *ngFor="let loc of LOCALES" [value]="loc">
<div class="centerline">
<span
>{{ loc }}
<span class="lighter cnsl-secondary-text"
>|&nbsp;{{ 'POLICY.LOGIN_TEXTS.LOCALES.' + loc | translate }}</span
></span
>
</div>
</mat-option>
</mat-select>
</cnsl-form-field>
</div>
<div class="content">
<cnsl-edit-text
[chips]="chips[currentType]"
[disabled]="(canWrite$ | async) === false"
label="one"
[default$]="getDefaultInitMessageTextMap$"
[current$]="getCustomInitMessageTextMap$"
(changedValues)="updateCurrentValues($event)"
></cnsl-edit-text>
</div>
<div class="content">
<cnsl-edit-text
[chips]="chips[currentType]"
[disabled]="(canWrite$ | async) === false"
label="one"
[default$]="getDefaultInitMessageTextMap$"
[current$]="getCustomInitMessageTextMap$"
(changedValues)="updateCurrentValues($event)"
></cnsl-edit-text>
</div>
<div class="actions">
<button
class="reset-button"
*ngIf="(getCustomInitMessageTextMap$ | async) && (getCustomInitMessageTextMap$ | async)?.isDefault === false"
[disabled]="(canWrite$ | async) === false"
(click)="resetDefault()"
color="warn"
type="submit"
mat-stroked-button
>
<i class="las la-history"></i> {{ 'ACTIONS.RESETDEFAULT' | translate }}
</button>
<button
class="save-button"
[disabled]="!updateRequest || (canWrite$ | async) === false"
(click)="saveCurrentMessage()"
color="primary"
type="submit"
mat-raised-button
>
{{ 'ACTIONS.SAVE' | translate }}
</button>
</div>
<cnsl-policy-grid [currentPolicy]="currentPolicy" [type]="serviceType" tagForFilter="text"></cnsl-policy-grid>
</cnsl-detail-layout>
<div class="actions">
<button
class="reset-button"
*ngIf="(getCustomInitMessageTextMap$ | async) && (getCustomInitMessageTextMap$ | async)?.isDefault === false"
[disabled]="(canWrite$ | async) === false"
(click)="resetDefault()"
color="warn"
type="submit"
mat-stroked-button
>
<i class="las la-history"></i> {{ 'ACTIONS.RESETDEFAULT' | translate }}
</button>
<button
class="save-button"
[disabled]="!updateRequest || (canWrite$ | async) === false"
(click)="saveCurrentMessage()"
color="primary"
type="submit"
mat-raised-button
>
{{ 'ACTIONS.SAVE' | translate }}
</button>
</div>
@@ -1,51 +1,46 @@
import { Component, Injector, OnDestroy, Type } from '@angular/core';
import { Component, Injector, Input, OnDestroy, OnInit, Type } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatSelectChange } from '@angular/material/select';
import { ActivatedRoute } from '@angular/router';
import { BehaviorSubject, from, Observable, of, Subscription } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import {
GetCustomPasswordResetMessageTextRequest as AdminGetCustomPasswordResetMessageTextRequest,
GetDefaultInitMessageTextRequest as AdminGetDefaultInitMessageTextRequest,
GetDefaultVerifyEmailMessageTextRequest as AdminGetDefaultVerifyEmailMessageTextRequest,
GetDefaultVerifyPhoneMessageTextRequest as AdminGetDefaultVerifyPhoneMessageTextRequest,
SetDefaultDomainClaimedMessageTextRequest,
SetDefaultInitMessageTextRequest,
SetDefaultPasswordlessRegistrationMessageTextRequest,
SetDefaultPasswordResetMessageTextRequest,
SetDefaultVerifyEmailMessageTextRequest,
SetDefaultVerifyPhoneMessageTextRequest,
GetCustomPasswordResetMessageTextRequest as AdminGetCustomPasswordResetMessageTextRequest,
GetDefaultInitMessageTextRequest as AdminGetDefaultInitMessageTextRequest,
GetDefaultVerifyEmailMessageTextRequest as AdminGetDefaultVerifyEmailMessageTextRequest,
GetDefaultVerifyPhoneMessageTextRequest as AdminGetDefaultVerifyPhoneMessageTextRequest,
SetDefaultDomainClaimedMessageTextRequest,
SetDefaultInitMessageTextRequest,
SetDefaultPasswordlessRegistrationMessageTextRequest,
SetDefaultPasswordResetMessageTextRequest,
SetDefaultVerifyEmailMessageTextRequest,
SetDefaultVerifyPhoneMessageTextRequest,
} from 'src/app/proto/generated/zitadel/admin_pb';
import {
GetCustomDomainClaimedMessageTextRequest,
GetCustomPasswordlessRegistrationMessageTextRequest,
GetCustomPasswordResetMessageTextRequest,
GetCustomVerifyEmailMessageTextRequest,
GetCustomVerifyPhoneMessageTextRequest,
GetDefaultDomainClaimedMessageTextRequest,
GetDefaultInitMessageTextRequest,
GetDefaultPasswordlessRegistrationMessageTextRequest,
GetDefaultPasswordResetMessageTextRequest,
GetDefaultVerifyEmailMessageTextRequest,
GetDefaultVerifyPhoneMessageTextRequest,
SetCustomDomainClaimedMessageTextRequest,
SetCustomInitMessageTextRequest,
SetCustomPasswordlessRegistrationMessageTextRequest,
SetCustomPasswordResetMessageTextRequest,
SetCustomVerifyEmailMessageTextRequest,
SetCustomVerifyPhoneMessageTextRequest,
GetCustomDomainClaimedMessageTextRequest,
GetCustomPasswordlessRegistrationMessageTextRequest,
GetCustomPasswordResetMessageTextRequest,
GetCustomVerifyEmailMessageTextRequest,
GetCustomVerifyPhoneMessageTextRequest,
GetDefaultDomainClaimedMessageTextRequest,
GetDefaultInitMessageTextRequest,
GetDefaultPasswordlessRegistrationMessageTextRequest,
GetDefaultPasswordResetMessageTextRequest,
GetDefaultVerifyEmailMessageTextRequest,
GetDefaultVerifyPhoneMessageTextRequest,
SetCustomDomainClaimedMessageTextRequest,
SetCustomInitMessageTextRequest,
SetCustomPasswordlessRegistrationMessageTextRequest,
SetCustomPasswordResetMessageTextRequest,
SetCustomVerifyEmailMessageTextRequest,
SetCustomVerifyPhoneMessageTextRequest,
} from 'src/app/proto/generated/zitadel/management_pb';
import { Org } from 'src/app/proto/generated/zitadel/org_pb';
import { MessageCustomText } from 'src/app/proto/generated/zitadel/text_pb';
import { AdminService } from 'src/app/services/admin.service';
import { Breadcrumb, BreadcrumbService, BreadcrumbType } from 'src/app/services/breadcrumb.service';
import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
import { ManagementService } from 'src/app/services/mgmt.service';
import { StorageLocation, StorageService } from 'src/app/services/storage.service';
import { StorageService } from 'src/app/services/storage.service';
import { ToastService } from 'src/app/services/toast.service';
import { InfoSectionType } from '../../info-section/info-section.component';
import { GridPolicy, MESSAGE_TEXTS_POLICY } from '../../policy-grid/policies';
import { WarnDialogComponent } from '../../warn-dialog/warn-dialog.component';
import { PolicyComponentServiceType } from '../policy-component-types.enum';
@@ -279,7 +274,7 @@ const REQUESTMAP = {
templateUrl: './message-texts.component.html',
styleUrls: ['./message-texts.component.scss'],
})
export class MessageTextsComponent implements OnDestroy {
export class MessageTextsComponent implements OnInit, OnDestroy {
public getDefaultInitMessageTextMap$: Observable<{ [key: string]: string }> = of({});
public getCustomInitMessageTextMap$: BehaviorSubject<{ [key: string]: string | boolean }> = new BehaviorSubject({}); // boolean because of isDefault
@@ -287,7 +282,7 @@ export class MessageTextsComponent implements OnDestroy {
public service!: ManagementService | AdminService;
public PolicyComponentServiceType: any = PolicyComponentServiceType;
public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
@Input() public serviceType: PolicyComponentServiceType = PolicyComponentServiceType.MGMT;
public MESSAGETYPES: any = MESSAGETYPES;
@@ -392,8 +387,6 @@ export class MessageTextsComponent implements OnDestroy {
public locale: string = 'en';
public LOCALES: string[] = ['en', 'de', 'it'];
private sub: Subscription = new Subscription();
public currentPolicy: GridPolicy = MESSAGE_TEXTS_POLICY;
public orgName: string = '';
public canWrite$: Observable<boolean> = this.authService.isAllowed([
this.serviceType === PolicyComponentServiceType.ADMIN
? 'iam.policy.write'
@@ -404,61 +397,29 @@ export class MessageTextsComponent implements OnDestroy {
constructor(
private authService: GrpcAuthService,
private route: ActivatedRoute,
private toast: ToastService,
private injector: Injector,
private dialog: MatDialog,
private storageService: StorageService,
breadcrumbService: BreadcrumbService,
) {
this.sub = this.route.data
.pipe(
switchMap((data) => {
this.serviceType = data.serviceType;
switch (this.serviceType) {
case PolicyComponentServiceType.MGMT:
this.service = this.injector.get(ManagementService as Type<ManagementService>);
this.service.getSupportedLanguages().then((lang) => {
this.LOCALES = lang.languagesList;
});
this.loadData(this.currentType);
const org: Org.AsObject | null = this.storageService.getItem('organization', StorageLocation.session);
if (org && org.id) {
this.orgName = org.name;
}
) {}
const iambread = new Breadcrumb({
type: BreadcrumbType.IAM,
name: 'System',
routerLink: ['/system'],
});
const bread: Breadcrumb = {
type: BreadcrumbType.ORG,
routerLink: ['/org'],
};
breadcrumbService.setBreadcrumb([iambread, bread]);
break;
case PolicyComponentServiceType.ADMIN:
this.service = this.injector.get(AdminService as Type<AdminService>);
this.service.getSupportedLanguages().then((lang) => {
this.LOCALES = lang.languagesList;
});
this.loadData(this.currentType);
const iamBread = new Breadcrumb({
type: BreadcrumbType.IAM,
name: 'System',
routerLink: ['/system'],
});
breadcrumbService.setBreadcrumb([iamBread]);
break;
}
return this.route.params;
}),
)
.subscribe();
ngOnInit(): void {
switch (this.serviceType) {
case PolicyComponentServiceType.MGMT:
this.service = this.injector.get(ManagementService as Type<ManagementService>);
this.service.getSupportedLanguages().then((lang) => {
this.LOCALES = lang.languagesList;
});
this.loadData(this.currentType);
break;
case PolicyComponentServiceType.ADMIN:
this.service = this.injector.get(AdminService as Type<AdminService>);
this.service.getSupportedLanguages().then((lang) => {
this.LOCALES = lang.languagesList;
});
this.loadData(this.currentType);
break;
}
}
public getDefaultValues(type: MESSAGETYPES, req: any): Promise<any> {
@@ -13,10 +13,10 @@ import { DetailLayoutModule } from 'src/app/modules/detail-layout/detail-layout.
import { InputModule } from 'src/app/modules/input/input.module';
import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module';
import { CardModule } from '../../card/card.module';
import { EditTextModule } from '../../edit-text/edit-text.module';
import { FormFieldModule } from '../../form-field/form-field.module';
import { InfoSectionModule } from '../../info-section/info-section.module';
import { PolicyGridModule } from '../../policy-grid/policy-grid.module';
import { MessageTextsRoutingModule } from './message-texts-routing.module';
import { MessageTextsComponent } from './message-texts.component';
@@ -37,12 +37,13 @@ import { MessageTextsComponent } from './message-texts.component';
HasRolePipeModule,
MatTooltipModule,
TranslateModule,
CardModule,
MatTooltipModule,
MatSelectModule,
DetailLayoutModule,
MatProgressSpinnerModule,
PolicyGridModule,
TextFieldModule,
],
exports: [MessageTextsComponent],
})
export class MessageTextsPolicyModule {}