mirror of
https://github.com/goharbor/harbor
synced 2025-05-19 10:16:03 +00:00
Change the admin rename UX
Change the rename operation from double click icon to click button
This commit is contained in:
parent
bf6192f32b
commit
e1814597d8
@ -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")'>
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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;
|
||||||
|
@ -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 = "";
|
||||||
|
@ -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",
|
||||||
|
@ -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",
|
||||||
|
@ -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",
|
||||||
|
@ -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": "修改密码",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user