From 7b44209bfdd3849b2dffd0b681597aeac88ea19c Mon Sep 17 00:00:00 2001 From: Miguel Cabrerizo <30386061+doncicuto@users.noreply.github.com> Date: Tue, 18 Jul 2023 08:45:34 +0200 Subject: [PATCH] feat: show all available organizations when creating project grants (#6040) * feat: show available orgs (project) grants * feat: add e2e for project grant * feat: add bulgarian missing translations * feat: update docs * fix: add @peintnermax suggested changes --------- Co-authored-by: Max Peintner --- .../project-roles-table.component.html | 1 + .../search-org-autocomplete.component.html | 32 +++++++ .../search-org-autocomplete.component.scss | 38 +++++++++ .../search-org-autocomplete.component.spec.ts | 24 ++++++ .../search-org-autocomplete.component.ts | 83 +++++++++++++++++++ .../search-org-autocomplete.module.ts | 32 +++++++ .../project-grant-create.component.html | 36 ++++---- .../project-grant-create.component.ts | 4 + .../project-grant-create.module.ts | 2 + .../project-grants.component.html | 1 + .../project-role-create.component.html | 15 +++- console/src/assets/i18n/bg.json | 7 +- console/src/assets/i18n/de.json | 8 +- console/src/assets/i18n/en.json | 10 +-- console/src/assets/i18n/es.json | 8 +- console/src/assets/i18n/fr.json | 8 +- console/src/assets/i18n/it.json | 8 +- console/src/assets/i18n/ja.json | 8 +- console/src/assets/i18n/pl.json | 8 +- console/src/assets/i18n/zh.json | 8 +- docs/docs/guides/manage/console/projects.mdx | 8 +- e2e/cypress/e2e/projects/projects.cy.ts | 49 ++++++++++- 22 files changed, 328 insertions(+), 70 deletions(-) create mode 100644 console/src/app/modules/search-org-autocomplete/search-org-autocomplete.component.html create mode 100644 console/src/app/modules/search-org-autocomplete/search-org-autocomplete.component.scss create mode 100644 console/src/app/modules/search-org-autocomplete/search-org-autocomplete.component.spec.ts create mode 100644 console/src/app/modules/search-org-autocomplete/search-org-autocomplete.component.ts create mode 100644 console/src/app/modules/search-org-autocomplete/search-org-autocomplete.module.ts diff --git a/console/src/app/modules/project-roles-table/project-roles-table.component.html b/console/src/app/modules/project-roles-table/project-roles-table.component.html index e4d62293cd..6cb4658cff 100644 --- a/console/src/app/modules/project-roles-table/project-roles-table.component.html +++ b/console/src/app/modules/project-roles-table/project-roles-table.component.html @@ -16,6 +16,7 @@ color="primary" class="cnsl-action-button" mat-raised-button + data-e2e="create-project-role-button" > add {{ 'ACTIONS.NEW' | translate }} diff --git a/console/src/app/modules/search-org-autocomplete/search-org-autocomplete.component.html b/console/src/app/modules/search-org-autocomplete/search-org-autocomplete.component.html new file mode 100644 index 0000000000..f53717ade3 --- /dev/null +++ b/console/src/app/modules/search-org-autocomplete/search-org-autocomplete.component.html @@ -0,0 +1,32 @@ +
+ + {{ 'PROJECT.GRANT.CREATE.SEL_ORG_FORMFIELD' | translate }} + + + + + + + +
+
+ {{ org.name }} + + {{ org.primaryDomain }} +
+
+
+
+ + {{ 'PROJECT.GRANT.CREATE.SEL_ORG_DESC' | translate }} + +
+
diff --git a/console/src/app/modules/search-org-autocomplete/search-org-autocomplete.component.scss b/console/src/app/modules/search-org-autocomplete/search-org-autocomplete.component.scss new file mode 100644 index 0000000000..dbf3f4af1f --- /dev/null +++ b/console/src/app/modules/search-org-autocomplete/search-org-autocomplete.component.scss @@ -0,0 +1,38 @@ +.full-width { + width: 100%; +} + +input { + max-width: 500px; +} + +.org-option { + display: flex; + align-items: center; + + .org-option-column { + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: center; + width: 100%; + + span { + line-height: normal; + } + + .fill-space { + flex: 1; + } + + .smaller { + font-size: 13px; + } + } +} + +.org-autocomplete-target-desc { + font-size: 14px; + display: block; + margin-top: 0.5rem; +} diff --git a/console/src/app/modules/search-org-autocomplete/search-org-autocomplete.component.spec.ts b/console/src/app/modules/search-org-autocomplete/search-org-autocomplete.component.spec.ts new file mode 100644 index 0000000000..03a2bda406 --- /dev/null +++ b/console/src/app/modules/search-org-autocomplete/search-org-autocomplete.component.spec.ts @@ -0,0 +1,24 @@ +import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; + +import { SearchOrgAutocompleteComponent } from './search-org-autocomplete.component'; + +describe('SearchOrgComponent', () => { + let component: SearchOrgAutocompleteComponent; + let fixture: ComponentFixture; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [SearchOrgAutocompleteComponent], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SearchOrgAutocompleteComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/console/src/app/modules/search-org-autocomplete/search-org-autocomplete.component.ts b/console/src/app/modules/search-org-autocomplete/search-org-autocomplete.component.ts new file mode 100644 index 0000000000..b640c3038d --- /dev/null +++ b/console/src/app/modules/search-org-autocomplete/search-org-autocomplete.component.ts @@ -0,0 +1,83 @@ +import { Component, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'; +import { UntypedFormControl } from '@angular/forms'; +import { MatAutocompleteSelectedEvent } from '@angular/material/autocomplete'; +import { MatLegacyAutocomplete as MatAutocomplete } from '@angular/material/legacy-autocomplete'; +import { debounceTime, from, map, Subject, switchMap, takeUntil, tap } from 'rxjs'; +import { TextQueryMethod } from 'src/app/proto/generated/zitadel/object_pb'; +import { Org, OrgNameQuery, OrgQuery, OrgState, OrgStateQuery } from 'src/app/proto/generated/zitadel/org_pb'; +import { AuthenticationService } from 'src/app/services/authentication.service'; +import { GrpcAuthService } from 'src/app/services/grpc-auth.service'; + +@Component({ + selector: 'cnsl-search-org-autocomplete', + templateUrl: './search-org-autocomplete.component.html', + styleUrls: ['./search-org-autocomplete.component.scss'], +}) +export class SearchOrgAutocompleteComponent implements OnInit, OnDestroy { + public selectable: boolean = true; + public myControl: UntypedFormControl = new UntypedFormControl(); + public filteredOrgs: Array = []; + public isLoading: boolean = false; + @ViewChild('auto') public matAutocomplete!: MatAutocomplete; + @Output() public selectionChanged: EventEmitter = new EventEmitter(); + + private unsubscribed$: Subject = new Subject(); + constructor(public authService: AuthenticationService, private auth: GrpcAuthService) { + this.myControl.valueChanges + .pipe( + takeUntil(this.unsubscribed$), + debounceTime(200), + tap(() => (this.isLoading = true)), + switchMap((value) => { + const stateQuery = new OrgQuery(); + const orgStateQuery = new OrgStateQuery(); + orgStateQuery.setState(OrgState.ORG_STATE_ACTIVE); + stateQuery.setStateQuery(orgStateQuery); + + let queries: OrgQuery[] = [stateQuery]; + + if (value) { + const nameQuery = new OrgQuery(); + const orgNameQuery = new OrgNameQuery(); + orgNameQuery.setName(value); + orgNameQuery.setMethod(TextQueryMethod.TEXT_QUERY_METHOD_CONTAINS_IGNORE_CASE); + nameQuery.setNameQuery(orgNameQuery); + queries = [stateQuery, nameQuery]; + } + + return from(this.auth.listMyProjectOrgs(undefined, 0, queries)).pipe( + map((resp) => { + return resp.resultList.sort((left, right) => left.name.localeCompare(right.name)); + }), + ); + }), + ) + .subscribe((returnValue) => { + this.isLoading = false; + this.filteredOrgs = returnValue; + }); + } + + public ngOnInit(): void { + const query = new OrgQuery(); + const orgStateQuery = new OrgStateQuery(); + orgStateQuery.setState(OrgState.ORG_STATE_ACTIVE); + query.setStateQuery(orgStateQuery); + + this.auth.listMyProjectOrgs(undefined, 0, [query]).then((orgs) => { + this.filteredOrgs = orgs.resultList; + }); + } + + public ngOnDestroy(): void { + this.unsubscribed$.next(); + } + + public displayFn(org?: Org.AsObject): string { + return org ? `${org.name}` : ''; + } + + public selected(event: MatAutocompleteSelectedEvent): void { + this.selectionChanged.emit(event.option.value); + } +} diff --git a/console/src/app/modules/search-org-autocomplete/search-org-autocomplete.module.ts b/console/src/app/modules/search-org-autocomplete/search-org-autocomplete.module.ts new file mode 100644 index 0000000000..36c99d27f3 --- /dev/null +++ b/console/src/app/modules/search-org-autocomplete/search-org-autocomplete.module.ts @@ -0,0 +1,32 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { MatIconModule } from '@angular/material/icon'; +import { MatLegacyAutocompleteModule as MatAutocompleteModule } from '@angular/material/legacy-autocomplete'; +import { MatLegacyButtonModule as MatButtonModule } from '@angular/material/legacy-button'; +import { MatLegacyChipsModule as MatChipsModule } from '@angular/material/legacy-chips'; +import { MatLegacyProgressSpinnerModule as MatProgressSpinnerModule } from '@angular/material/legacy-progress-spinner'; +import { MatLegacySelectModule as MatSelectModule } from '@angular/material/legacy-select'; +import { TranslateModule } from '@ngx-translate/core'; +import { InputModule } from 'src/app/modules/input/input.module'; + +import { SearchOrgAutocompleteComponent } from './search-org-autocomplete.component'; + +@NgModule({ + declarations: [SearchOrgAutocompleteComponent], + imports: [ + CommonModule, + MatAutocompleteModule, + MatChipsModule, + MatButtonModule, + InputModule, + MatIconModule, + ReactiveFormsModule, + MatProgressSpinnerModule, + FormsModule, + TranslateModule, + MatSelectModule, + ], + exports: [SearchOrgAutocompleteComponent], +}) +export class SearchOrgAutocompleteModule {} diff --git a/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.component.html b/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.component.html index 17ab854492..0dd00975df 100644 --- a/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.component.html +++ b/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.component.html @@ -6,20 +6,8 @@ >

{{ 'PROJECT.GRANT.CREATE.SEL_ORG' | translate }}

-

{{ 'PROJECT.GRANT.CREATE.SEL_ORG_DESC' | translate }}

- -
- - {{ 'PROJECT.GRANT.CREATE.SEL_ORG_FORMFIELD' | translate }} - - - - -
- - {{ 'PROJECT.GRANT.CREATE.FOR_ORG' | translate }} {{ org.name }} + + {{ 'PROJECT.GRANT.CREATE.FOR_ORG' | translate }} {{ org.name }} - {{ org.primaryDomain }}
@@ -37,7 +25,15 @@
- @@ -46,7 +42,15 @@ - diff --git a/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.component.ts b/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.component.ts index 6cb71c63a6..ebcab508c6 100644 --- a/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.component.ts +++ b/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.component.ts @@ -88,6 +88,10 @@ export class ProjectGrantCreateComponent implements OnInit, OnDestroy { } } + public selectOrg(org: Org.AsObject): void { + this.org = org; + } + public selectRoles(roles: string[]): void { this.rolesKeyList = roles; } diff --git a/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.module.ts b/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.module.ts index e0fcca057b..aa0d65d188 100644 --- a/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.module.ts +++ b/console/src/app/pages/projects/owned-projects/project-grant-create/project-grant-create.module.ts @@ -15,6 +15,7 @@ import { InputModule } from 'src/app/modules/input/input.module'; import { ProjectRolesTableModule } from 'src/app/modules/project-roles-table/project-roles-table.module'; import { HasRolePipeModule } from 'src/app/pipes/has-role-pipe/has-role-pipe.module'; +import { SearchOrgAutocompleteModule } from 'src/app/modules/search-org-autocomplete/search-org-autocomplete.module'; import { ProjectGrantCreateRoutingModule } from './project-grant-create-routing.module'; import { ProjectGrantCreateComponent } from './project-grant-create.component'; @@ -38,6 +39,7 @@ import { ProjectGrantCreateComponent } from './project-grant-create.component'; MatProgressSpinnerModule, FormsModule, TranslateModule, + SearchOrgAutocompleteModule, ], }) export default class ProjectGrantCreateModule {} diff --git a/console/src/app/pages/projects/owned-projects/project-grants/project-grants.component.html b/console/src/app/pages/projects/owned-projects/project-grants/project-grants.component.html index 748b205918..b0a9321a30 100644 --- a/console/src/app/pages/projects/owned-projects/project-grants/project-grants.component.html +++ b/console/src/app/pages/projects/owned-projects/project-grants/project-grants.component.html @@ -17,6 +17,7 @@ class="cnsl-action-button" mat-raised-button [routerLink]="['/projects', projectId, 'projectgrants', 'create']" + data-e2e="create-project-grant-button" > add {{ 'ACTIONS.NEW' | translate }} diff --git a/console/src/app/pages/projects/owned-projects/project-role-create/project-role-create.component.html b/console/src/app/pages/projects/owned-projects/project-role-create/project-role-create.component.html index 8e68738c85..0e44373067 100644 --- a/console/src/app/pages/projects/owned-projects/project-role-create/project-role-create.component.html +++ b/console/src/app/pages/projects/owned-projects/project-role-create/project-role-create.component.html @@ -12,15 +12,15 @@
{{ 'PROJECT.ROLE.KEY' | translate }} - + {{ 'PROJECT.ROLE.DISPLAY_NAME' | translate }} - + {{ 'PROJECT.ROLE.GROUP' | translate }} - +
- diff --git a/console/src/assets/i18n/bg.json b/console/src/assets/i18n/bg.json index 3192117eec..49dc709f3b 100644 --- a/console/src/assets/i18n/bg.json +++ b/console/src/assets/i18n/bg.json @@ -1502,12 +1502,11 @@ "SEL_PROJECT": "Търсене на проект", "SEL_ROLES": "Изберете ролите, които искате да бъдат добавени към субсидията", "SEL_USER": "Изберете потребители", - "SEL_ORG": "Задайте домейна", - "SEL_ORG_DESC": "Въведете пълния домейн, за да посочите организацията, която да предоставите.", - "ORG_TITLE": "Организация", + "SEL_ORG": "Търсете организация", + "SEL_ORG_DESC": "Потърсете организацията за отпускане.", "ORG_DESCRIPTION": "На път сте да предоставите потребител за организацията {{name}}.", "ORG_DESCRIPTION_DESC": "Превключете контекста в заглавката по-горе, за да предоставите потребител за друга организация.", - "SEL_ORG_FORMFIELD": "Пълен домейн", + "SEL_ORG_FORMFIELD": "Организация", "SEL_ORG_BUTTON": "Организация на търсенето", "FOR_ORG": "Безвъзмездната помощ е създадена за:" }, diff --git a/console/src/assets/i18n/de.json b/console/src/assets/i18n/de.json index 4e9c1b4c16..7e6722edcd 100644 --- a/console/src/assets/i18n/de.json +++ b/console/src/assets/i18n/de.json @@ -1508,13 +1508,11 @@ "SEL_ROLES": "Selektiere die gewünschten Rollen für das Erstellen der Berechtigung.", "SEL_PROJECT": "Suchen nach Projekt", "SEL_USER": "Benutzer auswählen", - "SEL_ORG": "Suchen nach Domain", - "SEL_ORG_DESC": "Gebe die vollständige Domain ein, um Resultate zu erhalten.", - "ORG_TITLE": "Organisation", + "SEL_ORG": "Durchsuchen Sie eine Organisation", + "SEL_ORG_DESC": "Suchen Sie nach der zu gewährenden Organisation.", "ORG_DESCRIPTION": "Du bist im Begriff, einen Benutzer für die Organisation {{name}} zu berechtigen.", "ORG_DESCRIPTION_DESC": "Wechsle den Kontext, um die Organisation zu wechseln.", - "SEL_ORG_FORMFIELD": "Vollständige Domain", - "SEL_ORG_BUTTON": "Suche Organisation", + "SEL_ORG_FORMFIELD": "Organisation", "FOR_ORG": "Die Berechtigung wird erstellt für:" }, "DETAIL": { diff --git a/console/src/assets/i18n/en.json b/console/src/assets/i18n/en.json index 0ce9260e80..4f8aa0406c 100644 --- a/console/src/assets/i18n/en.json +++ b/console/src/assets/i18n/en.json @@ -1501,7 +1501,7 @@ "GRANT": { "EMPTY": "No granted organization.", "TITLE": "Project Grants", - "DESCRIPTION": "Allow an other organization to use your project.", + "DESCRIPTION": "Allow another organization to use your project.", "EDITTITLE": "Edit roles", "CREATE": { "TITLE": "Create Organization Grant", @@ -1509,13 +1509,11 @@ "SEL_PROJECT": "Search for a project", "SEL_ROLES": "Select the roles you want to be added to the grant", "SEL_USER": "Select users", - "SEL_ORG": "Set the domain", - "SEL_ORG_DESC": "Enter the complete domain to specify the organization to grant.", - "ORG_TITLE": "Organization", + "SEL_ORG": "Search an organization", + "SEL_ORG_DESC": "Search the organization to grant.", "ORG_DESCRIPTION": "You are about to grant a user for the organization {{name}}.", "ORG_DESCRIPTION_DESC": "Switch the context in the header above to grant a user for another organization.", - "SEL_ORG_FORMFIELD": "Complete Domain", - "SEL_ORG_BUTTON": "Search Organization", + "SEL_ORG_FORMFIELD": "Organization", "FOR_ORG": "The grant is created for:" }, "DETAIL": { diff --git a/console/src/assets/i18n/es.json b/console/src/assets/i18n/es.json index 8e5e0fb2b0..72c674e873 100644 --- a/console/src/assets/i18n/es.json +++ b/console/src/assets/i18n/es.json @@ -1509,13 +1509,11 @@ "SEL_PROJECT": "Buscar un proyecto", "SEL_ROLES": "Selecciona los roles que quieres que se añadan a la concesión", "SEL_USER": "Seleccionar usuarios", - "SEL_ORG": "Establecer el dominio", - "SEL_ORG_DESC": "Introduce el dominio completo para especificar la organización concesionaria.", - "ORG_TITLE": "Organización", + "SEL_ORG": "Buscar una organización", + "SEL_ORG_DESC": "Busca la organización concesionaria.", "ORG_DESCRIPTION": "Estás a punto de conceder acceso a un usuario para la organización {{name}}.", "ORG_DESCRIPTION_DESC": "Cambia el contexto en la cabecera superior para conceder acceso a un usuario para otra organización.", - "SEL_ORG_FORMFIELD": "Completar dominio", - "SEL_ORG_BUTTON": "Buscar organización", + "SEL_ORG_FORMFIELD": "Organización", "FOR_ORG": "La concesión se creó para:" }, "DETAIL": { diff --git a/console/src/assets/i18n/fr.json b/console/src/assets/i18n/fr.json index 146a1007c7..2ff0bcd305 100644 --- a/console/src/assets/i18n/fr.json +++ b/console/src/assets/i18n/fr.json @@ -1508,13 +1508,11 @@ "SEL_PROJECT": "Rechercher un projet", "SEL_ROLES": "Sélectionnez les rôles que vous souhaitez ajouter à l'autorisation.", "SEL_USER": "Sélectionnez les utilisateurs", - "SEL_ORG": "Définir le domaine", - "SEL_ORG_DESC": "Entrez le domaine complet pour spécifier l'organisation à accorder.", - "ORG_TITLE": "Organisation", + "SEL_ORG": "Rechercher une organisation", + "SEL_ORG_DESC": "Rechercher l'organisme à accorder", "ORG_DESCRIPTION": "Vous êtes sur le point d'accorder un utilisateur pour l'organisation{{name}}.", "ORG_DESCRIPTION_DESC": "Changez le contexte dans l'en-tête ci-dessus pour accorder un utilisateur pour une autre organisation.", - "SEL_ORG_FORMFIELD": "Domaine complet", - "SEL_ORG_BUTTON": "Rechercher une organisation", + "SEL_ORG_FORMFIELD": "Organisation", "FOR_ORG": "L'autorisation est créée pour" }, "DETAIL": { diff --git a/console/src/assets/i18n/it.json b/console/src/assets/i18n/it.json index a56034455f..31534f8890 100644 --- a/console/src/assets/i18n/it.json +++ b/console/src/assets/i18n/it.json @@ -1508,13 +1508,11 @@ "SEL_PROJECT": "Cerca un progetto", "SEL_ROLES": "Seleziona i ruoli che vuoi aggiungere", "SEL_USER": "Seleziona utenti", - "SEL_ORG": "Impostare il dominio", - "SEL_ORG_DESC": "Inserisci il dominio completo per specificare l'organizzazione da concedere.", - "ORG_TITLE": "Organizzazione", + "SEL_ORG": "Cerca un'organizzazione", + "SEL_ORG_DESC": "Cerca l'organizzazione da concedere.", "ORG_DESCRIPTION": "Stai per concedere un utente per l'organizzazione {{name}}.", "ORG_DESCRIPTION_DESC": "Cambia il contesto nell'intestazione qui sopra per concedere un utente per un'altra organizzazione.", - "SEL_ORG_FORMFIELD": "Dominio completo", - "SEL_ORG_BUTTON": "Ricerca organizzazione", + "SEL_ORG_FORMFIELD": "Organizzazione", "FOR_ORG": "Org grant \u00e8 creato per:" }, "DETAIL": { diff --git a/console/src/assets/i18n/ja.json b/console/src/assets/i18n/ja.json index f2c7749c29..03431f1058 100644 --- a/console/src/assets/i18n/ja.json +++ b/console/src/assets/i18n/ja.json @@ -1504,13 +1504,11 @@ "SEL_PROJECT": "プロジェクトを検索する", "SEL_ROLES": "許可するロールを選択する", "SEL_USER": "ユーザーを選択する", - "SEL_ORG": "ドメインを設定する", - "SEL_ORG_DESC": "完全なドメインを入力して、アクセスを許可する組織を指定する。", - "ORG_TITLE": "組織", + "SEL_ORG": "組織を検索する", + "SEL_ORG_DESC": "付与する組織を検索する", "ORG_DESCRIPTION": "組織 {{name}} にユーザーをグラントします。", "ORG_DESCRIPTION_DESC": "上記のヘッダーのコンテキストを切り替えることで、別組織のユーザーにグラントできます。", - "SEL_ORG_FORMFIELD": "完全なドメイン", - "SEL_ORG_BUTTON": "組織を検索する", + "SEL_ORG_FORMFIELD": "組織", "FOR_ORG": "グラントが以下に対して作成されます:" }, "DETAIL": { diff --git a/console/src/assets/i18n/pl.json b/console/src/assets/i18n/pl.json index 3265bc3f21..1c797ed14c 100644 --- a/console/src/assets/i18n/pl.json +++ b/console/src/assets/i18n/pl.json @@ -1508,13 +1508,11 @@ "SEL_PROJECT": "Wyszukaj projekt", "SEL_ROLES": "Wybierz role, które mają zostać dodane do udzielenia ", "SEL_USER": "Wybierz użytkowników", - "SEL_ORG": "Ustaw domenę", - "SEL_ORG_DESC": "Wprowadź pełną domenę, aby określić organizację, której chcesz udzielić dostępu.", - "ORG_TITLE": "Organizacja", + "SEL_ORG": "Wyszukaj organizację", + "SEL_ORG_DESC": "Wyszukaj organizację, której chcesz przyznać.", "ORG_DESCRIPTION": "Masz zamiar udzielić użytkownikowi dostęp dla organizacji {{name}}.", "ORG_DESCRIPTION_DESC": "Przełącz kontekst w nagłówku powyżej, aby udzielić użytkownikowi dostępu dla innej organizacji.", - "SEL_ORG_FORMFIELD": "Pełna domena", - "SEL_ORG_BUTTON": "Wyszukaj organizację", + "SEL_ORG_FORMFIELD": "Organizacja", "FOR_ORG": "Dostęp udzielany:" }, "DETAIL": { diff --git a/console/src/assets/i18n/zh.json b/console/src/assets/i18n/zh.json index 2d40252eb4..6a14bf744a 100644 --- a/console/src/assets/i18n/zh.json +++ b/console/src/assets/i18n/zh.json @@ -1507,13 +1507,11 @@ "SEL_PROJECT": "搜索项目", "SEL_ROLES": "选择要添加到授权中的角色", "SEL_USER": "选择一个或多个用户", - "SEL_ORG": "选择一个组织", - "SEL_ORG_DESC": "输入完整的域以指定要授予的组织。", - "ORG_TITLE": "组织", + "SEL_ORG": "搜索组织", + "SEL_ORG_DESC": "搜索要授予的组织", "ORG_DESCRIPTION": "您即将授予组织 {{name}} 的用户。", "ORG_DESCRIPTION_DESC": "切换上面标题中的上下文以授予另一个组织的用户。", - "SEL_ORG_FORMFIELD": "完整域名", - "SEL_ORG_BUTTON": "搜索组织", + "SEL_ORG_FORMFIELD": "组织", "FOR_ORG": "授予组织:" }, "DETAIL": { diff --git a/docs/docs/guides/manage/console/projects.mdx b/docs/docs/guides/manage/console/projects.mdx index 2acf0df86c..411674c18f 100644 --- a/docs/docs/guides/manage/console/projects.mdx +++ b/docs/docs/guides/manage/console/projects.mdx @@ -19,7 +19,11 @@ You would have to create roles for administration and your clients in this very To create a project, navigate to your organization, then projects or directly via , and then click the button to create a new project. -Empty Project +Empty Project then enter your project name and continue. @@ -51,7 +55,7 @@ Organizations can then create authorizations for their users on their own. The p Grants -2. Enter the domain of the organization you want to grant (go to the organization detail page if you can't remember it), hit the search button and continue. +2. Search the organization you want to grant using the auto complete input and continue. 3. Select some roles you would like to grant to the organization and confirm. 4. You should now see the granted organization in the section **grants**. diff --git a/e2e/cypress/e2e/projects/projects.cy.ts b/e2e/cypress/e2e/projects/projects.cy.ts index 36768a1537..1016082894 100644 --- a/e2e/cypress/e2e/projects/projects.cy.ts +++ b/e2e/cypress/e2e/projects/projects.cy.ts @@ -1,19 +1,23 @@ import { Context } from 'support/commands'; import { ensureProjectDoesntExist, ensureProjectExists } from '../../support/api/projects'; +import { ensureOrgExists } from 'support/api/orgs'; describe('projects', () => { beforeEach(() => { cy.context().as('ctx'); }); + const defaultOrg = 'e2eorgnewdefault'; const testProjectNameCreate = 'e2eprojectcreate'; const testProjectNameDelete = 'e2eprojectdelete'; describe('add project', () => { beforeEach(`ensure it doesn't exist already`, () => { cy.get('@ctx').then((ctx) => { - ensureProjectDoesntExist(ctx.api, testProjectNameCreate); - cy.visit(`/projects`); + ensureOrgExists(ctx, defaultOrg).then(() => { + ensureProjectDoesntExist(ctx.api, testProjectNameCreate); + cy.visit(`/projects`); + }); }); }); @@ -27,10 +31,49 @@ describe('projects', () => { it('should configure a project to assert roles on authentication'); }); + describe('create project grant', () => { + const testRoleName = 'e2eroleundertestname'; + + beforeEach('ensure it exists', () => { + cy.get('@ctx').then((ctx) => { + ensureProjectExists(ctx.api, testProjectNameCreate).as('projectId'); + cy.get('@projectId').then((projectId) => { + cy.visit(`/projects/${projectId}`); + }); + }); + }); + + it('should add a role', () => { + cy.get('[data-e2e="sidenav-element-roles"]').click(); + cy.get('[data-e2e="add-new-role"]').click(); + cy.get('[formcontrolname="key"]').type(testRoleName); + cy.get('[formcontrolname="displayName"]').type('e2eroleundertestdisplay'); + cy.get('[formcontrolname="group"]').type('e2eroleundertestgroup'); + cy.get('[data-e2e="save-button"]').click(); + cy.shouldConfirmSuccess(); + cy.contains('tr', testRoleName); + }); + + it('should add a project grant', () => { + const rowSelector = `tr:contains(${testRoleName})`; + + cy.get('[data-e2e="sidenav-element-projectgrants"]').click(); + cy.get('[data-e2e="create-project-grant-button"]').click(); + cy.get('[data-e2e="add-org-input"]').type(defaultOrg); + cy.get('mat-option').contains(defaultOrg).click(); + cy.get('button').should('be.enabled'); + cy.get('[data-e2e="project-grant-continue"]').first().click(); + cy.get(rowSelector).find('input').click({ force: true }); + cy.get('[data-e2e="save-project-grant-button"]').click(); + cy.contains('tr', defaultOrg); + cy.contains('tr', testRoleName); + }); + }); + describe('edit project', () => { beforeEach('ensure it exists', () => { cy.get('@ctx').then((ctx) => { - ensureProjectExists(ctx.api, testProjectNameDelete); + ensureProjectExists(ctx.api, testProjectNameDelete).as('projectId'); cy.visit(`/projects`); }); });