From af60b889971d59387855cbbde91bdff652294725 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Fri, 24 Jul 2020 09:48:58 +0200 Subject: [PATCH] fix(console): user create loading state and i18n, improved app create stepper, invalid token dialog, cleanup, new home (#509) * fix iam member model * fix org member model * fix auth user loading * copytoclipboard directive * directive logs, load bar on init, create user * typo * welcome section, contributor spinner * fix home link * fix stepper flow * show dialog on invalid token * fix app table refresh, pin icons light theme * cleanup contributor * Update console/src/assets/i18n/en.json Co-authored-by: Florian Forster * Update console/src/assets/i18n/de.json Co-authored-by: Florian Forster * Update console/src/assets/i18n/de.json Co-authored-by: Florian Forster * Update console/src/assets/i18n/de.json Co-authored-by: Florian Forster Co-authored-by: Florian Forster --- console/src/app/app.component.ts | 15 ++ console/src/app/app.module.ts | 4 + .../copy-to-clipboard.directive.ts | 31 ++++ .../copy-to-clipboard.module.ts | 19 +++ .../accounts-card.component.html | 4 +- .../app/modules/avatar/avatar.component.html | 3 +- .../app/modules/avatar/avatar.component.scss | 6 +- .../src/app/modules/avatar/avatar.module.ts | 2 + .../contributors/contributors.component.html | 2 + .../contributors/contributors.component.scss | 7 +- .../contributors/contributors.component.ts | 17 ++ .../contributors/contributors.module.ts | 2 + .../warn-dialog/warn-dialog.component.html | 4 +- .../warn-dialog/warn-dialog.component.scss | 5 +- .../src/app/pages/home/home.component.html | 27 +++- .../src/app/pages/home/home.component.scss | 48 +++--- console/src/app/pages/home/home.component.ts | 5 +- console/src/app/pages/home/home.module.ts | 4 + .../iam/iam-members/iam-members-datasource.ts | 37 ++--- .../iam/iam-members/iam-members.component.ts | 7 +- .../iam/iam-views/iam-views.component.html | 4 +- console/src/app/pages/iam/iam.component.html | 7 +- .../orgs/org-detail/org-detail.component.html | 4 +- .../org-members/org-members-datasource.ts | 41 ++--- .../orgs/org-members/org-members.component.ts | 14 +- .../apps/app-create/app-create.component.html | 67 ++++---- .../apps/app-create/app-create.component.scss | 6 +- .../apps/app-create/app-create.component.ts | 153 ++++++++++-------- .../apps/app-detail/app-detail.component.html | 10 +- .../apps/app-detail/app-detail.component.scss | 4 + .../apps/app-detail/app-detail.component.ts | 3 +- .../app-secret-dialog.component.html | 2 +- .../app-secret-dialog.component.ts | 18 --- .../app/pages/projects/apps/apps.module.ts | 2 + .../granted-project-detail.component.html | 4 +- .../granted-project-detail.component.ts | 5 +- .../granted-project-grid.component.html | 6 +- .../application-grid.component.html | 9 +- .../application-grid.component.scss | 23 ++- .../application-grid.component.ts | 2 +- .../applications/applications-datasource.ts | 2 +- .../applications/applications.component.html | 81 ++++------ .../applications/applications.component.scss | 94 ++++------- .../applications/applications.component.ts | 7 +- .../owned-project-detail.component.html | 4 +- .../owned-project-detail.component.ts | 5 +- .../owned-project-detail.module.ts | 2 + .../owned-project-grid.component.html | 6 +- .../owned-project-grid.component.scss | 4 - .../project-grant-detail.module.ts | 2 + .../user-create/user-create.component.html | 2 + .../user-create/user-create.component.ts | 7 + .../users/user-create/user-create.module.ts | 2 + .../auth-user-detail.component.html | 2 +- .../auth-user-detail.component.ts | 30 +--- .../auth-user-mfa/auth-user-mfa.component.ts | 1 - .../theme-setting/theme-card.scss | 11 ++ .../theme-setting.component.scss | 10 +- .../users/user-detail/user-detail.module.ts | 2 + .../user-detail/user-detail.component.html | 5 +- .../user-detail/user-detail.component.ts | 40 +---- console/src/app/services/toast.service.ts | 23 ++- console/src/assets/i18n/de.json | 18 ++- console/src/assets/i18n/en.json | 18 ++- .../zitadel-logo-oneline-lightdesign.svg | 16 +- console/src/assets/mdi/broom.svg | 1 + console/src/assets/mdi/pin-outline.svg | 1 + console/src/assets/mdi/pin.svg | 1 + console/src/component-themes.scss | 2 +- console/src/styles.scss | 4 +- console/src/styles/card.scss | 6 + console/src/styles/sidenav-list.scss | 5 +- console/src/styles/theme-card.scss | 21 --- 73 files changed, 581 insertions(+), 487 deletions(-) create mode 100644 console/src/app/directives/copy-to-clipboard/copy-to-clipboard.directive.ts create mode 100644 console/src/app/directives/copy-to-clipboard/copy-to-clipboard.module.ts create mode 100644 console/src/app/pages/users/user-detail/auth-user-detail/theme-setting/theme-card.scss create mode 100644 console/src/assets/mdi/broom.svg create mode 100644 console/src/assets/mdi/pin-outline.svg create mode 100644 console/src/assets/mdi/pin.svg delete mode 100644 console/src/styles/theme-card.scss diff --git a/console/src/app/app.component.ts b/console/src/app/app.component.ts index ffd5df62e..bd12730be 100644 --- a/console/src/app/app.component.ts +++ b/console/src/app/app.component.ts @@ -204,6 +204,21 @@ export class AppComponent implements OnDestroy { this.domSanitizer.bypassSecurityTrustResourceUrl('assets/mdi/lock-reset.svg'), ); + this.matIconRegistry.addSvgIcon( + 'mdi_broom', + this.domSanitizer.bypassSecurityTrustResourceUrl('assets/mdi/broom.svg'), + ); + + this.matIconRegistry.addSvgIcon( + 'mdi_pin_outline', + this.domSanitizer.bypassSecurityTrustResourceUrl('assets/mdi/pin-outline.svg'), + ); + + this.matIconRegistry.addSvgIcon( + 'mdi_pin', + this.domSanitizer.bypassSecurityTrustResourceUrl('assets/mdi/pin.svg'), + ); + this.orgSub = this.authService.activeOrgChanged.subscribe(org => { this.org = org; }); diff --git a/console/src/app/app.module.ts b/console/src/app/app.module.ts index 53a729a84..681d4fdf1 100644 --- a/console/src/app/app.module.ts +++ b/console/src/app/app.module.ts @@ -5,6 +5,7 @@ import localeDe from '@angular/common/locales/de'; import { APP_INITIALIZER, NgModule } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatCardModule } from '@angular/material/card'; +import { MatDialogModule } from '@angular/material/dialog'; import { MatIconModule } from '@angular/material/icon'; import { MatMenuModule } from '@angular/material/menu'; import { MatProgressBarModule } from '@angular/material/progress-bar'; @@ -27,6 +28,7 @@ import { HasRoleModule } from './directives/has-role/has-role.module'; import { OutsideClickModule } from './directives/outside-click/outside-click.module'; import { AccountsCardModule } from './modules/accounts-card/accounts-card.module'; import { AvatarModule } from './modules/avatar/avatar.module'; +import { WarnDialogModule } from './modules/warn-dialog/warn-dialog.module'; import { SignedoutComponent } from './pages/signedout/signedout.component'; import { HasRolePipeModule } from './pipes/has-role-pipe.module'; import { AuthUserService } from './services/auth-user.service'; @@ -105,6 +107,8 @@ const authConfig: AuthConfig = { MatMenuModule, MatSnackBarModule, AvatarModule, + WarnDialogModule, + MatDialogModule, ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }), ], providers: [ diff --git a/console/src/app/directives/copy-to-clipboard/copy-to-clipboard.directive.ts b/console/src/app/directives/copy-to-clipboard/copy-to-clipboard.directive.ts new file mode 100644 index 000000000..d27fcb1d0 --- /dev/null +++ b/console/src/app/directives/copy-to-clipboard/copy-to-clipboard.directive.ts @@ -0,0 +1,31 @@ +import { Directive, EventEmitter, HostListener, Input, Output } from '@angular/core'; + +@Directive({ + selector: '[appCopyToClipboard]', +}) +export class CopyToClipboardDirective { + @Input() valueToCopy: string = ''; + @Output() copiedValue: EventEmitter = new EventEmitter(); + + @HostListener('document:click', ['$event.target']) onMouseEnter(): void { + this.copytoclipboard(this.valueToCopy); + } + + public copytoclipboard(value: string): void { + const selBox = document.createElement('textarea'); + selBox.style.position = 'fixed'; + selBox.style.left = '0'; + selBox.style.top = '0'; + selBox.style.opacity = '0'; + selBox.value = value; + document.body.appendChild(selBox); + selBox.focus(); + selBox.select(); + document.execCommand('copy'); + document.body.removeChild(selBox); + this.copiedValue.emit(value); + setTimeout(() => { + this.copiedValue.emit(''); + }, 3000); + } +} diff --git a/console/src/app/directives/copy-to-clipboard/copy-to-clipboard.module.ts b/console/src/app/directives/copy-to-clipboard/copy-to-clipboard.module.ts new file mode 100644 index 000000000..4063210a3 --- /dev/null +++ b/console/src/app/directives/copy-to-clipboard/copy-to-clipboard.module.ts @@ -0,0 +1,19 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; + +import { CopyToClipboardDirective } from './copy-to-clipboard.directive'; + + + +@NgModule({ + declarations: [ + CopyToClipboardDirective, + ], + imports: [ + CommonModule, + ], + exports: [ + CopyToClipboardDirective, + ], +}) +export class CopyToClipboardModule { } diff --git a/console/src/app/modules/accounts-card/accounts-card.component.html b/console/src/app/modules/accounts-card/accounts-card.component.html index 28bcd24bc..6c7aa6bf8 100644 --- a/console/src/app/modules/accounts-card/accounts-card.component.html +++ b/console/src/app/modules/accounts-card/accounts-card.component.html @@ -7,7 +7,7 @@ {{profile?.preferredLoginName}} IAM USER - + - + \ No newline at end of file diff --git a/console/src/app/modules/avatar/avatar.component.html b/console/src/app/modules/avatar/avatar.component.html index 516519435..b12ecefbc 100644 --- a/console/src/app/modules/avatar/avatar.component.html +++ b/console/src/app/modules/avatar/avatar.component.html @@ -1,4 +1,5 @@ -
{{credentials}} diff --git a/console/src/app/modules/avatar/avatar.component.scss b/console/src/app/modules/avatar/avatar.component.scss index 97e512e6c..046b6d68a 100644 --- a/console/src/app/modules/avatar/avatar.component.scss +++ b/console/src/app/modules/avatar/avatar.component.scss @@ -16,8 +16,8 @@ outline: none; color: white; - &.active:hover { - border: 2px solid #8795a1; - } + // &.active:hover { + // border: 2px solid #8795a1; + // } } } \ No newline at end of file diff --git a/console/src/app/modules/avatar/avatar.module.ts b/console/src/app/modules/avatar/avatar.module.ts index bb98db527..ab0c97020 100644 --- a/console/src/app/modules/avatar/avatar.module.ts +++ b/console/src/app/modules/avatar/avatar.module.ts @@ -1,5 +1,6 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; +import { MatRippleModule } from '@angular/material/core'; import { AvatarComponent } from './avatar.component'; @@ -9,6 +10,7 @@ import { AvatarComponent } from './avatar.component'; declarations: [AvatarComponent], imports: [ CommonModule, + MatRippleModule, ], exports: [ AvatarComponent, diff --git a/console/src/app/modules/contributors/contributors.component.html b/console/src/app/modules/contributors/contributors.component.html index 18fcacce7..8d6548226 100644 --- a/console/src/app/modules/contributors/contributors.component.html +++ b/console/src/app/modules/contributors/contributors.component.html @@ -3,6 +3,8 @@ {{ description }}
+ +
; @Output() addClicked: EventEmitter = new EventEmitter(); @Output() showDetailClicked: EventEmitter = new EventEmitter(); diff --git a/console/src/app/modules/contributors/contributors.module.ts b/console/src/app/modules/contributors/contributors.module.ts index 358622060..a1a22614a 100644 --- a/console/src/app/modules/contributors/contributors.module.ts +++ b/console/src/app/modules/contributors/contributors.module.ts @@ -2,6 +2,7 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatTooltipModule } from '@angular/material/tooltip'; import { AvatarModule } from '../avatar/avatar.module'; @@ -17,6 +18,7 @@ import { ContributorsComponent } from './contributors.component'; MatIconModule, MatTooltipModule, MatButtonModule, + MatProgressSpinnerModule, ], exports: [ ContributorsComponent, diff --git a/console/src/app/modules/warn-dialog/warn-dialog.component.html b/console/src/app/modules/warn-dialog/warn-dialog.component.html index a37542480..c089810b7 100644 --- a/console/src/app/modules/warn-dialog/warn-dialog.component.html +++ b/console/src/app/modules/warn-dialog/warn-dialog.component.html @@ -3,10 +3,10 @@

{{data.descriptionKey | translate}}

- - + diff --git a/console/src/app/modules/warn-dialog/warn-dialog.component.scss b/console/src/app/modules/warn-dialog/warn-dialog.component.scss index 1fdc5bd3c..453787bb2 100644 --- a/console/src/app/modules/warn-dialog/warn-dialog.component.scss +++ b/console/src/app/modules/warn-dialog/warn-dialog.component.scss @@ -10,12 +10,15 @@ .action { display: flex; - justify-content: flex-end; .ok-button { margin-left: 0.5rem; } + .fill-space { + flex: 1; + } + button { border-radius: 0.5rem; } diff --git a/console/src/app/pages/home/home.component.html b/console/src/app/pages/home/home.component.html index bd6745793..69e867502 100644 --- a/console/src/app/pages/home/home.component.html +++ b/console/src/app/pages/home/home.component.html @@ -1,9 +1,17 @@ -
-
- zitadel logo - - zitadel logo +
+
+ + +

+ {{'HOME.WELCOME' | translate}}, + {{user?.displayName ? user.displayName : (user.firstName + ' '+ user.lastName)}}

+

{{user?.userName}}

+ +

{{'HOME.WELCOMESENTENCE' | translate}}

+ +
@@ -77,9 +85,14 @@
+ +

{{'HOME.DISCLAIMER' | translate}} + + +

\ No newline at end of file diff --git a/console/src/app/pages/home/home.component.scss b/console/src/app/pages/home/home.component.scss index 9538a0bf5..e00099159 100644 --- a/console/src/app/pages/home/home.component.scss +++ b/console/src/app/pages/home/home.component.scss @@ -1,39 +1,25 @@ .wrapper { - width: 80%; - max-width: 1350px; - @media only screen and (max-width: 700px) { - width: 90%; - } - margin: auto; - + padding-bottom: 100px; .header { display: flex; flex-direction: column; margin: 4rem 0; - align-items: center; + align-items: center; - .avatar { - width: 100px; - height: 100px; - font-size: 100px; - line-height: 100px; - margin-top: 1rem; - } - - h1 { - font-size: 3rem; - } - p { - color: #8795a1; - text-align: center; - font-size: 1rem; - margin: 0; + h3 { + font-size: 24px; + margin-bottom: 1rem; } - img { - height: 60px; - align-self: flex-end; + .wlc_stnce { + color: #8795a1; + font-size: 16px; + } + + .avatar { + outline: none; + cursor: pointer; } } @@ -84,5 +70,11 @@ } } } - } + } + + .disclaimer { + color: #8795a1; + font-size: 14px; + margin-top: 3rem; + } } diff --git a/console/src/app/pages/home/home.component.ts b/console/src/app/pages/home/home.component.ts index 0b235ca4f..844bbe420 100644 --- a/console/src/app/pages/home/home.component.ts +++ b/console/src/app/pages/home/home.component.ts @@ -1,4 +1,5 @@ import { Component } from '@angular/core'; +import { AuthService } from 'src/app/services/auth.service'; @Component({ selector: 'app-home', @@ -7,9 +8,9 @@ import { Component } from '@angular/core'; }) export class HomeComponent { public dark: boolean = true; - - constructor() { + constructor(public authService: AuthService) { const theme = localStorage.getItem('theme'); this.dark = theme === 'dark-theme' ? true : theme === 'light-theme' ? false : true; + } } diff --git a/console/src/app/pages/home/home.module.ts b/console/src/app/pages/home/home.module.ts index 11f80d6ef..2d397bd3f 100644 --- a/console/src/app/pages/home/home.module.ts +++ b/console/src/app/pages/home/home.module.ts @@ -2,8 +2,10 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { MatButtonModule } from '@angular/material/button'; import { MatIconModule } from '@angular/material/icon'; +import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { TranslateModule } from '@ngx-translate/core'; import { HasRoleModule } from 'src/app/directives/has-role/has-role.module'; +import { AvatarModule } from 'src/app/modules/avatar/avatar.module'; import { CardModule } from 'src/app/modules/card/card.module'; import { SharedModule } from 'src/app/modules/shared/shared.module'; @@ -21,7 +23,9 @@ import { HomeComponent } from './home.component'; HomeRoutingModule, MatButtonModule, TranslateModule, + AvatarModule, SharedModule, + MatProgressSpinnerModule, CardModule, ], }) diff --git a/console/src/app/pages/iam/iam-members/iam-members-datasource.ts b/console/src/app/pages/iam/iam-members/iam-members-datasource.ts index 78029b9e1..5f5c37ac9 100644 --- a/console/src/app/pages/iam/iam-members/iam-members-datasource.ts +++ b/console/src/app/pages/iam/iam-members/iam-members-datasource.ts @@ -1,8 +1,7 @@ import { DataSource } from '@angular/cdk/collections'; import { BehaviorSubject, from, Observable, of } from 'rxjs'; import { catchError, finalize, map } from 'rxjs/operators'; -import { IamMemberSearchResponse } from 'src/app/proto/generated/admin_pb'; -import { ProjectMember } from 'src/app/proto/generated/management_pb'; +import { IamMemberView } from 'src/app/proto/generated/admin_pb'; import { AdminService } from 'src/app/services/admin.service'; /** @@ -10,9 +9,9 @@ import { AdminService } from 'src/app/services/admin.service'; * encapsulate all logic for fetching and manipulating the displayed data * (including sorting, pagination, and filtering). */ -export class IamMembersDataSource extends DataSource { +export class IamMembersDataSource extends DataSource { public totalResult: number = 0; - public membersSubject: BehaviorSubject = new BehaviorSubject([]); + public membersSubject: BehaviorSubject = new BehaviorSubject([]); private loadingSubject: BehaviorSubject = new BehaviorSubject(false); public loading$: Observable = this.loadingSubject.asObservable(); @@ -21,25 +20,21 @@ export class IamMembersDataSource extends DataSource { } public loadMembers( - pageIndex: number, pageSize: number, grantId?: string, sortDirection?: string): void { + pageIndex: number, pageSize: number): void { const offset = pageIndex * pageSize; this.loadingSubject.next(true); - // TODO - const promise: Promise = - this.adminService.SearchIamMembers(pageSize, offset); - if (promise) { - from(promise).pipe( - map(resp => { - this.totalResult = resp.toObject().totalResult; - return resp.toObject().resultList; - }), - catchError(() => of([])), - finalize(() => this.loadingSubject.next(false)), - ).subscribe(members => { - this.membersSubject.next(members); - }); - } + + from(this.adminService.SearchIamMembers(pageSize, offset)).pipe( + map(resp => { + this.totalResult = resp.toObject().totalResult; + return resp.toObject().resultList; + }), + catchError(() => of([])), + finalize(() => this.loadingSubject.next(false)), + ).subscribe(members => { + this.membersSubject.next(members); + }); } @@ -48,7 +43,7 @@ export class IamMembersDataSource extends DataSource { * the returned stream emits new items. * @returns A stream of the items to be rendered. */ - public connect(): Observable { + public connect(): Observable { return this.membersSubject.asObservable(); } diff --git a/console/src/app/pages/iam/iam-members/iam-members.component.ts b/console/src/app/pages/iam/iam-members/iam-members.component.ts index 43d1f8551..187eb732c 100644 --- a/console/src/app/pages/iam/iam-members/iam-members.component.ts +++ b/console/src/app/pages/iam/iam-members/iam-members.component.ts @@ -5,6 +5,7 @@ import { MatPaginator } from '@angular/material/paginator'; import { MatTable } from '@angular/material/table'; import { tap } from 'rxjs/operators'; import { CreationType, MemberCreateDialogComponent } from 'src/app/modules/add-member-dialog/member-create-dialog.component'; +import { IamMemberView } from 'src/app/proto/generated/admin_pb'; import { ProjectMember, ProjectType, User } from 'src/app/proto/generated/management_pb'; import { AdminService } from 'src/app/services/admin.service'; import { ToastService } from 'src/app/services/toast.service'; @@ -20,9 +21,9 @@ export class IamMembersComponent implements AfterViewInit { public projectType: ProjectType = ProjectType.PROJECTTYPE_OWNED; public disabled: boolean = false; @ViewChild(MatPaginator) public paginator!: MatPaginator; - @ViewChild(MatTable) public table!: MatTable; + @ViewChild(MatTable) public table!: MatTable; public dataSource!: IamMembersDataSource; - public selection: SelectionModel = new SelectionModel(true, []); + public selection: SelectionModel = new SelectionModel(true, []); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ public displayedColumns: string[] = ['select', 'firstname', 'lastname', 'username', 'email', 'roles']; @@ -32,7 +33,7 @@ export class IamMembersComponent implements AfterViewInit { private toast: ToastService) { this.dataSource = new IamMembersDataSource(this.adminService); - this.dataSource.loadMembers(0, 25, 'asc'); + this.dataSource.loadMembers(0, 25); } public ngAfterViewInit(): void { diff --git a/console/src/app/pages/iam/iam-views/iam-views.component.html b/console/src/app/pages/iam/iam-views/iam-views.component.html index a429cabf8..06457132c 100644 --- a/console/src/app/pages/iam/iam-views/iam-views.component.html +++ b/console/src/app/pages/iam/iam-views/iam-views.component.html @@ -41,7 +41,9 @@ {{ 'IAM.VIEWS.ACTIONS' | translate }} + (click)="cancelView(role.viewName, role.database)"> + + diff --git a/console/src/app/pages/iam/iam.component.html b/console/src/app/pages/iam/iam.component.html index 64c7c95f7..9a2a0bdd7 100644 --- a/console/src/app/pages/iam/iam.component.html +++ b/console/src/app/pages/iam/iam.component.html @@ -9,9 +9,10 @@
- +
\ No newline at end of file diff --git a/console/src/app/pages/orgs/org-detail/org-detail.component.html b/console/src/app/pages/orgs/org-detail/org-detail.component.html index e448740e6..cf4bc75d5 100644 --- a/console/src/app/pages/orgs/org-detail/org-detail.component.html +++ b/console/src/app/pages/orgs/org-detail/org-detail.component.html @@ -39,8 +39,8 @@ - diff --git a/console/src/app/pages/orgs/org-members/org-members-datasource.ts b/console/src/app/pages/orgs/org-members/org-members-datasource.ts index 8c3339ff2..c1e1a404a 100644 --- a/console/src/app/pages/orgs/org-members/org-members-datasource.ts +++ b/console/src/app/pages/orgs/org-members/org-members-datasource.ts @@ -1,17 +1,12 @@ import { DataSource } from '@angular/cdk/collections'; import { BehaviorSubject, from, Observable, of } from 'rxjs'; import { catchError, finalize, map } from 'rxjs/operators'; -import { ProjectMember, ProjectMemberSearchResponse } from 'src/app/proto/generated/management_pb'; +import { OrgMemberView } from 'src/app/proto/generated/management_pb'; import { OrgService } from 'src/app/services/org.service'; -/** - * Data source for the ProjectMembers view. This class should - * encapsulate all logic for fetching and manipulating the displayed data - * (including sorting, pagination, and filtering). - */ -export class ProjectMembersDataSource extends DataSource { +export class OrgMembersDataSource extends DataSource { public totalResult: number = 0; - public membersSubject: BehaviorSubject = new BehaviorSubject([]); + public membersSubject: BehaviorSubject = new BehaviorSubject([]); private loadingSubject: BehaviorSubject = new BehaviorSubject(false); public loading$: Observable = this.loadingSubject.asObservable(); @@ -19,26 +14,20 @@ export class ProjectMembersDataSource extends DataSource super(); } - public loadMembers( - pageIndex: number, pageSize: number, grantId?: string, sortDirection?: string): void { + public loadMembers(pageIndex: number, pageSize: number): void { const offset = pageIndex * pageSize; this.loadingSubject.next(true); - // TODO - const promise: Promise = - this.orgService.SearchMyOrgMembers(pageSize, offset); - if (promise) { - from(promise).pipe( - map(resp => { - this.totalResult = resp.toObject().totalResult; - return resp.toObject().resultList; - }), - catchError(() => of([])), - finalize(() => this.loadingSubject.next(false)), - ).subscribe(members => { - this.membersSubject.next(members); - }); - } + from(this.orgService.SearchMyOrgMembers(pageSize, offset)).pipe( + map(resp => { + this.totalResult = resp.toObject().totalResult; + return resp.toObject().resultList; + }), + catchError(() => of([])), + finalize(() => this.loadingSubject.next(false)), + ).subscribe(members => { + this.membersSubject.next(members); + }); } @@ -47,7 +36,7 @@ export class ProjectMembersDataSource extends DataSource * the returned stream emits new items. * @returns A stream of the items to be rendered. */ - public connect(): Observable { + public connect(): Observable { return this.membersSubject.asObservable(); } diff --git a/console/src/app/pages/orgs/org-members/org-members.component.ts b/console/src/app/pages/orgs/org-members/org-members.component.ts index f82024299..64cfb3b97 100644 --- a/console/src/app/pages/orgs/org-members/org-members.component.ts +++ b/console/src/app/pages/orgs/org-members/org-members.component.ts @@ -5,11 +5,11 @@ import { MatPaginator } from '@angular/material/paginator'; import { MatTable } from '@angular/material/table'; import { tap } from 'rxjs/operators'; import { CreationType, MemberCreateDialogComponent } from 'src/app/modules/add-member-dialog/member-create-dialog.component'; -import { Org, ProjectMember, ProjectType, User } from 'src/app/proto/generated/management_pb'; +import { Org, OrgMemberView, ProjectMember, ProjectType, User } from 'src/app/proto/generated/management_pb'; import { OrgService } from 'src/app/services/org.service'; import { ToastService } from 'src/app/services/toast.service'; -import { ProjectMembersDataSource } from './org-members-datasource'; +import { OrgMembersDataSource } from './org-members-datasource'; @Component({ selector: 'app-org-members', @@ -21,9 +21,9 @@ export class OrgMembersComponent implements AfterViewInit { public projectType: ProjectType = ProjectType.PROJECTTYPE_OWNED; public disabled: boolean = false; @ViewChild(MatPaginator) public paginator!: MatPaginator; - @ViewChild(MatTable) public table!: MatTable; - public dataSource!: ProjectMembersDataSource; - public selection: SelectionModel = new SelectionModel(true, []); + @ViewChild(MatTable) public table!: MatTable; + public dataSource!: OrgMembersDataSource; + public selection: SelectionModel = new SelectionModel(true, []); /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ public displayedColumns: string[] = ['select', 'firstname', 'lastname', 'username', 'email', 'roles']; @@ -33,8 +33,8 @@ export class OrgMembersComponent implements AfterViewInit { private toast: ToastService) { this.orgService.GetMyOrg().then(org => { this.org = org.toObject(); - this.dataSource = new ProjectMembersDataSource(this.orgService); - this.dataSource.loadMembers(0, 25, 'asc'); + this.dataSource = new OrgMembersDataSource(this.orgService); + this.dataSource.loadMembers(0, 25); }); } diff --git a/console/src/app/pages/projects/apps/app-create/app-create.component.html b/console/src/app/pages/projects/apps/app-create/app-create.component.html index 73560b894..176549c64 100644 --- a/console/src/app/pages/projects/apps/app-create/app-create.component.html +++ b/console/src/app/pages/projects/apps/app-create/app-create.component.html @@ -41,29 +41,13 @@ - - {{'APP.OIDC.GRANTSECTION' | translate}} - -

{{'APP.OIDC.GRANTTITLE' | translate}}

- -
- - {{'APP.OIDC.GRANT'+granttype.type | translate}} - -
-
- - -
-
- - + {{'APP.OIDC.RESPONSESECTION' | translate}}
- - {{'APP.OIDC.RESPONSE'+responsetype.key | translate}} + + {{'APP.OIDC.RESPONSE'+responsetype.type | translate}}
@@ -72,8 +56,8 @@
- +
{{'APP.OIDC.AUTHMETHODSECTION' | translate}} @@ -157,19 +141,32 @@ {{ 'APP.GRANT' | translate }} - - + + [ {{'APP.OIDC.GRANT'+element | translate}} - + {{i < oidcApp.grantTypesList.length - 1 ? ', ': ''}} + ]
{{ 'APP.OIDC.RESPONSE' | translate }} + + [ + {{('APP.OIDC.RESPONSE'+element | translate)}} + {{i < oidcApp.responseTypesList.length - 1 ? ', ': ''}} + ] + +
+ +
+ + {{ 'APP.OIDC.AUTHMETHOD' | translate }} + - - {{'APP.OIDC.RESPONSE'+element | translate}} + + {{'APP.OIDC.AUTHMETHOD'+oidcApp?.authMethodType | translate}}
@@ -178,10 +175,11 @@ {{ 'APP.OIDC.REDIRECT' | translate }} - - + + [ {{redirect}} - + {{i < oidcApp.redirectUrisList.length - 1 ? ', ': ''}} + ]
@@ -189,10 +187,11 @@ {{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }} - - + + [ {{redirect}} - + {{i < oidcApp.postLogoutRedirectUrisList.length - 1 ? ', ': ''}} + ]
diff --git a/console/src/app/pages/projects/apps/app-create/app-create.component.scss b/console/src/app/pages/projects/apps/app-create/app-create.component.scss index 35183ea07..358275439 100644 --- a/console/src/app/pages/projects/apps/app-create/app-create.component.scss +++ b/console/src/app/pages/projects/apps/app-create/app-create.component.scss @@ -14,7 +14,11 @@ p.desc { } .container { - padding: 4rem 4rem 2rem 4rem; + padding: 4rem 4rem 2rem 4rem; + + mat-progress-bar { + margin-bottom: 1rem; + } .abort-container { display: flex; diff --git a/console/src/app/pages/projects/apps/app-create/app-create.component.ts b/console/src/app/pages/projects/apps/app-create/app-create.component.ts index 048baef50..d93c5b1aa 100644 --- a/console/src/app/pages/projects/apps/app-create/app-create.component.ts +++ b/console/src/app/pages/projects/apps/app-create/app-create.component.ts @@ -32,11 +32,36 @@ export class AppCreateComponent implements OnInit, OnDestroy { public loading: boolean = false; public oidcApp: OIDCApplicationCreate.AsObject = new OIDCApplicationCreate().toObject(); - public oidcResponseTypes: { type: OIDCResponseType, checked: boolean; }[] = [ - { type: OIDCResponseType.OIDCRESPONSETYPE_CODE, checked: false }, - { type: OIDCResponseType.OIDCRESPONSETYPE_ID_TOKEN, checked: false }, - { type: OIDCResponseType.OIDCRESPONSETYPE_ID_TOKEN_TOKEN, checked: false }, + public oidcResponseTypes: { type: OIDCResponseType, checked: boolean; disabled: boolean; }[] = [ + { type: OIDCResponseType.OIDCRESPONSETYPE_CODE, checked: false, disabled: false }, + { type: OIDCResponseType.OIDCRESPONSETYPE_ID_TOKEN, checked: false, disabled: false }, + { type: OIDCResponseType.OIDCRESPONSETYPE_ID_TOKEN_TOKEN, checked: false, disabled: false }, ]; + + public oidcAppTypes: OIDCApplicationType[] = [ + OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB, + OIDCApplicationType.OIDCAPPLICATIONTYPE_USER_AGENT, + OIDCApplicationType.OIDCAPPLICATIONTYPE_NATIVE, + ]; + + public oidcAuthMethodType: { type: OIDCAuthMethodType, checked: boolean, disabled: boolean; }[] = [ + { type: OIDCAuthMethodType.OIDCAUTHMETHODTYPE_BASIC, checked: false, disabled: false }, + { type: OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE, checked: false, disabled: false }, + { type: OIDCAuthMethodType.OIDCAUTHMETHODTYPE_POST, checked: false, disabled: false }, + ]; + + // stepper + firstFormGroup!: FormGroup; + secondFormGroup!: FormGroup; + // thirdFormGroup!: FormGroup; + + // devmode + public form!: FormGroup; + + public OIDCApplicationType: any = OIDCApplicationType; + public OIDCGrantType: any = OIDCGrantType; + public OIDCAuthMethodType: any = OIDCAuthMethodType; + public oidcGrantTypes: { type: OIDCGrantType, checked: boolean, @@ -47,28 +72,6 @@ export class AppCreateComponent implements OnInit, OnDestroy { // { type: OIDCGrantType.OIDCGRANTTYPE_REFRESH_TOKEN, checked: false, disabled: true }, // TODO show when implemented ]; - public oidcAppTypes: OIDCApplicationType[] = [ - OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB, - OIDCApplicationType.OIDCAPPLICATIONTYPE_USER_AGENT, - OIDCApplicationType.OIDCAPPLICATIONTYPE_NATIVE, - ]; - public oidcAuthMethodType: { type: OIDCAuthMethodType, checked: boolean, disabled: boolean; }[] = [ - { type: OIDCAuthMethodType.OIDCAUTHMETHODTYPE_BASIC, checked: false, disabled: false }, - { type: OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE, checked: false, disabled: false }, - { type: OIDCAuthMethodType.OIDCAUTHMETHODTYPE_POST, checked: false, disabled: false }, - ]; - - // stepper - firstFormGroup!: FormGroup; - secondFormGroup!: FormGroup; - thirdFormGroup!: FormGroup; - - // devmode - public form!: FormGroup; - - public OIDCApplicationType: any = OIDCApplicationType; - public OIDCGrantType: any = OIDCGrantType; - public OIDCAuthMethodType: any = OIDCAuthMethodType; public readonly separatorKeysCodes: number[] = [ENTER, COMMA, SPACE]; @@ -92,8 +95,8 @@ export class AppCreateComponent implements OnInit, OnDestroy { this.form.valueChanges.pipe(debounceTime(300)).subscribe((value) => { this.oidcApp.name = this.formname?.value; this.oidcApp.applicationType = this.formapplicationType?.value; - this.oidcApp.grantTypesList = this.formgrantTypesList?.value; this.oidcApp.responseTypesList = this.formresponseTypesList?.value; + this.oidcApp.grantTypesList = this.formgrantTypesList?.value; this.oidcApp.authMethodType = this.formauthMethodType?.value; console.log(this.oidcApp); @@ -103,48 +106,60 @@ export class AppCreateComponent implements OnInit, OnDestroy { name: ['', [Validators.required]], applicationType: ['', [Validators.required]], }); + + this.firstFormGroup.valueChanges.subscribe(value => { + if (this.firstFormGroup.valid) { + console.log('change firstform', value); + switch (value.applicationType) { + case OIDCApplicationType.OIDCAPPLICATIONTYPE_NATIVE: + console.log('NATIVE'); + this.oidcResponseTypes[0].checked = true; + this.oidcApp.responseTypesList = [OIDCResponseType.OIDCRESPONSETYPE_CODE]; + + this.oidcApp.grantTypesList = + [OIDCGrantType.OIDCGRANTTYPE_AUTHORIZATION_CODE]; + this.oidcApp.authMethodType = OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE; + break; + case OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB: + console.log('WEB'); + + this.oidcAuthMethodType[0].disabled = false; + this.oidcAuthMethodType[1].disabled = true; // NONE DISABLED + this.oidcAuthMethodType[2].disabled = false; // POST POSSIBLE + this.authMethodType?.setValue(OIDCAuthMethodType.OIDCAUTHMETHODTYPE_BASIC); // BASIC DEFAULT + this.oidcApp.authMethodType = OIDCAuthMethodType.OIDCAUTHMETHODTYPE_BASIC; + + this.oidcResponseTypes[0].checked = true; + this.oidcApp.responseTypesList = [OIDCResponseType.OIDCRESPONSETYPE_CODE]; + this.changeResponseType(); + + this.oidcApp.grantTypesList = + [OIDCGrantType.OIDCGRANTTYPE_AUTHORIZATION_CODE]; + + break; + case OIDCApplicationType.OIDCAPPLICATIONTYPE_USER_AGENT: + console.log('USERAGENT'); + + this.oidcResponseTypes[0].checked = true; + this.oidcApp.responseTypesList = [OIDCResponseType.OIDCRESPONSETYPE_CODE]; + + this.oidcApp.grantTypesList = + [OIDCGrantType.OIDCGRANTTYPE_AUTHORIZATION_CODE, OIDCGrantType.OIDCGRANTTYPE_IMPLICIT]; + + this.oidcApp.authMethodType = OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE; + break; + } + + this.oidcApp.name = this.name?.value; + this.oidcApp.applicationType = this.applicationType?.value; + } + }); + this.secondFormGroup = this.fb.group({ authMethodType: [OIDCAuthMethodType.OIDCAUTHMETHODTYPE_BASIC, [Validators.required]], }); - - this.oidcApp.authMethodType = OIDCAuthMethodType.OIDCAUTHMETHODTYPE_BASIC; - - this.firstFormGroup.valueChanges.subscribe(value => { - if (this.applicationType?.value === OIDCApplicationType.OIDCAPPLICATIONTYPE_NATIVE) { - this.oidcResponseTypes[0].checked = true; - // this.oidcApp.responseTypesList = [this.oidcResponseTypes[0].type]; - - this.authMethodType?.setValue(OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE); - this.oidcAuthMethodType[1].disabled = true; - } - if (this.applicationType?.value === OIDCApplicationType.OIDCAPPLICATIONTYPE_WEB) { - this.oidcResponseTypes[0].checked = true; - this.oidcApp.responseTypesList = [this.oidcResponseTypes[0].type]; - - this.authMethodType?.setValue(OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE); - this.oidcAuthMethodType[0].disabled = true; - this.oidcAuthMethodType[2].disabled = true; - } - if (this.applicationType?.value === OIDCApplicationType.OIDCAPPLICATIONTYPE_USER_AGENT) { - this.oidcResponseTypes[0].checked = true; - this.oidcApp.responseTypesList = [this.oidcResponseTypes[0].type]; - - this.authMethodType?.setValue(OIDCAuthMethodType.OIDCAUTHMETHODTYPE_NONE); - this.oidcAuthMethodType[0].disabled = true; - this.oidcAuthMethodType[2].disabled = true; - - this.oidcGrantTypes[1].disabled = false; - } - - this.changeResponseType(); - this.changeGrant(); - - this.oidcApp.name = this.name?.value; - this.oidcApp.applicationType = this.applicationType?.value; - }); - this.secondFormGroup.valueChanges.subscribe(value => { - this.oidcApp.authMethodType = this.authMethodType?.value; + this.oidcApp.authMethodType = value.authMethodType; }); } @@ -226,14 +241,14 @@ export class AppCreateComponent implements OnInit, OnDestroy { } } - changeGrant(): void { - this.oidcApp.grantTypesList = this.oidcGrantTypes.filter(gt => gt.checked).map(gt => gt.type); - } - changeResponseType(): void { this.oidcApp.responseTypesList = this.oidcResponseTypes.filter(gt => gt.checked).map(gt => gt.type); } + moreThanOneOption(options: Array<{ type: OIDCGrantType, checked: boolean, disabled: boolean; }>): boolean { + return options.filter(option => option.disabled === false).length > 1; + } + get name(): AbstractControl | null { return this.firstFormGroup.get('name'); } diff --git a/console/src/app/pages/projects/apps/app-detail/app-detail.component.html b/console/src/app/pages/projects/apps/app-detail/app-detail.component.html index 2fca556ee..75f2cb7ac 100644 --- a/console/src/app/pages/projects/apps/app-detail/app-detail.component.html +++ b/console/src/app/pages/projects/apps/app-detail/app-detail.component.html @@ -86,7 +86,9 @@ {{ 'APP.OIDC.REDIRECT' | translate }} - {{redirect}} cancel @@ -100,8 +102,10 @@ {{ 'APP.OIDC.POSTLOGOUTREDIRECT' | translate }} - + {{redirect}} cancel diff --git a/console/src/app/pages/projects/apps/app-detail/app-detail.component.scss b/console/src/app/pages/projects/apps/app-detail/app-detail.component.scss index a83a7d3cb..b43da5709 100644 --- a/console/src/app/pages/projects/apps/app-detail/app-detail.component.scss +++ b/console/src/app/pages/projects/apps/app-detail/app-detail.component.scss @@ -84,4 +84,8 @@ border-radius: .5rem; margin: 0 .5rem; } + } + + mat-chip[color='green'] { + background-color: #56a392 !important; } \ No newline at end of file diff --git a/console/src/app/pages/projects/apps/app-detail/app-detail.component.ts b/console/src/app/pages/projects/apps/app-detail/app-detail.component.ts index ed8c16f2a..26d698f8f 100644 --- a/console/src/app/pages/projects/apps/app-detail/app-detail.component.ts +++ b/console/src/app/pages/projects/apps/app-detail/app-detail.component.ts @@ -35,7 +35,6 @@ enum RedirectType { }) export class AppDetailComponent implements OnInit, OnDestroy { public errorMessage: string = ''; - public selectable: boolean = false; public removable: boolean = true; public addOnBlur: boolean = true; public readonly separatorKeysCodes: number[] = [ENTER, COMMA, SPACE]; @@ -219,7 +218,7 @@ export class AppDetailComponent implements OnInit, OnDestroy { this.projectService .UpdateOIDCAppConfig(this.projectId, this.app.id, this.app.oidcConfig) - .then((data: OIDCConfig) => { + .then(() => { this.toast.showInfo('APP.TOAST.OIDCUPDATED', true); }) .catch(error => { diff --git a/console/src/app/pages/projects/apps/app-secret-dialog/app-secret-dialog.component.html b/console/src/app/pages/projects/apps/app-secret-dialog/app-secret-dialog.component.html index ea7c01dc4..b041494e1 100644 --- a/console/src/app/pages/projects/apps/app-secret-dialog/app-secret-dialog.component.html +++ b/console/src/app/pages/projects/apps/app-secret-dialog/app-secret-dialog.component.html @@ -7,7 +7,7 @@
diff --git a/console/src/app/pages/projects/apps/app-secret-dialog/app-secret-dialog.component.ts b/console/src/app/pages/projects/apps/app-secret-dialog/app-secret-dialog.component.ts index 548b68ec7..50607c6f9 100644 --- a/console/src/app/pages/projects/apps/app-secret-dialog/app-secret-dialog.component.ts +++ b/console/src/app/pages/projects/apps/app-secret-dialog/app-secret-dialog.component.ts @@ -14,22 +14,4 @@ export class AppSecretDialogComponent { public closeDialog(): void { this.dialogRef.close(false); } - - public copytoclipboard(value: string): void { - const selBox = document.createElement('textarea'); - selBox.style.position = 'fixed'; - selBox.style.left = '0'; - selBox.style.top = '0'; - selBox.style.opacity = '0'; - selBox.value = value; - document.body.appendChild(selBox); - selBox.focus(); - selBox.select(); - document.execCommand('copy'); - document.body.removeChild(selBox); - this.copied = value; - setTimeout(() => { - this.copied = ''; - }, 3000); - } } diff --git a/console/src/app/pages/projects/apps/apps.module.ts b/console/src/app/pages/projects/apps/apps.module.ts index 4bb57b3f2..9de2f4150 100644 --- a/console/src/app/pages/projects/apps/apps.module.ts +++ b/console/src/app/pages/projects/apps/apps.module.ts @@ -17,6 +17,7 @@ import { MatSelectModule } from '@angular/material/select'; import { MatStepperModule } from '@angular/material/stepper'; import { MatTooltipModule } from '@angular/material/tooltip'; import { TranslateModule } from '@ngx-translate/core'; +import { CopyToClipboardModule } from 'src/app/directives/copy-to-clipboard/copy-to-clipboard.module'; import { HasRoleModule } from 'src/app/directives/has-role/has-role.module'; import { CardModule } from 'src/app/modules/card/card.module'; @@ -55,6 +56,7 @@ import { AppsRoutingModule } from './apps-routing.module'; TranslateModule, MatStepperModule, MatRadioModule, + CopyToClipboardModule, ], exports: [TranslateModule], }) diff --git a/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.html b/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.html index d9691c251..761f51271 100644 --- a/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.html +++ b/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.html @@ -34,8 +34,8 @@ - diff --git a/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.ts b/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.ts index 2141710c8..57f660db6 100644 --- a/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.ts +++ b/console/src/app/pages/projects/granted-projects/granted-project-detail/granted-project-detail.component.ts @@ -5,7 +5,7 @@ import { MatDialog } from '@angular/material/dialog'; import { MatTableDataSource } from '@angular/material/table'; import { ActivatedRoute, Params, Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; -import { BehaviorSubject, from, of, Subscription } from 'rxjs'; +import { BehaviorSubject, from, Observable, of, Subscription } from 'rxjs'; import { catchError, finalize, map } from 'rxjs/operators'; import { CreationType, MemberCreateDialogComponent } from 'src/app/modules/add-member-dialog/member-create-dialog.component'; import { ChangeType } from 'src/app/modules/changes/changes.component'; @@ -72,7 +72,8 @@ export class GrantedProjectDetailComponent implements OnInit, OnDestroy { public totalMemberResult: number = 0; public membersSubject: BehaviorSubject = new BehaviorSubject([]); - private loadingSubject: BehaviorSubject = new BehaviorSubject(false); + private loadingSubject: BehaviorSubject = new BehaviorSubject(true); + public loading$: Observable = this.loadingSubject.asObservable(); constructor( public translate: TranslateService, 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 144f8bb39..b757fd925 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 @@ -26,7 +26,8 @@
@@ -52,7 +53,8 @@

diff --git a/console/src/app/pages/projects/owned-projects/owned-project-detail/application-grid/application-grid.component.html b/console/src/app/pages/projects/owned-projects/owned-project-detail/application-grid/application-grid.component.html index f5c9ff799..44800df12 100644 --- a/console/src/app/pages/projects/owned-projects/owned-project-detail/application-grid/application-grid.component.html +++ b/console/src/app/pages/projects/owned-projects/owned-project-detail/application-grid/application-grid.component.html @@ -6,16 +6,21 @@

+
+ +
+
-
+
{{ app.name.charAt(0)}}
{{app.name}}
+
-
+
add
{{ 'ACTIONS.NEW' | translate }} diff --git a/console/src/app/pages/projects/owned-projects/owned-project-detail/application-grid/application-grid.component.scss b/console/src/app/pages/projects/owned-projects/owned-project-detail/application-grid/application-grid.component.scss index 8d917c85e..ecfefe901 100644 --- a/console/src/app/pages/projects/owned-projects/owned-project-detail/application-grid/application-grid.component.scss +++ b/console/src/app/pages/projects/owned-projects/owned-project-detail/application-grid/application-grid.component.scss @@ -21,6 +21,14 @@ margin: 0 -1rem; padding-bottom: 2rem; + .sp-container { + display: flex; + justify-content: center; + align-items: center; + width: calc(82px + 2rem); + height: calc(82px + 2rem); + } + .app-wrap { outline: none; display: flex; @@ -40,11 +48,24 @@ margin: 1rem; border-radius: .5rem; border: 1px solid $accent-color; + font-weight: 800; background-color: $primary-dark; - transition: background-color .4s ease-in-out; + transition: background-color .2s ease-in-out; + background-image: + linear-gradient(transparent 11px, rgba($accent-color,.5) 12px, transparent 12px), + linear-gradient(90deg, transparent 11px, rgba($accent-color,.5) 12px, transparent 12px); + background-size: 100% 12px, 12px 100%; + + &:hover { + background-color: rgba($accent-color,.2); + } &.add { background: $accent-color; + + &:hover { + background-color: rgba($accent-color,.8); + } } } diff --git a/console/src/app/pages/projects/owned-projects/owned-project-detail/application-grid/application-grid.component.ts b/console/src/app/pages/projects/owned-projects/owned-project-detail/application-grid/application-grid.component.ts index 52de0ab6b..774796730 100644 --- a/console/src/app/pages/projects/owned-projects/owned-project-detail/application-grid/application-grid.component.ts +++ b/console/src/app/pages/projects/owned-projects/owned-project-detail/application-grid/application-grid.component.ts @@ -14,7 +14,7 @@ export class ApplicationGridComponent implements OnInit { @Input() public disabled: boolean = false; @Output() public changeView: EventEmitter = new EventEmitter(); public appsSubject: BehaviorSubject = new BehaviorSubject([]); - private loadingSubject: BehaviorSubject = new BehaviorSubject(false); + private loadingSubject: BehaviorSubject = new BehaviorSubject(true); public loading$: Observable = this.loadingSubject.asObservable(); constructor(private projectService: ProjectService) { } diff --git a/console/src/app/pages/projects/owned-projects/owned-project-detail/applications/applications-datasource.ts b/console/src/app/pages/projects/owned-projects/owned-project-detail/applications/applications-datasource.ts index 1ff496f8b..d92f2351b 100644 --- a/console/src/app/pages/projects/owned-projects/owned-project-detail/applications/applications-datasource.ts +++ b/console/src/app/pages/projects/owned-projects/owned-project-detail/applications/applications-datasource.ts @@ -19,7 +19,7 @@ export class ProjectApplicationsDataSource extends DataSource -
- - {{'ORG_DETAIL.TABLE.TOTAL' | translate}} - {{dataSource?.appsSubject.value.length}} - - - {{'ORG_DETAIL.TABLE.SELECTION' | translate}} - {{selection?.selected?.length}} - -
- - + + add{{ 'ACTIONS.NEW' | translate }} -
-
-
- +
+ + + + + + + + + + + + + +
+ + + + + + {{ 'PROJECT.ROLE.NAME' | translate }} + {{role.name}}
+ + +
- - - - - - - - - - - - - - -
- - - - - - {{ 'PROJECT.ROLE.NAME' | translate }} - {{role.name}}
- - - -
\ No newline at end of file + \ No newline at end of file diff --git a/console/src/app/pages/projects/owned-projects/owned-project-detail/applications/applications.component.scss b/console/src/app/pages/projects/owned-projects/owned-project-detail/applications/applications.component.scss index 779bd1fdd..4dfcdb8b0 100644 --- a/console/src/app/pages/projects/owned-projects/owned-project-detail/applications/applications.component.scss +++ b/console/src/app/pages/projects/owned-projects/owned-project-detail/applications/applications.component.scss @@ -1,73 +1,39 @@ -.table-header-row { - display: flex; - align-items: center; - - .col { - display: flex; - flex-direction: column; - .desc { - font-size: .8rem; - color: #8795a1; - } - .count { - font-size: 2rem; - } - } - - .fill-space { - flex: 1; - } - - .icon-button { - margin-right: .5rem; - } - - .add-button { - border-radius: .5rem; - } -} .table-wrapper { overflow: auto; - .spinner-container { - display: flex; - align-items: center; - justify-content: center; + table, mat-paginator { + width: 100%; + background-color: #2d2e30; + + td, th { + &:first-child { + padding-left: 0; + padding-right: 1rem; + } + + &:last-child { + padding-right: 0; + } + } + + .data-row { + cursor: pointer; + &:hover { + background-color: #ffffff05; + } + } + + .selection { + width: 50px; + max-width: 50px; + } + + .margin-neg { + margin-left: -1rem; + } } - - table, mat-paginator { - width: 100%; - background-color: #2d2e30; - - td, th { - &:first-child { - padding-left: 0; - padding-right: 1rem; - } - - &:last-child { - padding-right: 0; - } - } - - .data-row { - cursor: pointer; - &:hover { - background-color: #ffffff05; - } - } - - .selection { - width: 50px; - max-width: 50px; - } - - .margin-neg { - margin-left: -1rem; - } - } } .pointer { diff --git a/console/src/app/pages/projects/owned-projects/owned-project-detail/applications/applications.component.ts b/console/src/app/pages/projects/owned-projects/owned-project-detail/applications/applications.component.ts index bee747f5f..be0909e87 100644 --- a/console/src/app/pages/projects/owned-projects/owned-project-detail/applications/applications.component.ts +++ b/console/src/app/pages/projects/owned-projects/owned-project-detail/applications/applications.component.ts @@ -33,7 +33,7 @@ export class ApplicationsComponent implements AfterViewInit, OnInit { public ngOnInit(): void { this.dataSource = new ProjectApplicationsDataSource(this.projectService); - this.dataSource.loadApps(this.projectId, 0, 25, 'asc'); + this.dataSource.loadApps(this.projectId, 0, 25); } public ngAfterViewInit(): void { @@ -51,7 +51,6 @@ export class ApplicationsComponent implements AfterViewInit, OnInit { this.projectId, this.paginator.pageIndex, this.paginator.pageSize, - this.sort.direction, ); } @@ -66,4 +65,8 @@ export class ApplicationsComponent implements AfterViewInit, OnInit { this.selection.clear() : this.dataSource.appsSubject.value.forEach((row: Application.AsObject) => this.selection.select(row)); } + + public refreshPage(): void { + this.dataSource.loadApps(this.projectId, this.paginator.pageIndex, this.paginator.pageSize); + } } diff --git a/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.component.html b/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.component.html index be6eac0cf..52e144d7a 100644 --- a/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.component.html +++ b/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.component.html @@ -101,8 +101,8 @@ - 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 ad259d1d7..4941f2054 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 @@ -5,7 +5,7 @@ import { MatDialog } from '@angular/material/dialog'; import { MatTableDataSource } from '@angular/material/table'; import { ActivatedRoute, Params, Router } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; -import { BehaviorSubject, from, of, Subscription } from 'rxjs'; +import { BehaviorSubject, from, Observable, of, Subscription } from 'rxjs'; import { catchError, finalize, map } from 'rxjs/operators'; import { CreationType, MemberCreateDialogComponent } from 'src/app/modules/add-member-dialog/member-create-dialog.component'; import { ChangeType } from 'src/app/modules/changes/changes.component'; @@ -72,7 +72,8 @@ export class OwnedProjectDetailComponent implements OnInit, OnDestroy { public totalMemberResult: number = 0; public membersSubject: BehaviorSubject = new BehaviorSubject([]); - private loadingSubject: BehaviorSubject = new BehaviorSubject(false); + private loadingSubject: BehaviorSubject = new BehaviorSubject(true); + public loading$: Observable = this.loadingSubject.asObservable(); constructor( public translate: TranslateService, diff --git a/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.module.ts b/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.module.ts index 399c5b610..448418fb8 100644 --- a/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.module.ts +++ b/console/src/app/pages/projects/owned-projects/owned-project-detail/owned-project-detail.module.ts @@ -3,6 +3,7 @@ import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { MatButtonModule } from '@angular/material/button'; import { MatCheckboxModule } from '@angular/material/checkbox'; +import { MatRippleModule } from '@angular/material/core'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatIconModule } from '@angular/material/icon'; import { MatPaginatorModule } from '@angular/material/paginator'; @@ -56,6 +57,7 @@ import { ProjectGrantsComponent } from './project-grants/project-grants.componen MatFormFieldModule, CardModule, MatPaginatorModule, + MatRippleModule, MatCheckboxModule, MatSelectModule, MatProgressSpinnerModule, 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 bc03a7d81..bdffcb124 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 @@ -29,7 +29,8 @@
@@ -57,7 +58,8 @@
diff --git a/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-grid/owned-project-grid.component.scss b/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-grid/owned-project-grid.component.scss index 93d55018c..0fee76d78 100644 --- a/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-grid/owned-project-grid.component.scss +++ b/console/src/app/pages/projects/owned-projects/owned-project-list/owned-project-grid/owned-project-grid.component.scss @@ -133,10 +133,6 @@ margin-bottom: 0.25rem; color: #8795a1; - &:hover { - color: white; - } - &.selected { opacity: 1; } diff --git a/console/src/app/pages/projects/owned-projects/project-grant-detail/project-grant-detail.module.ts b/console/src/app/pages/projects/owned-projects/project-grant-detail/project-grant-detail.module.ts index 13a2e45ef..045d50c09 100644 --- a/console/src/app/pages/projects/owned-projects/project-grant-detail/project-grant-detail.module.ts +++ b/console/src/app/pages/projects/owned-projects/project-grant-detail/project-grant-detail.module.ts @@ -9,6 +9,7 @@ import { MatFormFieldModule } from '@angular/material/form-field'; import { MatIconModule } from '@angular/material/icon'; import { MatPaginatorModule } from '@angular/material/paginator'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; +import { MatSelectModule } from '@angular/material/select'; import { MatTableModule } from '@angular/material/table'; import { MatTooltipModule } from '@angular/material/tooltip'; import { TranslateModule } from '@ngx-translate/core'; @@ -39,6 +40,7 @@ import { ProjectGrantMembersModule } from './project-grant-members/project-grant MatProgressSpinnerModule, FormsModule, TranslateModule, + MatSelectModule, ], }) export class ProjectGrantDetailModule { } diff --git a/console/src/app/pages/users/user-create/user-create.component.html b/console/src/app/pages/users/user-create/user-create.component.html index 62e87bab4..4ab251648 100644 --- a/console/src/app/pages/users/user-create/user-create.component.html +++ b/console/src/app/pages/users/user-create/user-create.component.html @@ -13,6 +13,8 @@

{{ 'USER.CREATE.DESCRIPTION' | translate }}

+ +
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 941ded777..728f6940b 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 @@ -39,6 +39,7 @@ export class UserCreateComponent implements OnDestroy { private sub: Subscription = new Subscription(); public userLoginMustBeDomain: boolean = false; + public loading: boolean = false; constructor( private router: Router, @@ -47,12 +48,15 @@ export class UserCreateComponent implements OnDestroy { private fb: FormBuilder, private orgService: OrgService, ) { + this.loading = true; this.orgService.GetMyOrgIamPolicy().then((iampolicy) => { this.userLoginMustBeDomain = iampolicy.toObject().userLoginMustBeDomain; this.initForm(); + this.loading = false; }).catch(error => { console.error(error); this.initForm(); + this.loading = false; }); } @@ -83,13 +87,16 @@ export class UserCreateComponent implements OnDestroy { public createUser(): void { this.user = this.userForm.value; + this.loading = true; this.userService .CreateUser(this.user) .then((data: User) => { + this.loading = false; this.toast.showInfo('USER.TOAST.CREATED', true); this.router.navigate(['users', data.getId()]); }) .catch(error => { + this.loading = false; this.toast.showError(error); }); } diff --git a/console/src/app/pages/users/user-create/user-create.module.ts b/console/src/app/pages/users/user-create/user-create.module.ts index 8c5735caf..0fe9eefbd 100644 --- a/console/src/app/pages/users/user-create/user-create.module.ts +++ b/console/src/app/pages/users/user-create/user-create.module.ts @@ -6,6 +6,7 @@ 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 { MatProgressBarModule } from '@angular/material/progress-bar'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { MatSelectModule } from '@angular/material/select'; import { MatTooltipModule } from '@angular/material/tooltip'; @@ -29,6 +30,7 @@ import { UserCreateComponent } from './user-create.component'; MatButtonModule, MatIconModule, MatProgressSpinnerModule, + MatProgressBarModule, MatCheckboxModule, MatTooltipModule, TranslateModule, diff --git a/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-detail.component.html b/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-detail.component.html index d67c9b4d0..b416e88b3 100644 --- a/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-detail.component.html +++ b/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-detail.component.html @@ -13,7 +13,7 @@ {{login}} diff --git a/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-detail.component.ts b/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-detail.component.ts index 3941d2a33..00f3ff66a 100644 --- a/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-detail.component.ts +++ b/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-detail.component.ts @@ -39,9 +39,11 @@ export class AuthUserDetailComponent implements OnDestroy { private dialog: MatDialog, ) { this.loading = true; - this.getData().then(() => { + this.userService.GetMyUser().then(user => { + this.user = user.toObject(); this.loading = false; }).catch(error => { + this.toast.showError(error); this.loading = false; }); } @@ -149,30 +151,4 @@ export class AuthUserDetailComponent implements OnDestroy { this.phoneEditState = false; }); } - - private async getData(): Promise { - this.userService.GetMyUser().then(user => { - this.user = user.toObject(); - }).catch(error => { - this.toast.showError(error); - }); - } - - public copytoclipboard(value: string): void { - const selBox = document.createElement('textarea'); - selBox.style.position = 'fixed'; - selBox.style.left = '0'; - selBox.style.top = '0'; - selBox.style.opacity = '0'; - selBox.value = value; - document.body.appendChild(selBox); - selBox.focus(); - selBox.select(); - document.execCommand('copy'); - document.body.removeChild(selBox); - this.copied = value; - setTimeout(() => { - this.copied = ''; - }, 3000); - } } diff --git a/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.ts b/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.ts index e3e699394..e93ee5649 100644 --- a/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.ts +++ b/console/src/app/pages/users/user-detail/auth-user-detail/auth-user-mfa/auth-user-mfa.component.ts @@ -60,7 +60,6 @@ export class AuthUserMfaComponent implements OnInit, OnDestroy { public getOTP(): void { this.service.GetMyMfas().then(mfas => { - console.log(mfas.toObject().mfasList); this.dataSource = new MatTableDataSource(mfas.toObject().mfasList); this.dataSource.sort = this.sort; diff --git a/console/src/app/pages/users/user-detail/auth-user-detail/theme-setting/theme-card.scss b/console/src/app/pages/users/user-detail/auth-user-detail/theme-setting/theme-card.scss new file mode 100644 index 000000000..111a8caf9 --- /dev/null +++ b/console/src/app/pages/users/user-detail/auth-user-detail/theme-setting/theme-card.scss @@ -0,0 +1,11 @@ +@import '~@angular/material/theming'; + +@mixin theme-card($theme) { + $primary: map-get($theme, primary); + $primary-dark: mat-color($primary, A800); + + .theme-conent, .theme-app , .crescent { + background-color: $primary-dark; + transition: background-color .4s cubic-bezier(0.645, 0.045, 0.355, 1); + } +} diff --git a/console/src/app/pages/users/user-detail/auth-user-detail/theme-setting/theme-setting.component.scss b/console/src/app/pages/users/user-detail/auth-user-detail/theme-setting/theme-setting.component.scss index a22678728..e5f16820f 100644 --- a/console/src/app/pages/users/user-detail/auth-user-detail/theme-setting/theme-setting.component.scss +++ b/console/src/app/pages/users/user-detail/auth-user-detail/theme-setting/theme-setting.component.scss @@ -1,4 +1,5 @@ $dark-background: #2d2e30; +$light-background: #fafafa; :root { transition: none; @@ -21,6 +22,7 @@ $dark-background: #2d2e30; height: 6rem; background: linear-gradient(40deg, #FF0080,#FF8C00 70%); margin: auto; + box-shadow: 0 30px 60px rgba(0,0,0,0.12); } .crescent { @@ -29,10 +31,10 @@ $dark-background: #2d2e30; right: 0; width: 4rem; height: 4rem; - background: #fafafa; + background: $light-background; transform: scale(0); transform-origin: top right; - transition: transform .6s cubic-bezier(0.645, 0.045, 0.355, 1); + transition: transform .4s cubic-bezier(0.645, 0.045, 0.355, 1); } p { @@ -66,7 +68,7 @@ label { .toggle { position: absolute; - background-color: #fafafa; + background-color: $light-background; box-shadow: 0 2px 15px rgba(0,0,0,.15); } @@ -101,7 +103,7 @@ label { [type="checkbox"]:checked + .theme-app{ background-color: $dark-background; - color: #fafafa; + color: $light-background; } [type="checkbox"]:checked + .theme-app .crescent{ diff --git a/console/src/app/pages/users/user-detail/user-detail.module.ts b/console/src/app/pages/users/user-detail/user-detail.module.ts index 368f6f1e1..b57f841e7 100644 --- a/console/src/app/pages/users/user-detail/user-detail.module.ts +++ b/console/src/app/pages/users/user-detail/user-detail.module.ts @@ -13,6 +13,7 @@ import { MatTableModule } from '@angular/material/table'; import { MatTooltipModule } from '@angular/material/tooltip'; import { TranslateModule } from '@ngx-translate/core'; import { QRCodeModule } from 'angularx-qrcode'; +import { CopyToClipboardModule } from 'src/app/directives/copy-to-clipboard/copy-to-clipboard.module'; import { HasRoleModule } from 'src/app/directives/has-role/has-role.module'; import { CardModule } from 'src/app/modules/card/card.module'; import { ChangesModule } from 'src/app/modules/changes/changes.module'; @@ -70,6 +71,7 @@ import { UserMfaComponent } from './user-detail/user-mfa/user-mfa.component'; MatPaginatorModule, SharedModule, RefreshTableModule, + CopyToClipboardModule, ], }) export class UserDetailModule { } 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 2c7d23abd..d00162401 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 @@ -25,12 +25,13 @@ diff --git a/console/src/app/pages/users/user-detail/user-detail/user-detail.component.ts b/console/src/app/pages/users/user-detail/user-detail/user-detail.component.ts index feaa13e5f..fd6923f60 100644 --- a/console/src/app/pages/users/user-detail/user-detail/user-detail.component.ts +++ b/console/src/app/pages/users/user-detail/user-detail/user-detail.component.ts @@ -1,6 +1,6 @@ import { Location } from '@angular/common'; import { Component, OnDestroy, OnInit } from '@angular/core'; -import { ActivatedRoute, Params } from '@angular/router'; +import { ActivatedRoute } from '@angular/router'; import { TranslateService } from '@ngx-translate/core'; import { Subscription } from 'rxjs'; import { ChangeType } from 'src/app/modules/changes/changes.component'; @@ -27,7 +27,6 @@ export class UserDetailComponent implements OnInit, OnDestroy { public genders: Gender[] = [Gender.GENDER_MALE, Gender.GENDER_FEMALE, Gender.GENDER_DIVERSE]; public languages: string[] = ['de', 'en']; - public isMgmt: boolean = false; private subscription: Subscription = new Subscription(); public emailEditState: boolean = false; public phoneEditState: boolean = false; @@ -49,11 +48,11 @@ export class UserDetailComponent implements OnInit, OnDestroy { public ngOnInit(): void { this.subscription = this.route.params.subscribe(params => { - this.loading = true; - this.getData(params).then(() => { - this.loading = false; - }).catch(error => { - this.loading = false; + const { id } = params; + this.mgmtUserService.GetUserByID(id).then(user => { + this.user = user.toObject(); + }).catch(err => { + console.error(err); }); }); } @@ -157,15 +156,6 @@ export class UserDetailComponent implements OnInit, OnDestroy { this._location.back(); } - private async getData({ id }: Params): Promise { - this.isMgmt = true; - this.mgmtUserService.GetUserByID(id).then(user => { - this.user = user.toObject(); - }).catch(err => { - console.error(err); - }); - } - public sendSetPasswordNotification(): void { this.mgmtUserService.SendSetPasswordNotification(this.user.id, NotificationType.NOTIFICATIONTYPE_EMAIL) .then(() => { @@ -174,22 +164,4 @@ export class UserDetailComponent implements OnInit, OnDestroy { this.toast.showError(error); }); } - - public copytoclipboard(value: string): void { - const selBox = document.createElement('textarea'); - selBox.style.position = 'fixed'; - selBox.style.left = '0'; - selBox.style.top = '0'; - selBox.style.opacity = '0'; - selBox.value = value; - document.body.appendChild(selBox); - selBox.focus(); - selBox.select(); - document.execCommand('copy'); - document.body.removeChild(selBox); - this.copied = value; - setTimeout(() => { - this.copied = ''; - }, 3000); - } } diff --git a/console/src/app/services/toast.service.ts b/console/src/app/services/toast.service.ts index 01ecd427a..e51b4cc2f 100644 --- a/console/src/app/services/toast.service.ts +++ b/console/src/app/services/toast.service.ts @@ -1,16 +1,22 @@ import { Injectable } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; import { MatSnackBar, MatSnackBarConfig } from '@angular/material/snack-bar'; import { TranslateService } from '@ngx-translate/core'; import { Observable } from 'rxjs'; import { take } from 'rxjs/operators'; +import { WarnDialogComponent } from '../modules/warn-dialog/warn-dialog.component'; import { AuthService } from './auth.service'; @Injectable({ providedIn: 'root', }) export class ToastService { - constructor(private snackBar: MatSnackBar, private translate: TranslateService, private authService: AuthService) { } + constructor(private dialog: MatDialog, + private snackBar: MatSnackBar, + private translate: TranslateService, + private authService: AuthService, + ) { } public showInfo(message: string, i18nkey: boolean = false): void { if (i18nkey) { @@ -28,10 +34,19 @@ export class ToastService { const { message, code, metadata } = grpcError; // TODO: remove check for code === 7 if (code === 16 || (code === 7 && message === 'invalid token')) { - const actionObserver$ = this.showMessage(decodeURI(message), 'Login'); + const dialogRef = this.dialog.open(WarnDialogComponent, { + data: { + confirmKey: 'ACTIONS.LOGIN', + titleKey: 'ERRORS.TOKENINVALID.TITLE', + descriptionKey: 'ERRORS.TOKENINVALID.DESCRIPTION', + }, + width: '400px', + }); - actionObserver$.pipe(take(1)).subscribe(() => { - this.authService.authenticate(undefined, true, true); + dialogRef.afterClosed().pipe(take(1)).subscribe(resp => { + if (resp) { + this.authService.authenticate(undefined, true, true); + } }); } else { this.showMessage(decodeURI(message), 'close', { duration: 3000 }); diff --git a/console/src/assets/i18n/de.json b/console/src/assets/i18n/de.json index 0b9f39503..ea38430de 100644 --- a/console/src/assets/i18n/de.json +++ b/console/src/assets/i18n/de.json @@ -16,7 +16,11 @@ "USERS_BUTTON": "Benutzer anzeigen", "IAM": "Identity and Access Management", "IAM_DESC": "Verwalte deine Organisationen und Administratoren.", - "IAM_BUTTON": "ZITADEL verwalten" + "IAM_BUTTON": "ZITADEL verwalten", + "WELCOME":"Willkommen", + "WELCOMESENTENCE":"Hier findest du die empfohlenen Aktionen basierend auf deinen zuletzt erworbenen Berechtigungen. Beachte bitte, dass du möglicherweise deine Organisation in der Kopfzeile wechseln musst.", + "DISCLAIMER":"Du kannst nur die Einstellungen deiner aktuellen Organisation sehen, die in der Kopfzeile angegeben ist. ZITADEL behandelt deine Daten vertraulich und sicher.", + "DISCLAIMERLINK":"Mehr Informationen zur Sicherheit" }, "MENU": { "PERSONAL_INFO": "Persönliche Informationen", @@ -51,10 +55,15 @@ "CHANGE":"Ändern", "REACTIVATE":"Aktivieren", "DEACTIVATE":"Deaktivieren", - "REFRESH":"Aktualisieren" + "REFRESH":"Aktualisieren", + "LOGIN":"Login" }, "ERRORS": { - "REQUIRED": "Bitte fülle alle benötigten Felder aus!" + "REQUIRED": "Bitte fülle alle benötigten Felder aus!", + "TOKENINVALID": { + "TITLE":"Du bist abgemeldet", + "DESCRIPTION":"Klicke auf Knopf Login um dich wieder einzuloggen!" + } }, "USER": { "TITLE": "Persönliche Informationen", @@ -102,7 +111,8 @@ "NAMEANDEMAILSECTION":"Name und Email", "GENDERLANGSECTION":"Geschlecht und Sprache", "PHONESECTION":"Telefonnummer", - "PASSWORDSECTION":"Setze ein initiales Passwort." + "PASSWORDSECTION":"Setze ein initiales Passwort.", + "ADDRESSANDPHONESECTION":"Telefonnummer" }, "CODEDIALOG": { "TITLE":"Telefonnummer verifizieren", diff --git a/console/src/assets/i18n/en.json b/console/src/assets/i18n/en.json index 93ecb3a71..572bab438 100644 --- a/console/src/assets/i18n/en.json +++ b/console/src/assets/i18n/en.json @@ -16,7 +16,11 @@ "USERS_BUTTON": "Show users", "IAM": "Identity and Access Management", "IAM_DESC": "Manage your organisations and administrators.", - "IAM_BUTTON": "Manage ZITADEL" + "IAM_BUTTON": "Manage ZITADEL", + "WELCOME":"Welcome", + "WELCOMESENTENCE":"Here you can find recommended Actions based on your last acquired permissions. Note that you may have to select your organisation in the header above.", + "DISCLAIMER":"You can only see settings of your current organisation specified in the header. ZITADEL treats your data confidentially and securely.", + "DISCLAIMERLINK":"Further information" }, "MENU": { "PERSONAL_INFO": "Personal Information", @@ -51,10 +55,15 @@ "CHANGE":"Change", "REACTIVATE":"Reactivate", "DEACTIVATE":"Deactivate", - "REFRESH":"Refresh" + "REFRESH":"Refresh", + "LOGIN":"Login" }, "ERRORS": { - "REQUIRED": "Some required fields are missing!" + "REQUIRED": "Some required fields are missing!", + "TOKENINVALID": { + "TITLE":"Your auth token has expired", + "DESCRIPTION":"Click the button below to login again!" + } }, "USER": { "TITLE": "Personal Information", @@ -102,7 +111,8 @@ "NAMEANDEMAILSECTION":"Name and Email", "GENDERLANGSECTION":"Gender and Language", "PHONESECTION":"Phonenumbers", - "PASSWORDSECTION":"Set the initial Password." + "PASSWORDSECTION":"Set the initial Password.", + "ADDRESSANDPHONESECTION":"Phonenumber" }, "CODEDIALOG": { "TITLE":"Verify Phone Number", diff --git a/console/src/assets/images/zitadel-logo-oneline-lightdesign.svg b/console/src/assets/images/zitadel-logo-oneline-lightdesign.svg index 1206e2422..09f4d9a3a 100644 --- a/console/src/assets/images/zitadel-logo-oneline-lightdesign.svg +++ b/console/src/assets/images/zitadel-logo-oneline-lightdesign.svg @@ -61,29 +61,29 @@ - + - + - + - + - + - + - + - + diff --git a/console/src/assets/mdi/broom.svg b/console/src/assets/mdi/broom.svg new file mode 100644 index 000000000..1e61d7675 --- /dev/null +++ b/console/src/assets/mdi/broom.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/console/src/assets/mdi/pin-outline.svg b/console/src/assets/mdi/pin-outline.svg new file mode 100644 index 000000000..5d2799f98 --- /dev/null +++ b/console/src/assets/mdi/pin-outline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/console/src/assets/mdi/pin.svg b/console/src/assets/mdi/pin.svg new file mode 100644 index 000000000..228403698 --- /dev/null +++ b/console/src/assets/mdi/pin.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/console/src/component-themes.scss b/console/src/component-themes.scss index 0c8dbdef5..4c4b203cd 100644 --- a/console/src/component-themes.scss +++ b/console/src/component-themes.scss @@ -5,7 +5,7 @@ @import './styles/changes'; @import 'src/app/pages/projects/owned-projects/owned-project-detail/application-grid/application-grid.component'; @import './styles/meta'; -@import './styles/theme-card'; +@import 'src/app/pages/users/user-detail/auth-user-detail/theme-setting/theme-card'; @mixin component-themes($theme) { @include avatar-theme($theme); diff --git a/console/src/styles.scss b/console/src/styles.scss index 129cdab9f..c239abf66 100644 --- a/console/src/styles.scss +++ b/console/src/styles.scss @@ -154,7 +154,7 @@ $custom-typography: mat-typography-config( @include angular-material-theme($light-theme); color: #202124; - .sidenav, .main-container { + .sidenav, .main-container, .mat-dialog-container { background-color: #fafafa; transition: background-color .4s ease-in-out; } @@ -183,7 +183,7 @@ $custom-typography: mat-typography-config( @include component-themes($dark-theme); @include angular-material-theme($dark-theme); - .sidenav, .main-container { + .sidenav, .main-container, .mat-dialog-container { background-color: #212224; transition: background-color .4s ease-in-out; } diff --git a/console/src/styles/card.scss b/console/src/styles/card.scss index f0bd74e43..b698753b2 100644 --- a/console/src/styles/card.scss +++ b/console/src/styles/card.scss @@ -45,5 +45,11 @@ .iamuser { color: $primary-color; } + + .edit-button { + &:hover { + color: $border-selected-color; + } + } } } diff --git a/console/src/styles/sidenav-list.scss b/console/src/styles/sidenav-list.scss index 63308a784..2c09c690c 100644 --- a/console/src/styles/sidenav-list.scss +++ b/console/src/styles/sidenav-list.scss @@ -48,7 +48,7 @@ } .root-header { - box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.1), 0px 1px 1px 0px rgba(0, 0, 0, 0.1), 0px 1px 3px 0px rgba(0, 0, 0, 0.1); + box-shadow: 0 5px 10px rgba(0,0,0,0.12); background-color: $primary-dark !important; transition: background-color .4s ease-in-out; } @@ -56,6 +56,9 @@ .admin-line { background: $accent-color; color: white; + margin-right: 1rem; + border-top-right-radius: 50vw; + border-bottom-right-radius: 50vw; // &::after { // content: ''; diff --git a/console/src/styles/theme-card.scss b/console/src/styles/theme-card.scss deleted file mode 100644 index 1a467696e..000000000 --- a/console/src/styles/theme-card.scss +++ /dev/null @@ -1,21 +0,0 @@ -@import '~@angular/material/theming'; - -@mixin theme-card($theme) { - $primary: map-get($theme, primary); - $primary-dark: mat-color($primary, A800); - - .theme-conent { - background-color: $primary-dark; - transition: background-color .4s ease-in-out; - } - - .theme-app { - background-color: $primary-dark; - transition: background-color .4s ease-in-out; - } - - .crescent { - background-color: $primary-dark; - transition: background-color .4s ease-in-out; - } -}