mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-15 18:02:13 +00:00
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 <florian@caos.ch> * Update console/src/assets/i18n/de.json Co-authored-by: Florian Forster <florian@caos.ch> * Update console/src/assets/i18n/de.json Co-authored-by: Florian Forster <florian@caos.ch> * Update console/src/assets/i18n/de.json Co-authored-by: Florian Forster <florian@caos.ch> Co-authored-by: Florian Forster <florian@caos.ch>
This commit is contained in:
@@ -13,6 +13,8 @@
|
||||
<p class="desc">{{ 'USER.CREATE.DESCRIPTION' | translate }}</p>
|
||||
</div>
|
||||
|
||||
<mat-progress-bar *ngIf="loading" color="accent" mode="indeterminate"></mat-progress-bar>
|
||||
|
||||
<form *ngIf="userForm" [formGroup]="userForm" (ngSubmit)="createUser()" class="form">
|
||||
<!-- <h2>{{ 'USER.PAGES.CREATE' | translate}}</h2> -->
|
||||
<div class="content">
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<span>{{login}}</span>
|
||||
<button color="primary" [disabled]="copied == login"
|
||||
[matTooltip]="(copied != login ? 'USER.PAGES.COPY' : 'USER.PAGES.COPIED' ) | translate"
|
||||
(click)="copytoclipboard(login)" mat-icon-button>
|
||||
appCopyToClipboard [valueToCopy]="login" (copiedValue)="copied = $event" mat-icon-button>
|
||||
<i *ngIf="copied != login" class="las la-clipboard"></i>
|
||||
<i *ngIf="copied == login" class="las la-clipboard-check"></i>
|
||||
</button>
|
||||
|
||||
@@ -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<void> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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{
|
||||
|
||||
@@ -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 { }
|
||||
|
||||
@@ -25,12 +25,13 @@
|
||||
<app-card title="{{ 'USER.PAGES.LOGINNAMES' | translate }}"
|
||||
description="{{ 'USER.PAGES.LOGINNAMESDESC' | translate }}" *ngIf="user">
|
||||
<div class="login-name-row" *ngFor="let login of user?.loginNamesList">
|
||||
<span>{{login}}</span>
|
||||
<span>{{login}} </span>
|
||||
<button color="primary" [disabled]="copied == login"
|
||||
[matTooltip]="(copied != login ? 'USER.PAGES.COPY' : 'USER.PAGES.COPIED' ) | translate"
|
||||
(click)="copytoclipboard(login)" mat-icon-button>
|
||||
appCopyToClipboard [valueToCopy]="login" (copiedValue)="copied = $event" mat-icon-button>
|
||||
<i *ngIf="copied != login" class="las la-clipboard"></i>
|
||||
<i *ngIf="copied == login" class="las la-clipboard-check"></i>
|
||||
|
||||
</button>
|
||||
</div>
|
||||
</app-card>
|
||||
|
||||
@@ -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<void> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user