feat(console): rename org (#4542)

* rename org

* add data-e2e

* e2e test

* restore state after

* use ngIf instead of hasrole directive and initialized regex

* rm h2 check

* Update e2e/cypress/e2e/organization/organizations.cy.ts

Co-authored-by: Elio Bischof <eliobischof@gmail.com>

* Update console/src/assets/i18n/de.json

Co-authored-by: Elio Bischof <eliobischof@gmail.com>

* Update console/src/assets/i18n/de.json

Co-authored-by: Elio Bischof <eliobischof@gmail.com>

* Update console/src/assets/i18n/en.json

Co-authored-by: Elio Bischof <eliobischof@gmail.com>

* change e2e test

* org param

* reintroduct org param

* use org query param

* org rename test

* no initial focus on button

* contain name

Co-authored-by: Elio Bischof <eliobischof@gmail.com>
This commit is contained in:
Max Peintner
2022-10-20 14:08:13 +02:00
committed by GitHub
parent 2bfa51da1c
commit 6e89b7d0a1
16 changed files with 186 additions and 15 deletions

View File

@@ -8,7 +8,7 @@ import { DomSanitizer } from '@angular/platform-browser';
import { ActivatedRoute, Router, RouterOutlet } from '@angular/router';
import { LangChangeEvent, TranslateService } from '@ngx-translate/core';
import { Observable, of, Subject } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';
import { filter, map, takeUntil } from 'rxjs/operators';
import { accountCard, adminLineAnimation, navAnimations, routeAnimations, toolbarAnimation } from './animations';
import { Org } from './proto/generated/zitadel/org_pb';
@@ -191,6 +191,11 @@ export class AppComponent implements OnDestroy {
}
});
this.activatedRoute.queryParams.pipe(filter((params) => !!params.org)).subscribe((params) => {
const { org } = params;
this.authService.getActiveOrg(org);
});
this.authenticationService.authenticationChanged.pipe(takeUntil(this.destroy$)).subscribe((authenticated) => {
if (authenticated) {
this.authService

View File

@@ -5,7 +5,7 @@
<div mat-dialog-content>
<cnsl-form-field class="formfield">
<cnsl-label>{{ data.labelKey | translate }}</cnsl-label>
<input cnslInput [(ngModel)]="name" />
<input data-e2e="name" cnslInput [(ngModel)]="name" />
</cnsl-form-field>
</div>
<div mat-dialog-actions class="action">
@@ -13,7 +13,7 @@
{{ 'ACTIONS.CLOSE' | translate }}
</button>
<button [disabled]="!name" cdkFocusInitial color="primary" mat-raised-button (click)="closeDialog(name)">
<button data-e2e="dialog-submit" [disabled]="!name" color="primary" mat-raised-button (click)="closeDialog(name)">
{{ 'ACTIONS.RENAME' | translate }}
</button>
</div>

View File

@@ -7,7 +7,7 @@
</a>
<div class="cnsl-title-row-wrapper">
<div class="cnsl-title-row">
<h2 class="cnsl-title">{{ title }}</h2>
<h2 data-e2e="top-view-title" class="cnsl-title">{{ title }}</h2>
<div
class="cnsl-state-dot"
*ngIf="isActive || isInactive"
@@ -28,6 +28,7 @@
<ng-container *ngIf="hasActions">
<button
data-e2e="actions"
class="cnsl-actions-trigger-desk cnsl-action-button"
mat-raised-button
color="primary"

View File

@@ -1,13 +1,14 @@
<cnsl-top-view
*ngIf="['org.write:' + org?.id, 'org.write$'] | hasRole as hasWrite$"
[hasBackButton]="false"
title="{{ org?.name }}"
[isActive]="org?.state === OrgState.ORG_STATE_ACTIVE"
[isInactive]="org?.state === OrgState.ORG_STATE_INACTIVE"
[hasContributors]="true"
stateTooltip="{{ 'ORG.STATE.' + org?.state | translate }}"
[hasActions]="['org.write:' + org?.id, 'org.write$'] | hasRole | async"
[hasActions]="hasWrite$ | async"
>
<ng-template topActions cnslHasRole [hasRole]="['org.write:' + org?.id, 'org.write$']">
<ng-container topActions *ngIf="hasWrite$ | async">
<button
mat-menu-item
*ngIf="org?.state === OrgState.ORG_STATE_ACTIVE"
@@ -23,7 +24,11 @@
>
{{ 'ORG.PAGES.REACTIVATE' | translate }}
</button>
</ng-template>
<button data-e2e="rename" mat-menu-item (click)="renameOrg()">
{{ 'ORG.PAGES.RENAME.ACTION' | translate }}
</button>
</ng-container>
<cnsl-contributors
topContributors
[totalResult]="totalMemberResult"

View File

@@ -18,6 +18,7 @@ import { GrpcAuthService } from 'src/app/services/grpc-auth.service';
import { ManagementService } from 'src/app/services/mgmt.service';
import { ToastService } from 'src/app/services/toast.service';
import { Buffer } from 'buffer';
import { NameDialogComponent } from 'src/app/modules/name-dialog/name-dialog.component';
@Component({
selector: 'cnsl-org-detail',
@@ -44,7 +45,7 @@ export class OrgDetailComponent implements OnInit, OnDestroy {
public InfoSectionType: any = InfoSectionType;
constructor(
auth: GrpcAuthService,
private auth: GrpcAuthService,
private dialog: MatDialog,
public mgmtService: ManagementService,
private toast: ToastService,
@@ -235,4 +236,49 @@ export class OrgDetailComponent implements OnInit, OnDestroy {
this.loadMetadata();
});
}
public renameOrg(): void {
const dialogRef = this.dialog.open(NameDialogComponent, {
data: {
name: this.org?.name,
titleKey: 'ORG.PAGES.RENAME.TITLE',
descKey: 'ORG.PAGES.RENAME.DESCRIPTION',
labelKey: 'ORG.PAGES.NAME',
},
width: '400px',
});
dialogRef.afterClosed().subscribe((name) => {
if (name) {
this.updateOrg(name);
}
});
}
public updateOrg(name: string): void {
if (this.org) {
this.mgmtService
.updateOrg(name)
.then(() => {
this.toast.showInfo('ORG.TOAST.UPDATED', true);
if (this.org) {
this.org.name = name;
}
this.mgmtService
.getMyOrg()
.then((resp) => {
if (resp.org) {
this.org = resp.org;
this.auth.setActiveOrg(resp.org);
}
})
.catch((error) => {
this.toast.showError(error);
});
})
.catch((error) => {
this.toast.showError(error);
});
}
}
}

View File

@@ -19,6 +19,7 @@ import { InfoSectionModule } from 'src/app/modules/info-section/info-section.mod
import { InputModule } from 'src/app/modules/input/input.module';
import { MetaLayoutModule } from 'src/app/modules/meta-layout/meta-layout.module';
import { MetadataModule } from 'src/app/modules/metadata/metadata.module';
import { NameDialogModule } from 'src/app/modules/name-dialog/name-dialog.module';
import { SettingsGridModule } from 'src/app/modules/settings-grid/settings-grid.module';
import { SharedModule } from 'src/app/modules/shared/shared.module';
import { TopViewModule } from 'src/app/modules/top-view/top-view.module';
@@ -52,6 +53,7 @@ import { OrgRoutingModule } from './org-routing.module';
WarnDialogModule,
MemberCreateDialogModule,
MatMenuModule,
NameDialogModule,
ChangesModule,
MatProgressSpinnerModule,
MetadataModule,

View File

@@ -425,6 +425,8 @@ import {
UpdateOrgIDPResponse,
UpdateOrgMemberRequest,
UpdateOrgMemberResponse,
UpdateOrgRequest,
UpdateOrgResponse,
UpdateProjectGrantMemberRequest,
UpdateProjectGrantMemberResponse,
UpdateProjectGrantRequest,
@@ -2353,6 +2355,12 @@ export class ManagementService {
return this.grpcService.mgmt.updateApp(req, null).then((resp) => resp.toObject());
}
public updateOrg(name: string): Promise<UpdateOrgResponse.AsObject> {
const req = new UpdateOrgRequest();
req.setName(name);
return this.grpcService.mgmt.updateOrg(req, null).then((resp) => resp.toObject());
}
public updateOIDCAppConfig(req: UpdateOIDCAppConfigRequest): Promise<UpdateOIDCAppConfigResponse.AsObject> {
return this.grpcService.mgmt.updateOIDCAppConfig(req, null).then((resp) => resp.toObject());
}

View File

@@ -777,6 +777,12 @@
"ORGDETAIL_TITLE": "Gebe den Namen und die Domain für die neue Organisation ein.",
"ORGDETAIL_TITLE_WITHOUT_DOMAIN": "Geben Sie den Namen der neuen Organisation ein.",
"ORGDETAILUSER_TITLE": "Organisationsbesitzer hinzufügen",
"RENAME": {
"ACTION": "Umbenennen",
"TITLE": "Organisation umbenennen",
"DESCRIPTION": "Geben Sie den neuen Namen Ihrer Organisation an.",
"BTN": "Umbenennen"
},
"ORGDOMAIN": {
"TITLE": "Verifikation der Domain der Organisation",
"VERIFICATION": "Überprüfe den Besitz Deiner Domain, indem Du eine Bestätigungsdatei herunterlädst und unter der angegebenen URL speicherst, oder indem Du sie mit einem DNS-Eintrag verifizierst.",
@@ -828,6 +834,7 @@
"DESCRIPTION": "Definiere hier die Benutzer, die Operationen auf Deinen Organisationen vornehmen dürfen."
},
"TOAST": {
"UPDATED": "Organisation geändert",
"DEACTIVATED": "Organisation deaktiviert.",
"REACTIVATED": "Organisation reaktiviert.",
"DOMAINADDED": "Domain hinzugefügt.",

View File

@@ -777,6 +777,12 @@
"ORGDETAIL_TITLE": "Enter the name and domain of your new organization.",
"ORGDETAIL_TITLE_WITHOUT_DOMAIN": "Enter the name of your new organization.",
"ORGDETAILUSER_TITLE": "Configure Organization Owner",
"RENAME": {
"ACTION": "Rename",
"TITLE": "Rename Organization",
"DESCRIPTION": "Enter the new name for your organization",
"BTN": "Rename"
},
"ORGDOMAIN": {
"TITLE": "Organization Domain Ownership Verification",
"VERIFICATION": "To verify the ownership of your domain, you need to download a verification file and upload it at the provided URL listed below, or place a TXT Record DNS entry for the provided URL. To complete, click the button to verify.",
@@ -828,6 +834,7 @@
"DESCRIPTION": "Define the users who can change your organizations preferences."
},
"TOAST": {
"UPDATED": "Organization updated successfully.",
"DEACTIVATED": "Organization deactivated.",
"REACTIVATED": "Organization reactivated.",
"DOMAINADDED": "Added domain.",

View File

@@ -777,6 +777,12 @@
"ORGDETAIL_TITLE": "Saisissez le nom et le domaine de votre nouvelle organisation.",
"ORGDETAIL_TITLE_WITHOUT_DOMAIN": "Saisissez le nom de votre nouvelle organisation.",
"ORGDETAILUSER_TITLE": "Configurer le propriétaire de l'organisation",
"RENAME": {
"ACTION": "Renommer",
"TITLE": "Renommer l'organisation",
"DESCRIPTION": "Entrez le nouveau nom de votre organisation",
"BTN": "Renommer"
},
"ORGDOMAIN": {
"TITLE": "Vérification de la propriété du domaine de l'organisation",
"VERIFICATION": "Pour vérifier la propriété de votre domaine, vous devez télécharger un fichier de vérification et le charger à l'URL indiquée ci-dessous, ou placer une entrée DNS TXT Record pour l'URL indiquée. Pour terminer, cliquez sur le bouton de vérification.",
@@ -828,6 +834,7 @@
"DESCRIPTION": "Définissez les utilisateurs qui peuvent modifier les préférences de votre organisation."
},
"TOAST": {
"UPDATED": "L'organisation a été mise à jour",
"DEACTIVATED": "Organisation désactivée.",
"REACTIVATED": "Organisation réactivée.",
"DOMAINADDED": "Domaine ajouté.",

View File

@@ -777,6 +777,12 @@
"ORGDETAIL_TITLE": "Inserisci il nome e il dominio della tua nuova organizzazione.",
"ORGDETAIL_TITLE_WITHOUT_DOMAIN": "Inserisci il nome della tua nuova organizzazione.",
"ORGDETAILUSER_TITLE": "Configurare il proprietario dell'organizzazione",
"RENAME": {
"ACTION": "Rinomina",
"TITLE": "Rinomina organizzazione",
"DESCRIPTION": "Inserisci il nuovo nome per la tua organizzazione",
"BTN": "Rinomina"
},
"ORGDOMAIN": {
"TITLE": "Verificazione della propriet\u00e0 del dominio dell'organizzazione",
"VERIFICATION": "Verifica la propriet\u00e0 del tuo dominio. \u00c8 necessario scaricare un file di verifica e caricarlo all'URL fornito elencato di seguito, o inserire una voce DNS TXT Record per l'URL fornito. Per completare, clicca sul pulsante di verifica.",
@@ -828,6 +834,7 @@
"DESCRIPTION": "Definisci gli utenti che possono cambiare le preferenze delle tue organizzazioni."
},
"TOAST": {
"UPDATED": "L'organizzazione es stata aggiornata.",
"DEACTIVATED": "Organizzazione disattivata.",
"REACTIVATED": "Organizzazione riattivata.",
"DOMAINADDED": "Aggiunto dominio.",

View File

@@ -777,6 +777,12 @@
"ORGDETAIL_TITLE": "输入新组织的名称和域名。",
"ORGDETAIL_TITLE_WITHOUT_DOMAIN": "输入新组织的名称。",
"ORGDETAILUSER_TITLE": "配置组织所有者",
"RENAME": {
"ACTION": "改名",
"TITLE": "重命名组织",
"DESCRIPTION": "输入组织的新名称",
"BTN": "改名"
},
"ORGDOMAIN": {
"TITLE": "组织域所有权验证",
"VERIFICATION": "要验证您对域的所有权,您需要下载验证文件并将其上传到下面列出的提供的 URL或者为提供的域名添加一条类型为TXT的DNS解析记录。完成后请单击按钮进行验证。",
@@ -828,6 +834,7 @@
"DESCRIPTION": "定义可以更改组织首选项的用户。"
},
"TOAST": {
"UPDATED": "组织已更新",
"DEACTIVATED": "组织已停用。",
"REACTIVATED": "组织重新启用。",
"DOMAINADDED": "域名已添加。",