diff --git a/src/ui_ng/lib/package.json b/src/ui_ng/lib/package.json index 3017d468e..f779fd0d5 100644 --- a/src/ui_ng/lib/package.json +++ b/src/ui_ng/lib/package.json @@ -43,4 +43,4 @@ "web-animations-js": "^2.2.1", "zone.js": "^0.8.4" } -} +} \ No newline at end of file diff --git a/src/ui_ng/src/app/account/account-settings/account-settings-modal.component.html b/src/ui_ng/src/app/account/account-settings/account-settings-modal.component.html index 4da5773fa..7031269a7 100644 --- a/src/ui_ng/src/app/account/account-settings/account-settings-modal.component.html +++ b/src/ui_ng/src/app/account/account-settings/account-settings-modal.component.html @@ -7,14 +7,17 @@
- - - - {{'PROFILE.ADMIN_RENAME_TIP' | translate}} - - + + + + {{'PROFILE.ADMIN_RENAME_TIP' | translate}} + + +
diff --git a/src/ui_ng/src/app/account/account-settings/account-settings-modal.component.scss b/src/ui_ng/src/app/account/account-settings/account-settings-modal.component.scss index e69de29bb..ff10745a9 100644 --- a/src/ui_ng/src/app/account/account-settings/account-settings-modal.component.scss +++ b/src/ui_ng/src/app/account/account-settings/account-settings-modal.component.scss @@ -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; + } +} \ No newline at end of file diff --git a/src/ui_ng/src/app/account/account-settings/account-settings-modal.component.ts b/src/ui_ng/src/app/account/account-settings/account-settings-modal.component.ts index 4f2d46fe4..34752b1a0 100644 --- a/src/ui_ng/src/app/account/account-settings/account-settings-modal.component.ts +++ b/src/ui_ng/src/app/account/account-settings/account-settings-modal.component.ts @@ -1,3 +1,4 @@ +import { ChangeDetectorRef } from '@angular/core'; // Copyright (c) 2017 VMware, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,206 +24,238 @@ import { SearchTriggerService } from "../../base/global-search/search-trigger.se import { CommonRoutes } from "../../shared/shared.const"; @Component({ - selector: "account-settings-modal", - templateUrl: "account-settings-modal.component.html", - styleUrls: ["./account-settings-modal.component.scss", "../../common.scss"] + selector: "account-settings-modal", + templateUrl: "account-settings-modal.component.html", + styleUrls: ["./account-settings-modal.component.scss", "../../common.scss"] }) - export class AccountSettingsModalComponent implements OnInit, AfterViewChecked { - opened = false; - staticBackdrop = true; - account: SessionUser; - error: any = null; - originalStaticData: SessionUser; - emailTooltip = "TOOLTIP.EMAIL"; - mailAlreadyChecked = {}; - isOnCalling = false; - formValueChanged = false; - checkOnGoing = false; - RenameOnGoing = false; + opened = false; + staticBackdrop = true; + originalStaticData: SessionUser; + account: SessionUser; + error: any = null; + emailTooltip = "TOOLTIP.EMAIL"; + mailAlreadyChecked = {}; + isOnCalling = false; + formValueChanged = false; + checkOnGoing = false; + RenameOnGoing = false; + originAdminName = "admin"; + newAdminName = "admin@harbor.local"; + renameConfirmation = false; +// confirmRename = false; - accountFormRef: NgForm; - @ViewChild("accountSettingsFrom") accountForm: NgForm; - @ViewChild(InlineAlertComponent) - inlineAlert: InlineAlertComponent; + accountFormRef: NgForm; + @ViewChild("accountSettingsFrom") accountForm: NgForm; + @ViewChild(InlineAlertComponent) inlineAlert: InlineAlertComponent; - constructor( - private session: SessionService, - private msgHandler: MessageHandlerService, - private router: Router, - private searchTrigger: SearchTriggerService - ) { } + constructor( + private session: SessionService, + private msgHandler: MessageHandlerService, + private router: Router, + private searchTrigger: SearchTriggerService, + private ref: ChangeDetectorRef + ) {} + private validationStateMap: any = { + account_settings_email: true, + account_settings_full_name: true + }; + ngOnInit(): void { + // Value copy + this.account = Object.assign({}, this.session.getCurrentUser()); + this.originalStaticData = Object.assign({}, this.session.getCurrentUser()); + } - private validationStateMap: any = { - "account_settings_email": true, - "account_settings_full_name": true - }; - ngOnInit(): void { - // Value copy - this.account = Object.assign({}, this.session.getCurrentUser()); - } - - getValidationState(key: string): boolean { - return this.validationStateMap[key]; - } - - handleValidation(key: string, flag: boolean): void { - if (flag) { - // Checking - let cont = this.accountForm.controls[key]; - if (cont) { - this.validationStateMap[key] = cont.valid; - // Check email existing from backend - if (cont.valid && key === "account_settings_email") { - if (this.formValueChanged && this.account.email !== this.originalStaticData.email) { - if (this.mailAlreadyChecked[this.account.email]) { - this.validationStateMap[key] = !this.mailAlreadyChecked[this.account.email].result; - if (!this.validationStateMap[key]) { - this.emailTooltip = "TOOLTIP.EMAIL_EXISTING"; - } - return; - } - - // Mail changed - this.checkOnGoing = true; - this.session.checkUserExisting("email", this.account.email) - .then((res: boolean) => { - this.checkOnGoing = false; - this.validationStateMap[key] = !res; - if (res) { - this.emailTooltip = "TOOLTIP.EMAIL_EXISTING"; - } - this.mailAlreadyChecked[this.account.email] = { - result: res - }; // Tag it checked - }) - .catch(error => { - this.checkOnGoing = false; - this.validationStateMap[key] = false; // Not valid @ backend - }); - } - } - } - } else { - // Reset - this.validationStateMap[key] = true; - this.emailTooltip = "TOOLTIP.EMAIL"; - } - } - - isUserDataChange(): boolean { - if (!this.originalStaticData || !this.account) { - return false; - } - - for (let prop in this.originalStaticData) { - if (this.originalStaticData[prop] !== this.account[prop]) { - return true; - } - } - - return false; - } - - public get isValid(): boolean { - return this.accountForm && - this.accountForm.valid && - this.error === null && - this.validationStateMap["account_settings_email"]; // backend check is valid as well - } - - public get showProgress(): boolean { - return this.isOnCalling; - } - - public get checkProgress(): boolean { - return this.checkOnGoing; - } - - public get canRename(): boolean { - return this.account && this.account.has_admin_role && this.account.username === "admin" && this.account.user_id === 1; - } - - openRenameAlert(): void { - this.RenameOnGoing = true; - this.inlineAlert.showInlineConfirmation({ - message: "PROFILE.RENAME_CONFIRM_INFO" + 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(); + } }); + } } + } - confirmRename(): void { - if (this.canRename) { - this.session.renameAdmin(this.account) - .then(() => { - this.msgHandler.showSuccess("PROFILE.RENAME_SUCCESS"); - }) - .catch(error => { - this.msgHandler.handleError(error); - }); - } - } + getValidationState(key: string): boolean { + return this.validationStateMap[key]; + } - 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(); - }); + handleValidation(key: string, flag: boolean): void { + if (flag) { + // Checking + let cont = this.accountForm.controls[key]; + if (cont) { + this.validationStateMap[key] = cont.valid; + // Check email existing from backend + if (cont.valid && key === "account_settings_email") { + if ( + this.formValueChanged && + this.account.email !== this.originalStaticData.email + ) { + if (this.mailAlreadyChecked[this.account.email]) { + this.validationStateMap[key] = !this.mailAlreadyChecked[ + this.account.email + ].result; + if (!this.validationStateMap[key]) { + this.emailTooltip = "TOOLTIP.EMAIL_EXISTING"; + } + return; } + + // Mail changed + this.checkOnGoing = true; + this.session + .checkUserExisting("email", this.account.email) + .then((res: boolean) => { + this.checkOnGoing = false; + this.validationStateMap[key] = !res; + if (res) { + this.emailTooltip = "TOOLTIP.EMAIL_EXISTING"; + } + this.mailAlreadyChecked[this.account.email] = { + result: res + }; // Tag it checked + }) + .catch(error => { + this.checkOnGoing = false; + this.validationStateMap[key] = false; // Not valid @ backend + }); + } } + } + } else { + // Reset + this.validationStateMap[key] = true; + this.emailTooltip = "TOOLTIP.EMAIL"; } + } - // Log out system - logOut(): void { - // Naviagte to the sign in route - // Appending 'signout' means destroy session cache - let navigatorExtra: NavigationExtras = { - queryParams: { "signout": true } - }; - this.router.navigate([CommonRoutes.EMBEDDED_SIGN_IN], navigatorExtra); - // Confirm search result panel is close - this.searchTrigger.closeSearch(true); + isUserDataChange(): boolean { + if (!this.originalStaticData || !this.account) { + return false; } - - open() { - // Keep the initial data for future diff - this.originalStaticData = Object.assign({}, this.session.getCurrentUser()); - this.account = Object.assign({}, this.session.getCurrentUser()); - this.formValueChanged = false; - - // Confirm inline alert is closed - this.inlineAlert.close(); - - // Clear check history - this.mailAlreadyChecked = {}; - - // Reset validation status - this.validationStateMap = { - "account_settings_email": true, - "account_settings_full_name": true - }; - - this.opened = true; + for (let prop in this.originalStaticData) { + if (this.originalStaticData[prop] !== this.account[prop]) { + return true; + } } + return false; + } + + public get isValid(): boolean { + return ( + this.accountForm && + this.accountForm.valid && + this.error === null && + this.validationStateMap["account_settings_email"] + ); // backend check is valid as well + } + + public get showProgress(): boolean { + return this.isOnCalling; + } + + public get checkProgress(): boolean { + return this.checkOnGoing; + } + + public get canRename(): boolean { + return ( + this.account && + this.account.has_admin_role && + this.originalStaticData.username === "admin" && + this.account.user_id === 1 + ); + } + + onRename(): void { + this.account.username = this.newAdminName; + this.RenameOnGoing = true; + } + + confirmRename(): void { + if (this.canRename) { + this.session + .updateAccountSettings(this.account) + .then(() => { + this.session.renameAdmin(this.account) + .then(() => { + this.msgHandler.showSuccess("PROFILE.RENAME_SUCCESS"); + this.opened = false; + this.logOut(); + }) + .catch(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); + } + }); + } + } + + // Log out system + logOut(): void { + // Naviagte to the sign in route + // Appending 'signout' means destroy session cache + let navigatorExtra: NavigationExtras = { + queryParams: { signout: true } + }; + this.router.navigate([CommonRoutes.EMBEDDED_SIGN_IN], navigatorExtra); + // Confirm search result panel is close + this.searchTrigger.closeSearch(true); + } + + open() { + // Keep the initial data for future diff + this.originalStaticData = Object.assign({}, this.session.getCurrentUser()); + this.account = Object.assign({}, this.session.getCurrentUser()); + this.formValueChanged = false; + + // Confirm inline alert is closed + this.inlineAlert.close(); + + // Clear check history + this.mailAlreadyChecked = {}; + + // Reset validation status + this.validationStateMap = { + account_settings_email: true, + account_settings_full_name: true + }; + + this.opened = true; + } close() { - if (this.RenameOnGoing) { - this.RenameOnGoing = false; - } if (this.formValueChanged) { if (!this.isUserDataChange()) { this.opened = false; } else { - // Need user confirmation - this.inlineAlert.showInlineConfirmation({ - message: "ALERT.FORM_CHANGE_CONFIRMATION" - }); + if (this.RenameOnGoing) { + this.RenameOnGoing = false; + this.opened = false; + } else { + // Need user confirmation + this.inlineAlert.showInlineConfirmation({ + message: "ALERT.FORM_CHANGE_CONFIRMATION" + }); + } } } else { this.opened = false; @@ -240,38 +273,55 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked { return; } + if (this.RenameOnGoing && !this.renameConfirmation) { + this.renameConfirmation = true; + this.inlineAlert.showInlineWarning({ + message: "PROFILE.RENAME_CONFIRM_INFO" + }); + return; + } + this.isOnCalling = true; - this.session.updateAccountSettings(this.account) - .then(() => { - this.isOnCalling = false; - this.opened = false; - this.msgHandler.showSuccess("PROFILE.SAVE_SUCCESS"); - }) - .catch(error => { - this.isOnCalling = false; - this.error = error; - if (this.msgHandler.isAppLevel(error)) { + if (this.RenameOnGoing && this.renameConfirmation) { + this.confirmRename(); + } else { + this.session + .updateAccountSettings(this.account) + .then(() => { + this.isOnCalling = false; this.opened = false; - this.msgHandler.handleError(error); - } else { - this.inlineAlert.showInlineError(error); - } - }); + this.msgHandler.showSuccess("PROFILE.SAVE_SUCCESS"); + }) + .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); + } + }); + } } - confirmNo($event: any): void { - if (this.RenameOnGoing) { - this.RenameOnGoing = false; - } + confirmNo($event: any): void { + if (this.RenameOnGoing) { + this.RenameOnGoing = false; } - confirmYes($event: any): void { - if (this.RenameOnGoing) { - this.confirmRename(); - this.RenameOnGoing = false; - this.logOut(); - } - this.inlineAlert.close(); - this.opened = false; + if (this.renameConfirmation) { + this.renameConfirmation = false; } + } + confirmYes($event: any): void { + if (this.RenameOnGoing) { + this.RenameOnGoing = false; + } + if (this.renameConfirmation) { + this.renameConfirmation = false; + } + this.inlineAlert.close(); + this.opened = false; + } } diff --git a/src/ui_ng/src/app/shared/inline-alert/inline-alert.component.ts b/src/ui_ng/src/app/shared/inline-alert/inline-alert.component.ts index a96f717b1..7576f170a 100644 --- a/src/ui_ng/src/app/shared/inline-alert/inline-alert.component.ts +++ b/src/ui_ng/src/app/shared/inline-alert/inline-alert.component.ts @@ -69,6 +69,19 @@ export class InlineAlertComponent { 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 public showInlineSuccess(info: any): void { this.displayedText = ""; diff --git a/src/ui_ng/src/i18n/lang/en-us-lang.json b/src/ui_ng/src/i18n/lang/en-us-lang.json index fe680f68a..b66d7c748 100644 --- a/src/ui_ng/src/i18n/lang/en-us-lang.json +++ b/src/ui_ng/src/i18n/lang/en-us-lang.json @@ -83,9 +83,10 @@ "COMMENT": "Comments", "PASSWORD": "Password", "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_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": { "TITLE": "Change Password", diff --git a/src/ui_ng/src/i18n/lang/es-es-lang.json b/src/ui_ng/src/i18n/lang/es-es-lang.json index 0c6565158..c7cc7f5b8 100644 --- a/src/ui_ng/src/i18n/lang/es-es-lang.json +++ b/src/ui_ng/src/i18n/lang/es-es-lang.json @@ -83,9 +83,9 @@ "COMMENT": "Comentarios", "PASSWORD": "Contraseña", "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_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": { "TITLE": "Cambiar contraseña", diff --git a/src/ui_ng/src/i18n/lang/fr-fr-lang.json b/src/ui_ng/src/i18n/lang/fr-fr-lang.json index f4c9e2ca1..b6b40b6ac 100644 --- a/src/ui_ng/src/i18n/lang/fr-fr-lang.json +++ b/src/ui_ng/src/i18n/lang/fr-fr-lang.json @@ -69,7 +69,10 @@ "FULL_NAME": "Prénom et nom", "COMMENT": "Commentaires", "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": { "TITLE": "Modifier le mot de passe", diff --git a/src/ui_ng/src/i18n/lang/zh-cn-lang.json b/src/ui_ng/src/i18n/lang/zh-cn-lang.json index 48b3c2764..9b3271042 100644 --- a/src/ui_ng/src/i18n/lang/zh-cn-lang.json +++ b/src/ui_ng/src/i18n/lang/zh-cn-lang.json @@ -83,9 +83,9 @@ "COMMENT": "注释", "PASSWORD": "密码", "SAVE_SUCCESS": "成功保存用户设置。", - "ADMIN_RENAME_TIP": "双击将用户名改为 \"admin@harbor.local\", 注意这个操作是不可逆的", + "ADMIN_RENAME_TIP": "单击将用户名改为 \"admin@harbor.local\", 注意这个操作是无法撤销的", "RENAME_SUCCESS": "用户名更改成功!", - "RENAME_CONFIRM_INFO": "更改用户名无法撤销, 你确定更改吗·?" + "RENAME_CONFIRM_INFO": "更改用户名为admin@harbor.local是无法撤销的, 你确定更改吗·?" }, "CHANGE_PWD": { "TITLE": "修改密码",