Change the admin rename UX

Change the rename operation from double click icon to click button
This commit is contained in:
Deng, Qian 2018-04-25 13:44:23 +08:00
parent bf6192f32b
commit e1814597d8
9 changed files with 304 additions and 220 deletions

View File

@ -7,15 +7,18 @@
<div class="form-group form-group-override"> <div class="form-group form-group-override">
<label for="account_settings_username" aria-haspopup="true" class="form-group-label-override">{{'PROFILE.USER_NAME' | translate}}</label> <label for="account_settings_username" aria-haspopup="true" class="form-group-label-override">{{'PROFILE.USER_NAME' | translate}}</label>
<input type="text" name="account_settings_username" [(ngModel)]="account.username" disabled id="account_settings_username" size="33"> <input type="text" name="account_settings_username" [(ngModel)]="account.username" disabled id="account_settings_username" size="33">
<clr-tooltip *ngIf="canRename"> <div *ngIf="canRename" class="rename-tool">
<button (dblclick)="openRenameAlert()" class="btn btn-link"> <button [disabled]="RenameOnGoing" (click)="onRename()" class="btn btn-outline btn-sm">
<clr-icon clrTooltipTrigger shape="info-circle" size="24"></clr-icon> {{'PROFILE.ADMIN_RENAME_BUTTON' | translate}}
</button> </button>
<clr-tooltip>
<clr-icon clrTooltipTrigger shape="info-circle" size="24"></clr-icon>
<clr-tooltip-content clrPosition="bottom-left" clrSize="md" *clrIfOpen> <clr-tooltip-content clrPosition="bottom-left" clrSize="md" *clrIfOpen>
<span (click)="openRenameAlert()"> {{'PROFILE.ADMIN_RENAME_TIP' | translate}}</span> <span> {{'PROFILE.ADMIN_RENAME_TIP' | translate}}</span>
</clr-tooltip-content> </clr-tooltip-content>
</clr-tooltip> </clr-tooltip>
</div> </div>
</div>
<div class="form-group form-group-override"> <div class="form-group form-group-override">
<label for="account_settings_email" class="required form-group-label-override">{{'PROFILE.EMAIL' | translate}}</label> <label for="account_settings_email" class="required form-group-label-override">{{'PROFILE.EMAIL' | translate}}</label>
<label for="account_settings_email" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-top-left" [class.invalid]='!getValidationState("account_settings_email")'> <label for="account_settings_email" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-top-left" [class.invalid]='!getValidationState("account_settings_email")'>

View File

@ -0,0 +1,14 @@
clr-modal {
::ng-deep div.modal-dialog {
width: unset;
}
.rename-tool {
.btn {
margin-right: 6px;
padding-left: 3px;
padding-right: 3px;
}
position: relative;
bottom: 9px;
}
}

View File

@ -1,3 +1,4 @@
import { ChangeDetectorRef } from '@angular/core';
// Copyright (c) 2017 VMware, Inc. All Rights Reserved. // Copyright (c) 2017 VMware, Inc. All Rights Reserved.
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
@ -27,40 +28,60 @@ import { CommonRoutes } from "../../shared/shared.const";
templateUrl: "account-settings-modal.component.html", templateUrl: "account-settings-modal.component.html",
styleUrls: ["./account-settings-modal.component.scss", "../../common.scss"] styleUrls: ["./account-settings-modal.component.scss", "../../common.scss"]
}) })
export class AccountSettingsModalComponent implements OnInit, AfterViewChecked { export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
opened = false; opened = false;
staticBackdrop = true; staticBackdrop = true;
originalStaticData: SessionUser;
account: SessionUser; account: SessionUser;
error: any = null; error: any = null;
originalStaticData: SessionUser;
emailTooltip = "TOOLTIP.EMAIL"; emailTooltip = "TOOLTIP.EMAIL";
mailAlreadyChecked = {}; mailAlreadyChecked = {};
isOnCalling = false; isOnCalling = false;
formValueChanged = false; formValueChanged = false;
checkOnGoing = false; checkOnGoing = false;
RenameOnGoing = false; RenameOnGoing = false;
originAdminName = "admin";
newAdminName = "admin@harbor.local";
renameConfirmation = false;
// confirmRename = false;
accountFormRef: NgForm; accountFormRef: NgForm;
@ViewChild("accountSettingsFrom") accountForm: NgForm; @ViewChild("accountSettingsFrom") accountForm: NgForm;
@ViewChild(InlineAlertComponent) @ViewChild(InlineAlertComponent) inlineAlert: InlineAlertComponent;
inlineAlert: InlineAlertComponent;
constructor( constructor(
private session: SessionService, private session: SessionService,
private msgHandler: MessageHandlerService, private msgHandler: MessageHandlerService,
private router: Router, private router: Router,
private searchTrigger: SearchTriggerService private searchTrigger: SearchTriggerService,
private ref: ChangeDetectorRef
) {} ) {}
private validationStateMap: any = { private validationStateMap: any = {
"account_settings_email": true, account_settings_email: true,
"account_settings_full_name": true account_settings_full_name: true
}; };
ngOnInit(): void { ngOnInit(): void {
// Value copy // Value copy
this.account = Object.assign({}, this.session.getCurrentUser()); this.account = Object.assign({}, this.session.getCurrentUser());
this.originalStaticData = Object.assign({}, this.session.getCurrentUser());
}
ngAfterViewChecked(): void {
if (this.accountFormRef !== this.accountForm) {
this.accountFormRef = this.accountForm;
if (this.accountFormRef) {
this.accountFormRef.valueChanges.subscribe(data => {
if (this.error) {
this.error = null;
}
this.formValueChanged = true;
if (this.account.username === this.originAdminName) {
this.inlineAlert.close();
}
});
}
}
} }
getValidationState(key: string): boolean { getValidationState(key: string): boolean {
@ -75,9 +96,14 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
this.validationStateMap[key] = cont.valid; this.validationStateMap[key] = cont.valid;
// Check email existing from backend // Check email existing from backend
if (cont.valid && key === "account_settings_email") { if (cont.valid && key === "account_settings_email") {
if (this.formValueChanged && this.account.email !== this.originalStaticData.email) { if (
this.formValueChanged &&
this.account.email !== this.originalStaticData.email
) {
if (this.mailAlreadyChecked[this.account.email]) { if (this.mailAlreadyChecked[this.account.email]) {
this.validationStateMap[key] = !this.mailAlreadyChecked[this.account.email].result; this.validationStateMap[key] = !this.mailAlreadyChecked[
this.account.email
].result;
if (!this.validationStateMap[key]) { if (!this.validationStateMap[key]) {
this.emailTooltip = "TOOLTIP.EMAIL_EXISTING"; this.emailTooltip = "TOOLTIP.EMAIL_EXISTING";
} }
@ -86,7 +112,8 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
// Mail changed // Mail changed
this.checkOnGoing = true; this.checkOnGoing = true;
this.session.checkUserExisting("email", this.account.email) this.session
.checkUserExisting("email", this.account.email)
.then((res: boolean) => { .then((res: boolean) => {
this.checkOnGoing = false; this.checkOnGoing = false;
this.validationStateMap[key] = !res; this.validationStateMap[key] = !res;
@ -115,21 +142,21 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
if (!this.originalStaticData || !this.account) { if (!this.originalStaticData || !this.account) {
return false; return false;
} }
for (let prop in this.originalStaticData) { for (let prop in this.originalStaticData) {
if (this.originalStaticData[prop] !== this.account[prop]) { if (this.originalStaticData[prop] !== this.account[prop]) {
return true; return true;
} }
} }
return false; return false;
} }
public get isValid(): boolean { public get isValid(): boolean {
return this.accountForm && return (
this.accountForm &&
this.accountForm.valid && this.accountForm.valid &&
this.error === null && this.error === null &&
this.validationStateMap["account_settings_email"]; // backend check is valid as well this.validationStateMap["account_settings_email"]
); // backend check is valid as well
} }
public get showProgress(): boolean { public get showProgress(): boolean {
@ -141,49 +168,53 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
} }
public get canRename(): boolean { public get canRename(): boolean {
return this.account && this.account.has_admin_role && this.account.username === "admin" && this.account.user_id === 1; return (
this.account &&
this.account.has_admin_role &&
this.originalStaticData.username === "admin" &&
this.account.user_id === 1
);
} }
openRenameAlert(): void { onRename(): void {
this.account.username = this.newAdminName;
this.RenameOnGoing = true; this.RenameOnGoing = true;
this.inlineAlert.showInlineConfirmation({
message: "PROFILE.RENAME_CONFIRM_INFO"
});
} }
confirmRename(): void { confirmRename(): void {
if (this.canRename) { if (this.canRename) {
this.session
.updateAccountSettings(this.account)
.then(() => {
this.session.renameAdmin(this.account) this.session.renameAdmin(this.account)
.then(() => { .then(() => {
this.msgHandler.showSuccess("PROFILE.RENAME_SUCCESS"); this.msgHandler.showSuccess("PROFILE.RENAME_SUCCESS");
this.opened = false;
this.logOut();
}) })
.catch(error => { .catch(error => {
this.msgHandler.handleError(error); this.msgHandler.handleError(error);
}); });
})
.catch(error => {
this.isOnCalling = false;
this.error = error;
if (this.msgHandler.isAppLevel(error)) {
this.opened = false;
this.msgHandler.handleError(error);
} else {
this.inlineAlert.showInlineError(error);
} }
}
ngAfterViewChecked(): void {
if (this.accountFormRef !== this.accountForm) {
this.accountFormRef = this.accountForm;
if (this.accountFormRef) {
this.accountFormRef.valueChanges.subscribe(data => {
if (this.error) {
this.error = null;
}
this.formValueChanged = true;
this.inlineAlert.close();
}); });
} }
} }
}
// Log out system // Log out system
logOut(): void { logOut(): void {
// Naviagte to the sign in route // Naviagte to the sign in route
// Appending 'signout' means destroy session cache // Appending 'signout' means destroy session cache
let navigatorExtra: NavigationExtras = { let navigatorExtra: NavigationExtras = {
queryParams: { "signout": true } queryParams: { signout: true }
}; };
this.router.navigate([CommonRoutes.EMBEDDED_SIGN_IN], navigatorExtra); this.router.navigate([CommonRoutes.EMBEDDED_SIGN_IN], navigatorExtra);
// Confirm search result panel is close // Confirm search result panel is close
@ -204,26 +235,28 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
// Reset validation status // Reset validation status
this.validationStateMap = { this.validationStateMap = {
"account_settings_email": true, account_settings_email: true,
"account_settings_full_name": true account_settings_full_name: true
}; };
this.opened = true; this.opened = true;
} }
close() { close() {
if (this.RenameOnGoing) {
this.RenameOnGoing = false;
}
if (this.formValueChanged) { if (this.formValueChanged) {
if (!this.isUserDataChange()) { if (!this.isUserDataChange()) {
this.opened = false; this.opened = false;
} else {
if (this.RenameOnGoing) {
this.RenameOnGoing = false;
this.opened = false;
} else { } else {
// Need user confirmation // Need user confirmation
this.inlineAlert.showInlineConfirmation({ this.inlineAlert.showInlineConfirmation({
message: "ALERT.FORM_CHANGE_CONFIRMATION" message: "ALERT.FORM_CHANGE_CONFIRMATION"
}); });
} }
}
} else { } else {
this.opened = false; this.opened = false;
} }
@ -240,9 +273,21 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
return; return;
} }
if (this.RenameOnGoing && !this.renameConfirmation) {
this.renameConfirmation = true;
this.inlineAlert.showInlineWarning({
message: "PROFILE.RENAME_CONFIRM_INFO"
});
return;
}
this.isOnCalling = true; this.isOnCalling = true;
this.session.updateAccountSettings(this.account) if (this.RenameOnGoing && this.renameConfirmation) {
this.confirmRename();
} else {
this.session
.updateAccountSettings(this.account)
.then(() => { .then(() => {
this.isOnCalling = false; this.isOnCalling = false;
this.opened = false; this.opened = false;
@ -259,17 +304,22 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
} }
}); });
} }
}
confirmNo($event: any): void { confirmNo($event: any): void {
if (this.RenameOnGoing) { if (this.RenameOnGoing) {
this.RenameOnGoing = false; this.RenameOnGoing = false;
} }
if (this.renameConfirmation) {
this.renameConfirmation = false;
}
} }
confirmYes($event: any): void { confirmYes($event: any): void {
if (this.RenameOnGoing) { if (this.RenameOnGoing) {
this.confirmRename();
this.RenameOnGoing = false; this.RenameOnGoing = false;
this.logOut(); }
if (this.renameConfirmation) {
this.renameConfirmation = false;
} }
this.inlineAlert.close(); this.inlineAlert.close();
this.opened = false; this.opened = false;

View File

@ -69,6 +69,19 @@ export class InlineAlertComponent {
this.useAppLevelStyle = false; this.useAppLevelStyle = false;
} }
// Show warning
public showInlineWarning(warning: any): void {
this.displayedText = "";
if (warning && warning.message) {
this.translate.get(warning.message).subscribe((res: string) => this.displayedText = res);
}
this.inlineAlertType = 'alert-warning';
this.showCancelAction = false;
this.inlineAlertClosable = true;
this.alertClose = false;
this.useAppLevelStyle = false;
}
// Show inline sccess info // Show inline sccess info
public showInlineSuccess(info: any): void { public showInlineSuccess(info: any): void {
this.displayedText = ""; this.displayedText = "";

View File

@ -83,9 +83,10 @@
"COMMENT": "Comments", "COMMENT": "Comments",
"PASSWORD": "Password", "PASSWORD": "Password",
"SAVE_SUCCESS": "User profile saved successfully.", "SAVE_SUCCESS": "User profile saved successfully.",
"ADMIN_RENAME_TIP": "Double click to change your username to \"admin@harbor.local\", but this action can NOT redo.", "ADMIN_RENAME_BUTTON": "Change username",
"ADMIN_RENAME_TIP": "Select the button in order to change the username to \"admin@harbor.local\". This operation can not be undone.",
"RENAME_SUCCESS": "Rename success!", "RENAME_SUCCESS": "Rename success!",
"RENAME_CONFIRM_INFO": "This action can not undo, Confirm To Rename?" "RENAME_CONFIRM_INFO": "Warning, changing the name to admin@harbor.local can not be undone."
}, },
"CHANGE_PWD": { "CHANGE_PWD": {
"TITLE": "Change Password", "TITLE": "Change Password",

View File

@ -83,9 +83,9 @@
"COMMENT": "Comentarios", "COMMENT": "Comentarios",
"PASSWORD": "Contraseña", "PASSWORD": "Contraseña",
"SAVE_SUCCESS": "Perfil de usuario guardado satisfactoriamente.", "SAVE_SUCCESS": "Perfil de usuario guardado satisfactoriamente.",
"ADMIN_RENAME_TIP": "Double click to change your username to \"admin@harbor.local\", but this action can NOT redo.", "ADMIN_RENAME_TIP": "Select the button in order to change the username to \"admin@harbor.local\". This operation can not be undone.",
"RENAME_SUCCESS": "Rename success!", "RENAME_SUCCESS": "Rename success!",
"RENAME_CONFIRM_INFO": "This action can not undo, Confirm To Rename?" "RENAME_CONFIRM_INFO": "Warning, changing the name to admin@harbor.local can not be undone."
}, },
"CHANGE_PWD": { "CHANGE_PWD": {
"TITLE": "Cambiar contraseña", "TITLE": "Cambiar contraseña",

View File

@ -69,7 +69,10 @@
"FULL_NAME": "Prénom et nom", "FULL_NAME": "Prénom et nom",
"COMMENT": "Commentaires", "COMMENT": "Commentaires",
"PASSWORD": "Mot de passe", "PASSWORD": "Mot de passe",
"SAVE_SUCCESS": "Profil utilisateur sauvegardé avec succès." "SAVE_SUCCESS": "Profil utilisateur sauvegardé avec succès.",
"ADMIN_RENAME_TIP": "Select the button in order to change the username to \"admin@harbor.local\". This operation can not be undone.",
"RENAME_SUCCESS": "Rename success!",
"RENAME_CONFIRM_INFO": "Warning, changing the name to admin@harbor.local can not be undone."
}, },
"CHANGE_PWD": { "CHANGE_PWD": {
"TITLE": "Modifier le mot de passe", "TITLE": "Modifier le mot de passe",

View File

@ -83,9 +83,9 @@
"COMMENT": "注释", "COMMENT": "注释",
"PASSWORD": "密码", "PASSWORD": "密码",
"SAVE_SUCCESS": "成功保存用户设置。", "SAVE_SUCCESS": "成功保存用户设置。",
"ADMIN_RENAME_TIP": "双击将用户名改为 \"admin@harbor.local\", 注意这个操作是不可逆的", "ADMIN_RENAME_TIP": "单击将用户名改为 \"admin@harbor.local\", 注意这个操作是无法撤销的",
"RENAME_SUCCESS": "用户名更改成功!", "RENAME_SUCCESS": "用户名更改成功!",
"RENAME_CONFIRM_INFO": "更改用户名无法撤销, 你确定更改吗·?" "RENAME_CONFIRM_INFO": "更改用户名为admin@harbor.local是无法撤销, 你确定更改吗·?"
}, },
"CHANGE_PWD": { "CHANGE_PWD": {
"TITLE": "修改密码", "TITLE": "修改密码",