From 42effd870225d22d73f93afc4f1b27cae439ba7a Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Fri, 13 Nov 2020 09:59:11 +0100 Subject: [PATCH] feat(console): user grant filtering, org domain verification improvements, fix membership detail link (#916) * user grant filter * add filter input * org domain spinner and reload * user grant filter templates * single selection filter for grants, same dl btn * filter margin * lint style, remove duplicate code * project count as observable * deferred reload on delete * fix user grant formfield * lint styles * fix event propagation on pin, change selection * propagate counter change * admin warn, localstorage, i18n, sidenav impv * overlays * adapt toolbar elevationn, card * color vars, i18n, admin section * fix lint * selection clear on filter * ts lint * Update console/src/assets/i18n/de.json Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com> * Update console/src/assets/i18n/de.json Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com> * Update console/src/assets/i18n/en.json Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com> Co-authored-by: Fabi <38692350+fgerschwiler@users.noreply.github.com> --- console/src/app/app.component.html | 43 ++++++---- console/src/app/app.component.scss | 19 +++-- console/src/app/app.component.ts | 25 +++--- .../src/app/modules/card/card.component.scss | 1 + console/src/app/modules/card/card.scss | 1 + .../modules/changes/changes.component.scss | 1 + .../meta-layout/meta-layout.component.scss | 1 + console/src/app/modules/meta-layout/meta.scss | 11 +-- .../login-policy/login-policy.component.scss | 2 +- .../org-iam-policy.component.scss | 2 +- .../password-complexity-policy.component.scss | 2 +- .../password-lockout-policy.component.scss | 2 +- .../policy-grid/policy-grid.component.scss | 3 +- .../user-grants/user-grants-datasource.ts | 2 +- .../user-grants/user-grants.component.html | 82 +++++++++++++------ .../user-grants/user-grants.component.scss | 28 ++++++- .../user-grants/user-grants.component.ts | 67 +++++++++++++-- .../modules/user-grants/user-grants.module.ts | 2 + .../src/app/pages/home/home.component.html | 50 +++++++++++ .../src/app/pages/home/home.component.scss | 24 +++++- .../domain-verification.component.html | 19 +++-- .../domain-verification.component.scss | 2 +- .../domain-verification.component.ts | 7 +- .../orgs/org-detail/org-detail.component.scss | 2 +- .../orgs/org-detail/org-detail.component.ts | 16 +++- console/src/app/pages/orgs/orgs.module.ts | 2 + .../granted-project-grid.component.html | 23 ++++-- .../granted-project-grid.component.ts | 15 +--- .../owned-project-detail.component.ts | 5 +- .../owned-project-grid.component.html | 37 +++++---- .../owned-project-grid.component.ts | 32 +++++--- .../owned-project-list.component.ts | 16 +++- .../user-create/user-create.component.ts | 2 +- .../auth-user-mfa.component.scss | 2 +- .../memberships/memberships.component.html | 2 +- .../user-detail/user-detail.component.html | 8 +- .../user-detail/user-detail.component.scss | 1 + .../user-mfa/user-mfa.component.scss | 2 +- .../user-table/user-table.component.html | 6 +- .../user-table/user-table.component.scss | 45 +++++----- .../user-table/user-table.component.ts | 1 + console/src/app/services/mgmt.service.ts | 58 +++++++++---- console/src/assets/i18n/de.json | 19 ++++- console/src/assets/i18n/en.json | 19 ++++- console/src/component-themes.scss | 2 + console/src/styles.scss | 43 ++++++---- console/src/styles/link.scss | 16 ++++ console/src/styles/sidenav-list.scss | 54 ++++++++++-- console/src/styles/table.scss | 2 +- 49 files changed, 599 insertions(+), 227 deletions(-) create mode 100644 console/src/styles/link.scss diff --git a/console/src/app/app.component.html b/console/src/app/app.component.html index f189c3ffec..ed66bf1676 100644 --- a/console/src/app/app.component.html +++ b/console/src/app/app.component.html @@ -29,10 +29,12 @@ placeholder="{{'ORG.PAGES.FILTERPLACEHOLDER' | translate}}" #input> - +
+ +
@@ -70,8 +72,10 @@ - - +
{{ 'MENU.GRANTEDPROJECT' | translate }} - {{grantPCount}} + {{mgmtService?.grantedProjectsCount | async}}
@@ -122,7 +128,7 @@
{{ 'MENU.USERSECTION' | translate }} -
+
{{ 'MENU.GRANTSECTION' | translate }} -
+
-
- {{'MENU.IAMADMIN' | translate}} -
+
+ + {{'MENU.IAMADMIN' | translate}} +
\ No newline at end of file diff --git a/console/src/app/app.component.scss b/console/src/app/app.component.scss index b0ba7a6ab1..f5596e86fc 100644 --- a/console/src/app/app.component.scss +++ b/console/src/app/app.component.scss @@ -66,13 +66,6 @@ } } -.admin-line { - font-size: 12px; - padding: 4px 2rem; - position: relative; - overflow: hidden; -} - .main-container { display: flex; flex-direction: column; @@ -222,6 +215,13 @@ margin: .5rem 0; flex: 1; } + + .hiddenline { + display: block; + visibility: hidden; + // flex: 1; + width: 4rem; + } } @mixin textvar($theme) { @@ -255,3 +255,8 @@ align-items: center; } } + +.org-wrapper { + max-height: 350px; + overflow-y: auto; +} diff --git a/console/src/app/app.component.ts b/console/src/app/app.component.ts index 06d082776d..4439282db3 100644 --- a/console/src/app/app.component.ts +++ b/console/src/app/app.component.ts @@ -23,7 +23,6 @@ import { AuthenticationService } from './services/authentication.service'; import { GrpcAuthService } from './services/grpc-auth.service'; import { ManagementService } from './services/mgmt.service'; import { ThemeService } from './services/theme.service'; -import { ToastService } from './services/toast.service'; import { UpdateService } from './services/update.service'; @Component({ @@ -57,13 +56,11 @@ export class AppComponent implements OnDestroy { public showProjectSection: boolean = false; - public grantedProjectsCount: number = 0; - public ownedProjectsCount: number = 0; - public filterControl: FormControl = new FormControl(''); private authSub: Subscription = new Subscription(); private orgSub: Subscription = new Subscription(); + public hideAdminWarn: boolean = true; constructor( public viewPortScroller: ViewportScroller, @Inject('windowObject') public window: Window, @@ -73,15 +70,14 @@ export class AppComponent implements OnDestroy { private breakpointObserver: BreakpointObserver, public overlayContainer: OverlayContainer, private themeService: ThemeService, - private mgmtService: ManagementService, + public mgmtService: ManagementService, public matIconRegistry: MatIconRegistry, public domSanitizer: DomSanitizer, - private toast: ToastService, private router: Router, update: UpdateService, @Inject(DOCUMENT) private document: Document, ) { - console.log('%cWait!', 'text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; color: #5282c1; font-size: 50px'); + console.log('%cWait!', 'text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; color: #5469D4; font-size: 50px'); console.log('%cInserting something here could give attackers access to your zitadel account.', 'color: red; font-size: 18px'); console.log('%cIf you don\'t know exactly what you\'re doing, close the window and stay on the safe side', 'font-size: 16px'); console.log('%cIf you know exactly what you are doing, you should work for us', 'font-size: 16px'); @@ -179,6 +175,8 @@ export class AppComponent implements OnDestroy { value.trim().toLowerCase(), ); }); + + this.hideAdminWarn = localStorage.getItem('hideAdministratorWarning') === 'true' ? true : false; } public ngOnDestroy(): void { @@ -186,6 +184,11 @@ export class AppComponent implements OnDestroy { this.orgSub.unsubscribe(); } + public toggleAdminHide(): void { + this.hideAdminWarn = !this.hideAdminWarn; + localStorage.setItem('hideAdministratorWarning', this.hideAdminWarn.toString()); + } + public loadOrgs(filter?: string): void { let query; if (filter) { @@ -249,13 +252,9 @@ export class AppComponent implements OnDestroy { private getProjectCount(): void { this.authService.isAllowed(['project.read$']).subscribe((allowed) => { if (allowed) { - this.mgmtService.SearchProjects(0, 0).then(res => { - this.ownedProjectsCount = res.toObject().totalResult; - }); + this.mgmtService.SearchProjects(0, 0); - this.mgmtService.SearchGrantedProjects(0, 0).then(res => { - this.grantedProjectsCount = res.toObject().totalResult; - }); + this.mgmtService.SearchGrantedProjects(0, 0); } }); } diff --git a/console/src/app/modules/card/card.component.scss b/console/src/app/modules/card/card.component.scss index f8067632c5..674176943c 100644 --- a/console/src/app/modules/card/card.component.scss +++ b/console/src/app/modules/card/card.component.scss @@ -42,5 +42,6 @@ display: flex; flex-direction: column; width: 100%; + height: 100%; } } diff --git a/console/src/app/modules/card/card.scss b/console/src/app/modules/card/card.scss index ed053a208f..7eb874164a 100644 --- a/console/src/app/modules/card/card.scss +++ b/console/src/app/modules/card/card.scss @@ -16,6 +16,7 @@ box-sizing: border-box; border-radius: .5rem; outline: none; + height: 100%; .selection-icon { opacity: 0; diff --git a/console/src/app/modules/changes/changes.component.scss b/console/src/app/modules/changes/changes.component.scss index 7a4b9ad7fe..21c8403652 100644 --- a/console/src/app/modules/changes/changes.component.scss +++ b/console/src/app/modules/changes/changes.component.scss @@ -5,6 +5,7 @@ margin-bottom: 1rem; font-weight: 400; margin-top: 1rem; + font-size: 14px; } @mixin changes-theme($theme) { diff --git a/console/src/app/modules/meta-layout/meta-layout.component.scss b/console/src/app/modules/meta-layout/meta-layout.component.scss index 261731a654..21165c92bc 100644 --- a/console/src/app/modules/meta-layout/meta-layout.component.scss +++ b/console/src/app/modules/meta-layout/meta-layout.component.scss @@ -8,6 +8,7 @@ display: relative; width: 100%; overflow-y: auto; + padding-bottom: 50px; &.hidden { flex-basis: 100%; diff --git a/console/src/app/modules/meta-layout/meta.scss b/console/src/app/modules/meta-layout/meta.scss index 1deaaf9da4..2f4d9881b1 100644 --- a/console/src/app/modules/meta-layout/meta.scss +++ b/console/src/app/modules/meta-layout/meta.scss @@ -7,17 +7,10 @@ $primary-dark: mat-color($primary, A800); /* stylelint-enable */ - $lighter-color: rgba(mat-color($primary, 300), .5); - .meta-wrapper { .meta { position: relative; flex: 1 0 300px; - background: linear-gradient(to bottom right, rgba($lighter-color, .05) 20%, transparent 50%); - - &.hidden { - background: linear-gradient(to bottom right, rgba($lighter-color, .05), transparent 50%); - } &::after { border-left: 2px solid $primary-color; @@ -27,7 +20,7 @@ left top, left bottom, from($primary-color), - to($primary-dark), + to(rgb(0, 0, 0, .5)), color-stop( 01, $primary-dark @@ -39,7 +32,7 @@ left top, left bottom, from($primary-color), - to($primary-dark), + to(rgb(0, 0, 0, .5)), color-stop( 01, $primary-dark diff --git a/console/src/app/modules/policies/login-policy/login-policy.component.scss b/console/src/app/modules/policies/login-policy/login-policy.component.scss index ccfc996243..ea690233c2 100644 --- a/console/src/app/modules/policies/login-policy/login-policy.component.scss +++ b/console/src/app/modules/policies/login-policy/login-policy.component.scss @@ -1,5 +1,5 @@ .default { - color: #5282c1; + color: var(--color-main); margin-top: 0; } diff --git a/console/src/app/modules/policies/org-iam-policy/org-iam-policy.component.scss b/console/src/app/modules/policies/org-iam-policy/org-iam-policy.component.scss index 53d79e16f9..8167148521 100644 --- a/console/src/app/modules/policies/org-iam-policy/org-iam-policy.component.scss +++ b/console/src/app/modules/policies/org-iam-policy/org-iam-policy.component.scss @@ -1,5 +1,5 @@ .default { - color: #5282c1; + color: var(--color-main); margin-top: 0; } diff --git a/console/src/app/modules/policies/password-complexity-policy/password-complexity-policy.component.scss b/console/src/app/modules/policies/password-complexity-policy/password-complexity-policy.component.scss index aad97ba68c..b629cc0eac 100644 --- a/console/src/app/modules/policies/password-complexity-policy/password-complexity-policy.component.scss +++ b/console/src/app/modules/policies/password-complexity-policy/password-complexity-policy.component.scss @@ -1,5 +1,5 @@ .default { - color: #5282c1; + color: var(--color-main); margin-top: 0; } diff --git a/console/src/app/modules/policies/password-lockout-policy/password-lockout-policy.component.scss b/console/src/app/modules/policies/password-lockout-policy/password-lockout-policy.component.scss index 53d79e16f9..8167148521 100644 --- a/console/src/app/modules/policies/password-lockout-policy/password-lockout-policy.component.scss +++ b/console/src/app/modules/policies/password-lockout-policy/password-lockout-policy.component.scss @@ -1,5 +1,5 @@ .default { - color: #5282c1; + color: var(--color-main); margin-top: 0; } diff --git a/console/src/app/modules/policy-grid/policy-grid.component.scss b/console/src/app/modules/policy-grid/policy-grid.component.scss index ed25548eca..1bd5ad4413 100644 --- a/console/src/app/modules/policy-grid/policy-grid.component.scss +++ b/console/src/app/modules/policy-grid/policy-grid.component.scss @@ -16,8 +16,9 @@ h1 { margin: .5rem; display: flex; flex-direction: column; - min-height: 200px; + min-height: 250px; padding: 1rem; + height: 100%; @media only screen and (max-width: 450px) { flex-basis: 100%; diff --git a/console/src/app/modules/user-grants/user-grants-datasource.ts b/console/src/app/modules/user-grants/user-grants-datasource.ts index 787c51e258..c01cbcb2ca 100644 --- a/console/src/app/modules/user-grants/user-grants-datasource.ts +++ b/console/src/app/modules/user-grants/user-grants-datasource.ts @@ -103,7 +103,7 @@ export class UserGrantsDataSource extends DataSource { break; default: this.loadingSubject.next(true); - const promise3 = this.userService.SearchUserGrants(pageSize, pageSize * pageIndex, []); + const promise3 = this.userService.SearchUserGrants(pageSize, pageSize * pageIndex, queries ?? []); this.loadResponse(promise3); break; } diff --git a/console/src/app/modules/user-grants/user-grants.component.html b/console/src/app/modules/user-grants/user-grants.component.html index c8a0721d92..f3f491fae0 100644 --- a/console/src/app/modules/user-grants/user-grants.component.html +++ b/console/src/app/modules/user-grants/user-grants.component.html @@ -1,6 +1,12 @@ + + {{'USER.PAGES.FILTER' | translate}} + + + + +
+
+ {{ role }}
- + + +
- + *ngIf="(context === UserGrantContext.OWNED_PROJECT || context === UserGrantContext.USER || context === UserGrantContext.NONE) && grantToEdit == grant.id && loadedProjectId && loadedProjectId === grant.projectId"> + {{ 'PROJECT.GRANT.ROLENAMESLIST' | translate }} + - + *ngIf="(context === UserGrantContext.GRANTED_PROJECT || context === UserGrantContext.USER || context === UserGrantContext.NONE) && loadedGrantId && loadedGrantId === grant.grantId && grantToEdit == grant.id"> + {{ 'PROJECT.GRANT.ROLENAMESLIST' | translate }} + @@ -123,4 +148,11 @@ [length]="dataSource.totalResult" [pageSizeOptions]="[2, 3, 25, 50, 100, 250]" (page)="changePage($event)"> -
\ No newline at end of file + + + + + \ No newline at end of file diff --git a/console/src/app/modules/user-grants/user-grants.component.scss b/console/src/app/modules/user-grants/user-grants.component.scss index 6587614d4b..98feec09a7 100644 --- a/console/src/app/modules/user-grants/user-grants.component.scss +++ b/console/src/app/modules/user-grants/user-grants.component.scss @@ -21,6 +21,19 @@ } } + th { + .search-button { + display: none; + } + + &:hover, + &.search-active { + .search-button { + display: inline-block; + } + } + } + .selection { width: 50px; max-width: 50px; @@ -35,15 +48,22 @@ .flex-row { display: flex; - flex-direction: column; + flex-direction: row; max-width: 400px; .role { - display: block; + display: flex; + flex-direction: column; margin: .25rem; font-size: 14px; text-overflow: ellipsis; overflow: hidden; + justify-items: center; + align-self: center; + } + + .fill-space { + flex: 1; } button { @@ -60,3 +80,7 @@ .fill-space { flex: 1; } + +.filtername { + margin-right: 1rem; +} diff --git a/console/src/app/modules/user-grants/user-grants.component.ts b/console/src/app/modules/user-grants/user-grants.component.ts index a2b67d2be1..0d29873727 100644 --- a/console/src/app/modules/user-grants/user-grants.component.ts +++ b/console/src/app/modules/user-grants/user-grants.component.ts @@ -1,10 +1,19 @@ import { SelectionModel } from '@angular/cdk/collections'; import { AfterViewInit, Component, Input, OnInit, ViewChild } from '@angular/core'; +import { MatInput } from '@angular/material/input'; import { MatPaginator, PageEvent } from '@angular/material/paginator'; import { MatSelectChange } from '@angular/material/select'; import { MatTable } from '@angular/material/table'; import { tap } from 'rxjs/operators'; -import { ProjectRoleView, UserGrant, UserGrantView } from 'src/app/proto/generated/management_pb'; +import { enterAnimations } from 'src/app/animations'; +import { + ProjectRoleView, + SearchMethod, + UserGrant, + UserGrantSearchKey, + UserGrantSearchQuery, + UserGrantView, +} from 'src/app/proto/generated/management_pb'; import { ManagementService } from 'src/app/services/mgmt.service'; import { ToastService } from 'src/app/services/toast.service'; @@ -14,12 +23,17 @@ import { UserGrantContext, UserGrantsDataSource } from './user-grants-datasource selector: 'app-user-grants', templateUrl: './user-grants.component.html', styleUrls: ['./user-grants.component.scss'], + animations: [ + enterAnimations, + ], }) export class UserGrantsComponent implements OnInit, AfterViewInit { + public userGrantSearchKey: UserGrantSearchKey | undefined = undefined; + public UserGrantSearchKey: any = UserGrantSearchKey; + public INITIAL_PAGE_SIZE: number = 50; @Input() context: UserGrantContext = UserGrantContext.NONE; @Input() refreshOnPreviousRoutes: string[] = []; - public grants: UserGrantView.AsObject[] = []; public dataSource!: UserGrantsDataSource; public selection: SelectionModel = new SelectionModel(true, []); @@ -32,6 +46,7 @@ export class UserGrantsComponent implements OnInit, AfterViewInit { @Input() userId: string = ''; @Input() projectId: string = ''; @Input() grantId: string = ''; + @ViewChild('input') public filter!: MatInput; public grantRoleOptions: string[] = []; public projectRoleOptions: ProjectRoleView.AsObject[] = []; @@ -39,6 +54,7 @@ export class UserGrantsComponent implements OnInit, AfterViewInit { public loadedGrantId: string = ''; public loadedProjectId: string = ''; + public grantToEdit: string = ''; public UserGrantContext: any = UserGrantContext; @@ -89,7 +105,16 @@ export class UserGrantsComponent implements OnInit, AfterViewInit { .subscribe(); } - private loadGrantsPage(): void { + private loadGrantsPage(filterValue?: string): void { + let queries: UserGrantSearchQuery[] = []; + if (this.userGrantSearchKey !== undefined && filterValue) { + const query = new UserGrantSearchQuery(); + query.setKey(this.userGrantSearchKey); + query.setMethod(SearchMethod.SEARCHMETHOD_CONTAINS_IGNORE_CASE); + query.setValue(filterValue); + queries = [query]; + } + this.dataSource.loadGrants( this.context, this.paginator?.pageIndex ?? 0, @@ -99,6 +124,7 @@ export class UserGrantsComponent implements OnInit, AfterViewInit { grantId: this.grantId, userId: this.userId, }, + queries, ); } @@ -114,7 +140,16 @@ export class UserGrantsComponent implements OnInit, AfterViewInit { this.dataSource.grantsSubject.value.forEach(row => this.selection.select(row)); } - public getGrantRoleOptions(grantId: string, projectId: string): void { + public loadGrantOptions(grant: UserGrantView.AsObject): void { + this.grantToEdit = grant.id; + if (grant.grantId && grant.projectId) { + this.getGrantRoleOptions(grant.grantId, grant.projectId); + } else if (grant.projectId) { + this.getProjectRoleOptions(grant.projectId); + } + } + + private getGrantRoleOptions(grantId: string, projectId: string): void { this.mgmtService.GetGrantedProjectByID(projectId, grantId).then(resp => { this.loadedGrantId = grantId; this.grantRoleOptions = resp.toObject().roleKeysList; @@ -123,7 +158,7 @@ export class UserGrantsComponent implements OnInit, AfterViewInit { }); } - public getProjectRoleOptions(projectId: string): void { + private getProjectRoleOptions(projectId: string): void { this.mgmtService.SearchProjectRoles(projectId, 100, 0).then(resp => { this.loadedProjectId = projectId; this.projectRoleOptions = resp.toObject().resultList; @@ -168,4 +203,26 @@ export class UserGrantsComponent implements OnInit, AfterViewInit { }, ); } + + public applyFilter(event: Event): void { + this.selection.clear(); + const filterValue = (event.target as HTMLInputElement).value; + + this.loadGrantsPage(filterValue); + } + + public setFilter(key: UserGrantSearchKey): void { + setTimeout(() => { + if (this.filter) { + (this.filter as any).nativeElement.focus(); + } + }, 100); + + if (this.userGrantSearchKey !== key) { + this.userGrantSearchKey = key; + } else { + this.userGrantSearchKey = undefined; + this.loadGrantsPage(); + } + } } diff --git a/console/src/app/modules/user-grants/user-grants.module.ts b/console/src/app/modules/user-grants/user-grants.module.ts index 56d2626121..1370036ce8 100644 --- a/console/src/app/modules/user-grants/user-grants.module.ts +++ b/console/src/app/modules/user-grants/user-grants.module.ts @@ -5,6 +5,7 @@ import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; 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'; @@ -39,6 +40,7 @@ import { UserGrantsComponent } from './user-grants.component'; MatCheckboxModule, MatTooltipModule, MatSelectModule, + MatInputModule, MatFormFieldModule, TranslateModule, HasRolePipeModule, diff --git a/console/src/app/pages/home/home.component.html b/console/src/app/pages/home/home.component.html index c5d8e701b3..dd89e0074c 100644 --- a/console/src/app/pages/home/home.component.html +++ b/console/src/app/pages/home/home.component.html @@ -24,6 +24,23 @@ {{'HOME.IAM'| translate}}

{{'HOME.IAM_DESC'| translate}}

+ + +
{{'HOME.IAM_CREATE_ORG' | translate}} + + + {{'HOME.IAM_POLICY_IAM' | translate}} + {{'HOME.IAM_POLICY_COMPLEXITY' | translate}} + {{'HOME.IAM_POLICY_LOGIN' | translate}} + + + {{'HOME.CHANGE_PWD' | translate}} +

{{dns?.url}}

diff --git a/console/src/app/pages/orgs/org-detail/domain-verification/domain-verification.component.scss b/console/src/app/pages/orgs/org-detail/domain-verification/domain-verification.component.scss index b02cd75537..730866762b 100644 --- a/console/src/app/pages/orgs/org-detail/domain-verification/domain-verification.component.scss +++ b/console/src/app/pages/orgs/org-detail/domain-verification/domain-verification.component.scss @@ -1,10 +1,10 @@ .btn-container { display: flex; margin: -.5rem; + align-items: center; button { margin: 1rem .5rem; - display: block; } } diff --git a/console/src/app/pages/orgs/org-detail/domain-verification/domain-verification.component.ts b/console/src/app/pages/orgs/org-detail/domain-verification/domain-verification.component.ts index 1b75be70e2..0fbbf41ef3 100644 --- a/console/src/app/pages/orgs/org-detail/domain-verification/domain-verification.component.ts +++ b/console/src/app/pages/orgs/org-detail/domain-verification/domain-verification.component.ts @@ -21,6 +21,7 @@ export class DomainVerificationComponent { public showNew: boolean = false; + public validating: boolean = false; constructor( private toast: ToastService, public dialogRef: MatDialogRef, @@ -54,10 +55,14 @@ export class DomainVerificationComponent { } public validate(): void { + this.validating = true; this.mgmtService.ValidateMyOrgDomain(this.domain.domain).then(() => { - this.dialogRef.close(false); + this.dialogRef.close(true); + this.toast.showInfo('ORG.PAGES.ORGDOMAIN.VERIFICATION_SUCCESSFUL', true); + this.validating = false; }).catch((error) => { this.toast.showError(error); + this.validating = false; }); } diff --git a/console/src/app/pages/orgs/org-detail/org-detail.component.scss b/console/src/app/pages/orgs/org-detail/org-detail.component.scss index 9a12b3b917..b14d23b209 100644 --- a/console/src/app/pages/orgs/org-detail/org-detail.component.scss +++ b/console/src/app/pages/orgs/org-detail/org-detail.component.scss @@ -36,7 +36,7 @@ .verified, .primary { - color: #5282c1; + color: var(--color-main); margin-right: 1rem; } diff --git a/console/src/app/pages/orgs/org-detail/org-detail.component.ts b/console/src/app/pages/orgs/org-detail/org-detail.component.ts index 46d8df084d..64c2584535 100644 --- a/console/src/app/pages/orgs/org-detail/org-detail.component.ts +++ b/console/src/app/pages/orgs/org-detail/org-detail.component.ts @@ -79,10 +79,12 @@ export class OrgDetailComponent implements OnInit, OnDestroy { }).catch(error => { this.toast.showError(error); }); - this.loadMembers(); + this.loadDomains(); + } - this.mgmtService.SearchMyOrgDomains(0, 100).then(result => { + public loadDomains(): void { + this.mgmtService.SearchMyOrgDomains().then(result => { this.domains = result.toObject().resultList; this.primaryDomain = this.domains.find(domain => domain.primary)?.domain ?? ''; }); @@ -91,7 +93,7 @@ export class OrgDetailComponent implements OnInit, OnDestroy { public setPrimary(domain: OrgDomainView.AsObject): void { this.mgmtService.setMyPrimaryOrgDomain(domain.domain).then(() => { this.toast.showInfo('ORG.TOAST.SETPRIMARY', true); - this.getData(); + this.loadDomains(); }).catch((error) => { this.toast.showError(error); }); @@ -202,12 +204,18 @@ export class OrgDetailComponent implements OnInit, OnDestroy { } public verifyDomain(domain: OrgDomainView.AsObject): void { - this.dialog.open(DomainVerificationComponent, { + const dialogRef = this.dialog.open(DomainVerificationComponent, { data: { domain: domain, }, width: '500px', }); + + dialogRef.afterClosed().subscribe((reload) => { + if (reload) { + this.loadDomains(); + } + }); } public loadMembers(): void { diff --git a/console/src/app/pages/orgs/orgs.module.ts b/console/src/app/pages/orgs/orgs.module.ts index afe782f78a..22a6b25b39 100644 --- a/console/src/app/pages/orgs/orgs.module.ts +++ b/console/src/app/pages/orgs/orgs.module.ts @@ -8,6 +8,7 @@ import { MatFormFieldModule } from '@angular/material/form-field'; import { MatIconModule } from '@angular/material/icon'; import { MatInputModule } from '@angular/material/input'; import { MatMenuModule } from '@angular/material/menu'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatTabsModule } from '@angular/material/tabs'; import { MatTooltipModule } from '@angular/material/tooltip'; import { TranslateModule } from '@ngx-translate/core'; @@ -51,6 +52,7 @@ import { OrgsRoutingModule } from './orgs-routing.module'; MemberCreateDialogModule, MatMenuModule, ChangesModule, + MatProgressSpinnerModule, AddDomainDialogModule, TranslateModule, SharedModule, diff --git a/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-grid/granted-project-grid.component.html b/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-grid/granted-project-grid.component.html index baab6e5704..7724188bdc 100644 --- a/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-grid/granted-project-grid.component.html +++ b/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-grid/granted-project-grid.component.html @@ -22,11 +22,10 @@ {{ item.creationDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }} - + + + + @@ -47,12 +46,20 @@ {{ item.creationDate | timestampToDate | localizedDate: 'EEE dd. MMM, HH:mm' }} -

{{'PROJECT.PAGES.NOITEMS' | translate}}

- \ No newline at end of file + + + + + \ No newline at end of file diff --git a/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-grid/granted-project-grid.component.ts b/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-grid/granted-project-grid.component.ts index 1441587c60..d4d5e7d5ec 100644 --- a/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-grid/granted-project-grid.component.ts +++ b/console/src/app/pages/projects/granted-projects/granted-project-list/granted-project-grid/granted-project-grid.component.ts @@ -47,11 +47,10 @@ export class GrantedProjectGridComponent implements OnChanges { this.setPrefixedItem('pinned-granted-projects', JSON.stringify( this.selection.selected.map(item => item.projectId), )).then(() => { - const filtered = this.notPinned.filter(item => item === selection.added.find(i => i === item)); - filtered.forEach((f, i) => { - this.notPinned.splice(i, 1); + selection.added.forEach(item => { + const index = this.notPinned.findIndex(i => i.projectId === item.projectId); + this.notPinned.splice(index, 1); }); - this.notPinned.push(...selection.removed); }); }); @@ -74,18 +73,10 @@ export class GrantedProjectGridComponent implements OnChanges { const array: string[] = JSON.parse(storageEntry); const toSelect: ProjectGrantView.AsObject[] = this.items.filter((item, index) => { if (array.includes(item.projectId)) { - // this.notPinned.splice(index, 1); return true; } }); this.selection.select(...toSelect); - - const toNotPinned: ProjectGrantView.AsObject[] = this.items.filter((item, index) => { - if (!array.includes(item.projectId)) { - return true; - } - }); - this.notPinned = toNotPinned; } }); } diff --git a/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.component.ts b/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.component.ts index 617896a5b5..7044e99e28 100644 --- a/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.component.ts +++ b/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.component.ts @@ -182,7 +182,10 @@ export class OwnedProjectDetailComponent implements OnInit, OnDestroy { if (resp) { this.mgmtService.RemoveProject(this.projectId).then(() => { this.toast.showInfo('PROJECT.TOAST.DELETED', true); - this.router.navigate(['/projects']); + const params: Params = { + 'deferredReload': true, + }; + this.router.navigate(['/projects'], { queryParams: params }); }).catch(error => { this.toast.showError(error); }); diff --git a/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-grid/owned-project-grid.component.html b/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-grid/owned-project-grid.component.html index c7ee504df8..5b87846dd3 100644 --- a/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-grid/owned-project-grid.component.html +++ b/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-grid/owned-project-grid.component.html @@ -25,11 +25,9 @@ }} - + + + @@ -52,15 +50,9 @@ }} - - + + +

{{'PROJECT.PAGES.NOITEMS' | translate}}

@@ -71,4 +63,19 @@ {{'PROJECT.PAGES.ADDNEW' | translate}} - \ No newline at end of file + + + + + + + + + \ No newline at end of file diff --git a/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-grid/owned-project-grid.component.ts b/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-grid/owned-project-grid.component.ts index 0b0755587e..e2db225480 100644 --- a/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-grid/owned-project-grid.component.ts +++ b/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-grid/owned-project-grid.component.ts @@ -63,11 +63,10 @@ export class OwnedProjectGridComponent implements OnChanges { this.setPrefixedItem('pinned-projects', JSON.stringify( this.selection.selected.map(item => item.projectId), )).then(() => { - const filtered = this.notPinned.filter(item => item === selection.added.find(i => i === item)); - filtered.forEach((f, i) => { - this.notPinned.splice(i, 1); + selection.added.forEach(item => { + const index = this.notPinned.findIndex(i => i.projectId === item.projectId); + this.notPinned.splice(index, 1); }); - this.notPinned.push(...selection.removed); }); }); @@ -102,13 +101,6 @@ export class OwnedProjectGridComponent implements OnChanges { } }); this.selection.select(...toSelect); - - const toNotPinned: ProjectView.AsObject[] = this.items.filter((item, index) => { - if (!array.includes(item.projectId)) { - return true; - } - }); - this.notPinned = toNotPinned; } }); } @@ -133,7 +125,13 @@ export class OwnedProjectGridComponent implements OnChanges { this.changedView.emit(true); } - public deleteProject(item: ProjectView.AsObject): void { + public toggle(item: ProjectView.AsObject, event: any): void { + event.stopPropagation(); + this.selection.toggle(item); + } + + public deleteProject(event: any, item: ProjectView.AsObject): void { + event.stopPropagation(); const dialogRef = this.dialog.open(WarnDialogComponent, { data: { confirmKey: 'ACTIONS.DELETE', @@ -152,6 +150,16 @@ export class OwnedProjectGridComponent implements OnChanges { if (index > -1) { this.items.splice(index, 1); } + + const indexSelection = this.selection.selected.findIndex(iter => iter.projectId === item.projectId); + if (indexSelection > -1) { + this.selection.selected.splice(indexSelection, 1); + } + + const indexPinned = this.notPinned.findIndex(iter => iter.projectId === item.projectId); + if (indexPinned > -1) { + this.notPinned.splice(indexPinned, 1); + } }).catch(error => { this.toast.showError(error); }); diff --git a/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-list.component.ts b/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-list.component.ts index 8b52d2bb71..4cb9d30dc4 100644 --- a/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-list.component.ts +++ b/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-list.component.ts @@ -4,10 +4,11 @@ import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { MatPaginator, PageEvent } from '@angular/material/paginator'; import { MatTableDataSource } from '@angular/material/table'; -import { Router } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; import { Timestamp } from 'google-protobuf/google/protobuf/timestamp_pb'; import { BehaviorSubject, Observable, Subscription } from 'rxjs'; +import { take } from 'rxjs/operators'; import { WarnDialogComponent } from 'src/app/modules/warn-dialog/warn-dialog.component'; import { ProjectView } from 'src/app/proto/generated/management_pb'; import { ManagementService } from 'src/app/services/mgmt.service'; @@ -59,6 +60,7 @@ export class OwnedProjectListComponent implements OnInit, OnDestroy { public zitadelProjectId: string = ''; constructor(private router: Router, + private route: ActivatedRoute, public translate: TranslateService, private mgmtService: ManagementService, private toast: ToastService, @@ -70,7 +72,15 @@ export class OwnedProjectListComponent implements OnInit, OnDestroy { } public ngOnInit(): void { - this.getData(10, 0); + this.route.queryParams.pipe(take(1)).subscribe(params => { + console.log(params); + this.getData(); + if (params.deferredReload) { + setTimeout(() => { + this.getData(); + }, 2000); + } + }); } public ngOnDestroy(): void { @@ -97,7 +107,7 @@ export class OwnedProjectListComponent implements OnInit, OnDestroy { this.router.navigate(['/projects', 'create']); } - private async getData(limit: number, offset: number): Promise { + private async getData(limit?: number, offset?: number): Promise { this.loadingSubject.next(true); this.mgmtService.SearchProjects(limit, offset).then(res => { const response = res.toObject(); diff --git a/console/src/app/pages/users/user-create/user-create.component.ts b/console/src/app/pages/users/user-create/user-create.component.ts index 4294c32a55..3efd84bc1c 100644 --- a/console/src/app/pages/users/user-create/user-create.component.ts +++ b/console/src/app/pages/users/user-create/user-create.component.ts @@ -68,7 +68,7 @@ export class UserCreateComponent implements OnDestroy { } private async loadOrg(): Promise { - const domains = (await this.mgmtService.SearchMyOrgDomains(0, 100).then(doms => doms.toObject())); + const domains = (await this.mgmtService.SearchMyOrgDomains().then(doms => doms.toObject())); const found = domains.resultList.find(domain => domain.primary); if (found) { this.primaryDomain = found; diff --git a/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.scss b/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.scss index 711b44e18e..411f391e2f 100644 --- a/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.scss +++ b/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.scss @@ -19,7 +19,7 @@ i { margin-left: 1rem; - color: #5282c1; + color: var(--color-main); } } diff --git a/console/src/app/pages/users/user-detail/memberships/memberships.component.html b/console/src/app/pages/users/user-detail/memberships/memberships.component.html index 095f4cca09..c4b9fa3611 100644 --- a/console/src/app/pages/users/user-detail/memberships/memberships.component.html +++ b/console/src/app/pages/users/user-detail/memberships/memberships.component.html @@ -23,7 +23,7 @@ -
+
{{memberships.totalResult}}
diff --git a/console/src/app/pages/users/user-detail/user-detail/user-detail.component.html b/console/src/app/pages/users/user-detail/user-detail/user-detail.component.html index 4d21a5fa0d..60e8e523f0 100644 --- a/console/src/app/pages/users/user-detail/user-detail/user-detail.component.html +++ b/console/src/app/pages/users/user-detail/user-detail/user-detail.component.html @@ -6,13 +6,13 @@

{{user.human ? user.human?.displayName : user.machine?.name}}

- - - + + + diff --git a/console/src/app/pages/users/user-list/user-table/user-table.component.scss b/console/src/app/pages/users/user-list/user-table/user-table.component.scss index df6717dcd4..4f910725e3 100644 --- a/console/src/app/pages/users/user-list/user-table/user-table.component.scss +++ b/console/src/app/pages/users/user-list/user-table/user-table.component.scss @@ -18,6 +18,26 @@ &:last-child { padding-right: 0; } + + .search-button, + .dlt-button { + visibility: hidden; + } + + &:hover, + &.search-active { + .search-button { + visibility: visible; + } + } + } + + tr { + &:hover { + .dlt-button { + visibility: visible; + } + } } .selection { @@ -27,31 +47,6 @@ } } -tr { - button { - visibility: hidden; - } - - &:hover { - button { - visibility: visible; - } - } -} - -th { - .search-button { - visibility: hidden; - } - - &:hover, - &.search-active { - .search-button { - visibility: visible; - } - } -} - .filtername { margin: 0 1rem; } diff --git a/console/src/app/pages/users/user-list/user-table/user-table.component.ts b/console/src/app/pages/users/user-list/user-table/user-table.component.ts index 6f4bd212c8..a79be84eb7 100644 --- a/console/src/app/pages/users/user-list/user-table/user-table.component.ts +++ b/console/src/app/pages/users/user-list/user-table/user-table.component.ts @@ -121,6 +121,7 @@ export class UserTableComponent implements OnInit { } public applyFilter(event: Event): void { + this.selection.clear(); const filterValue = (event.target as HTMLInputElement).value; this.getData( diff --git a/console/src/app/services/mgmt.service.ts b/console/src/app/services/mgmt.service.ts index c02012ed41..e006f9232b 100644 --- a/console/src/app/services/mgmt.service.ts +++ b/console/src/app/services/mgmt.service.ts @@ -1,6 +1,7 @@ import { Injectable } from '@angular/core'; import { Empty } from 'google-protobuf/google/protobuf/empty_pb'; import { Timestamp } from 'google-protobuf/google/protobuf/timestamp_pb'; +import { BehaviorSubject } from 'rxjs'; import { AddMachineKeyRequest, @@ -160,6 +161,9 @@ export type ResponseMapper = (resp: TResp) => TMappedResp; providedIn: 'root', }) export class ManagementService { + public ownedProjectsCount: BehaviorSubject = new BehaviorSubject(0); + public grantedProjectsCount: BehaviorSubject = new BehaviorSubject(0); + constructor(private readonly grpcService: GrpcService) { } public SearchIdps( @@ -393,11 +397,9 @@ export class ManagementService { return this.grpcService.mgmt.removeMyOrgDomain(req); } - public SearchMyOrgDomains(offset: number, limit: number, queryList?: OrgDomainSearchQuery[]): + public SearchMyOrgDomains(queryList?: OrgDomainSearchQuery[]): Promise { const req: OrgDomainSearchRequest = new OrgDomainSearchRequest(); - req.setLimit(limit); - req.setOffset(offset); if (queryList) { req.setQueriesList(queryList); } @@ -834,13 +836,17 @@ export class ManagementService { // USER GRANTS public SearchUserGrants( - limit: number, - offset: number, + limit?: number, + offset?: number, queryList?: UserGrantSearchQuery[], ): Promise { const req = new UserGrantSearchRequest(); - req.setLimit(limit); - req.setOffset(offset); + if (limit) { + req.setLimit(limit); + } + if (offset) { + req.setOffset(offset); + } if (queryList) { req.setQueriesList(queryList); } @@ -929,14 +935,26 @@ export class ManagementService { // project public SearchProjects( - limit: number, offset: number, queryList?: ProjectSearchQuery[]): Promise { + limit?: number, offset?: number, queryList?: ProjectSearchQuery[]): Promise { const req = new ProjectSearchRequest(); - req.setLimit(limit); - req.setOffset(offset); + if (limit) { + req.setLimit(limit); + } + if (offset) { + req.setOffset(offset); + } + if (queryList) { req.setQueriesList(queryList); } - return this.grpcService.mgmt.searchProjects(req); + return this.grpcService.mgmt.searchProjects(req).then(value => { + const count = value.toObject().resultList.length; + if (count >= 0) { + this.ownedProjectsCount.next(count); + } + + return value; + }); } public SearchGrantedProjects( @@ -947,10 +965,12 @@ export class ManagementService { if (queryList) { req.setQueriesList(queryList); } - return this.grpcService.mgmt.searchGrantedProjects(req); + return this.grpcService.mgmt.searchGrantedProjects(req).then(value => { + this.grantedProjectsCount.next(value.toObject().resultList.length); + return value; + }); } - public GetZitadelDocs(): Promise { const req = new Empty(); return this.grpcService.mgmt.getZitadelDocs(req); @@ -972,7 +992,11 @@ export class ManagementService { public CreateProject(project: ProjectCreateRequest.AsObject): Promise { const req = new ProjectCreateRequest(); req.setName(project.name); - return this.grpcService.mgmt.createProject(req); + return this.grpcService.mgmt.createProject(req).then(value => { + const current = this.ownedProjectsCount.getValue(); + this.ownedProjectsCount.next(current + 1); + return value; + }); } public UpdateProject(id: string, projectView: ProjectView.AsObject): Promise { @@ -1221,7 +1245,11 @@ export class ManagementService { public RemoveProject(id: string): Promise { const req = new ProjectID(); req.setId(id); - return this.grpcService.mgmt.removeProject(req); + return this.grpcService.mgmt.removeProject(req).then(value => { + const current = this.ownedProjectsCount.getValue(); + this.ownedProjectsCount.next(current > 0 ? current - 1 : 0); + return value; + }); } diff --git a/console/src/assets/i18n/de.json b/console/src/assets/i18n/de.json index 862f46c374..4d96e8cc46 100644 --- a/console/src/assets/i18n/de.json +++ b/console/src/assets/i18n/de.json @@ -5,14 +5,26 @@ "SECURITYANDPRIVACY": "Datenschutz und Personalisierung", "SECURITYANDPRIVACY_DESC": "Verwalte Deine Informationen und Sicherheitseinstellungen.", "SECURITYANDPRIVACY_BUTTON": "Daten verwalten und personalisieren", + "CHANGE_PWD":"Password ändern", "PROTECTION": "Organisationsrichtlinien", "PROTECTION_DESC": "Verwalte Deine Organisationsrichtlinien und entdecke die vorgefertigte Lösungen, die Zeit sparen und Sicherheit gewährleisten.", "PROTECTION_BUTTON": "Erkunden", "PROJECTS": "Volle Skalierbarkeit und Anpassungsfähigkeit", "PROJECTS_DESC": "Autorisiere andere Benutzer, Deine eigenen Projekte zu verwenden, oder erstelle benutzerdefinierte Rollen für berechtigte Projekte", "PROJECTS_BUTTON": "Projektübersicht", + "PROJECTS_NEW_LINK":"Neues Projekt erstellen", + "IAM_CREATE_ORG":"Organisation erstellen", + "ORG_POLICY_COMPLEXITY":"Passwort Komplexität", + "ORG_POLICY_IAM":"Organisation Zugangseinstellungen", + "ORG_POLICY_LOGIN":"Login Richtlinie", + "IAM_POLICY_COMPLEXITY":"Systemweite Passwort Komplexität", + "IAM_POLICY_IAM":"Systemweite Zugangseinstellungen", + "IAN_POLICY_LOGIN":"Systemweite Login Richtlinie", "USERS": "Erstelle und verwalte Deine Benutzer.", "USERS_DESC": "Überwache Dein Rollenkonzept in Echtzeit. Ergreife sofort Massnahmen.", + "USERS_HUMANS":"Zeige Benutzer", + "USERS_MACHINES": "Zeige Service User", + "USERS_CREATE":"User erstellen", "USERS_BUTTON": "Benutzer anzeigen", "IAM": "Identity- und Access-Management", "IAM_DESC": "Verwalte Deine Organisationen und Administratoren.", @@ -26,6 +38,7 @@ "PERSONAL_INFO": "Persönliche Informationen", "IAM":"Administration", "ORGANIZATION": "Organisation", + "ADMINSECTION":"Administration", "PROJECTSSECTION":"Projektsektion", "PROJECT": "Projekte", "GRANTEDPROJECT":"Berechtigte Projekte", @@ -106,8 +119,11 @@ "1":"Nach Username filtern", "2":"Nach Vornamen filtern", "3":"Nach Nachnamen filtern", + "4":"Nach rollenschlüssel filtern", "5":"Nach Display Namen filtern", - "6":"Nach Email filtern" + "6":"Nach Email filtern", + "10":"Nach Organisationsname filtern", + "12":"Project Name" } }, "MFA": { @@ -384,6 +400,7 @@ "VERIFICATION_NEWTOKEN_DESC":"Wenn Du ein neues Token anfordern willst, klicke auf die gewünschte Methode. Wenn Du ein vorhandenes Token validieren möchtest, klicke auf \"Verifizieren\".", "VERIFICATION_VALIDATION_ONGOING":"Ein Token zur Validierung wurde bereits angefragt. Klicke auf \"Verifizieren\", um dieses Token zu validieren.", "VERIFICATION_VALIDATION_ONGOING_TYPE":"Typ des Tokens:", + "VERIFICATION_SUCCESSFUL":"Domain erfolgreich validiert!", "REQUESTNEWTOKEN":"Neues Token anfordern", "TYPES": { "1":"HTTP", diff --git a/console/src/assets/i18n/en.json b/console/src/assets/i18n/en.json index a76168ff23..a0a9700ecd 100644 --- a/console/src/assets/i18n/en.json +++ b/console/src/assets/i18n/en.json @@ -5,14 +5,26 @@ "SECURITYANDPRIVACY": "Data Protection and Personalisation", "SECURITYANDPRIVACY_DESC": "Manage Your Information and Security Settings", "SECURITYANDPRIVACY_BUTTON": "Personalise Information and Security", + "CHANGE_PWD":"Change Password", "PROTECTION": "Organisational Policies", "PROTECTION_DESC": "Manage your organisational guidelines. Explore some pre-packaged solutions that save you time and ensure security.", "PROTECTION_BUTTON": "Explore", "PROJECTS": "Create and Manage Your Applications and Projects", "PROJECTS_DESC": "Authorize others to use your projects or define custom roles on eligible projects.", "PROJECTS_BUTTON": "Project Overview", + "PROJECTS_NEW_LINK":"Create new project", + "ORG_POLICY_COMPLEXITY":"Password Complexity Settings", + "ORG_POLICY_IAM":"Organisation Access Properties", + "ORG_POLICY_LOGIN":"Login Policy", + "IAM_CREATE_ORG":"Create organisation", + "IAM_POLICY_COMPLEXITY":"System Password Complexity Settings", + "IAM_POLICY_IAM":"System Access Properties", + "IAM_POLICY_LOGIN":"System Login Policy", "USERS": "Create and Manage Your Users", "USERS_DESC": "Monitor your role concept in real time. Take immediate action.", + "USERS_HUMANS":"Show human users", + "USERS_MACHINES": "Show machine users", + "USERS_CREATE":"Create User", "USERS_BUTTON": "Show Users", "IAM": "Identity and Access Management", "IAM_DESC": "Manage your organisations and administrators.", @@ -26,6 +38,7 @@ "PERSONAL_INFO": "Personal Information", "IAM":"Administration", "ORGANIZATION": "Organisation", + "ADMINSECTION":"Administration", "PROJECTSSECTION":"Projects Section", "PROJECT": "Projects", "GRANTEDPROJECT":"Granted Projects", @@ -106,8 +119,11 @@ "1":"Filter for Username", "2":"filter for Firstname", "3":"filter for Lastname", + "4":"filter for role Key", "5":"filter for DisplayName", - "6":"filter for email" + "6":"filter for email", + "10":"filter for organisation name", + "12":"filter for project name" } }, "MFA": { @@ -384,6 +400,7 @@ "VERIFICATION_NEWTOKEN_DESC":"If you want to request a new token, select you preferred method. If you want to validate a persisting token, click the button above.", "VERIFICATION_VALIDATION_ONGOING":"A verification token has already been requested. Click on the button to trigger a verification check.", "VERIFICATION_VALIDATION_ONGOING_TYPE":"Type of the token:", + "VERIFICATION_SUCCESSFUL":"Domain successfully verified!", "REQUESTNEWTOKEN":"Request new Token", "TYPES": { "1":"HTTP", diff --git a/console/src/component-themes.scss b/console/src/component-themes.scss index e7611f44dd..ea92746ca4 100644 --- a/console/src/component-themes.scss +++ b/console/src/component-themes.scss @@ -1,5 +1,6 @@ @import 'src/app/modules/card/card'; @import './styles/table'; +@import './styles/link.scss'; @import './styles/sidenav-list'; @import 'src/app/modules/avatar/avatar.component'; @import 'src/app/modules/changes/changes.component'; @@ -22,4 +23,5 @@ @include meta-theme($theme); @include theme-card($theme); @include textvar($theme); + @include link-theme($theme); } diff --git a/console/src/styles.scss b/console/src/styles.scss index f9d5c50877..5d9daaa0d2 100644 --- a/console/src/styles.scss +++ b/console/src/styles.scss @@ -61,20 +61,20 @@ $caos-dark-brand: ( ); $caos-light-brand: ( - 50: #fff, - 100: #dde6f3, - 200: #b4c9e4, - 300: #7fa3d1, - 400: #6992c9, - 500: #5282c1, - 600: #4072b4, - 700: #38649d, - 800: #305687, - 900: #284770, - A100: #fff, - A200: #dde6f3, - A300: #6992c9, - A400: #38649d, + 50: #eaedfa, + 100: #ccd2f2, + 200: #aab4ea, + 300: #8796e1, + 400: #6e80da, + 500: #5469d4, + 600: #4d61cf, + 700: #4356c9, + 800: #3a4cc3, + 900: #293bb9, + A100: #f9faff, + A200: #c6ccff, + A300: #939fff, + A400: #7a88ff, A500:#333, A600: #000, A700: #8795a1, @@ -167,7 +167,9 @@ $custom-typography: @include component-themes($light-theme); @include angular-material-theme($light-theme); - --table-row-back: #eceef1; + --grey: #697386; + --table-row-back: #e7ebf0; + --color-main: #5469d4; .sidenav, .main-container, @@ -194,13 +196,18 @@ $custom-typography: border-radius: 8px; cursor: pointer; } + + .root-header { + box-shadow: inset 0 -1px #e3e8ee; + } } .dark-theme { @include component-themes($dark-theme); @include angular-material-theme($dark-theme); - --table-row-back: #363738; + --table-row-back: #292a2b; + --color-main: #5282c1; .sidenav, .main-container, @@ -227,6 +234,10 @@ $custom-typography: border-radius: 8px; cursor: pointer; } + + .root-header { + box-shadow: inset 0 -1px #303131; + } } // @include mat-checkbox-theme($candy-app-theme); diff --git a/console/src/styles/link.scss b/console/src/styles/link.scss new file mode 100644 index 0000000000..56c4087319 --- /dev/null +++ b/console/src/styles/link.scss @@ -0,0 +1,16 @@ +@import '~@angular/material/theming'; + +@mixin link-theme($theme) { + /* stylelint-disable */ + $primary: map-get($theme, primary); + $primary-color: mat-color($primary, 500); + $primary-color-lighter: mat-color($primary, A300); + + a { + color: $primary-color; + } + + a:hover { + color: $primary-color-lighter; + } +} diff --git a/console/src/styles/sidenav-list.scss b/console/src/styles/sidenav-list.scss index eb2f5b0f63..a2f88e9bff 100644 --- a/console/src/styles/sidenav-list.scss +++ b/console/src/styles/sidenav-list.scss @@ -7,11 +7,12 @@ $primary-color: mat-color($primary, 500); $accent-color: mat-color($accent, 500); $primary-dark: mat-color($primary, A900); + $foreground: map-get($theme, foreground); $sec-dark: mat-color($primary, A800); /* stylelint-enable */ .nav-item { - color: inherit; + color: mat-color($foreground, text) !important; &:hover { background-color: $sec-dark; @@ -48,27 +49,62 @@ } .root-header { - box-shadow: 0 5px 10px rgba(0, 0, 0, .12); + box-shadow: inset 0 -1px #e3e8ee; background-color: $primary-dark !important; transition: background-color .3s cubic-bezier(.645, .045, .355, 1); } .admin-line { - background: $accent-color; + position: fixed; + bottom: 0; + left: 0; + right: calc(100vw - 300px); + background-color: $primary-color; color: white; - margin-right: 1rem; - border-top-right-radius: 50vw; - border-bottom-right-radius: 50vw; + z-index: 1; + font-size: 13px; + padding: 3px 2rem; + transform: translateY(75%); + transition: all .2s; + border-top-right-radius: 5px; + + span { + display: none; + } + + button { + height: 1.2rem; + width: 1.2rem; + line-height: 1.2rem; + margin-right: 1rem; + + * { + height: 1.2rem; + width: 1.2rem; + line-height: 1rem; + } + } &::before { content: ''; position: absolute; width: 0; - bottom: 0; + height: 0; + top: 0; left: 0; - border-bottom: 20px solid $primary-dark; - border-right: 20px solid transparent; + border-bottom: 20px solid transparent; + border-left: 20px solid $primary-dark; transition: border-color .3s cubic-bezier(.645, .045, .355, 1); } + + &.expanded, + &:hover { + transform: translateY(0%); + right: 0; + + span { + display: inline-block; + } + } } } diff --git a/console/src/styles/table.scss b/console/src/styles/table.scss index 3397770f57..dae3cccb91 100644 --- a/console/src/styles/table.scss +++ b/console/src/styles/table.scss @@ -36,7 +36,7 @@ &:hover { td { - background-color: var(--table-row-back); // rgba($inv-color, .05); + background: var(--table-row-back); // rgba($inv-color, .05); } } }