Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
CSAN
Csan
Commits
e1814597
Commit
e1814597
authored
Apr 25, 2018
by
Deng, Qian
Browse files
Change the admin rename UX
Change the rename operation from double click icon to click button
parent
bf6192f3
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
306 additions
and
222 deletions
+306
-222
src/ui_ng/lib/package.json
src/ui_ng/lib/package.json
+1
-1
src/ui_ng/src/app/account/account-settings/account-settings-modal.component.html
...nt/account-settings/account-settings-modal.component.html
+10
-7
src/ui_ng/src/app/account/account-settings/account-settings-modal.component.scss
...nt/account-settings/account-settings-modal.component.scss
+14
-0
src/ui_ng/src/app/account/account-settings/account-settings-modal.component.ts
...ount/account-settings/account-settings-modal.component.ts
+257
-207
src/ui_ng/src/app/shared/inline-alert/inline-alert.component.ts
..._ng/src/app/shared/inline-alert/inline-alert.component.ts
+13
-0
src/ui_ng/src/i18n/lang/en-us-lang.json
src/ui_ng/src/i18n/lang/en-us-lang.json
+3
-2
src/ui_ng/src/i18n/lang/es-es-lang.json
src/ui_ng/src/i18n/lang/es-es-lang.json
+2
-2
src/ui_ng/src/i18n/lang/fr-fr-lang.json
src/ui_ng/src/i18n/lang/fr-fr-lang.json
+4
-1
src/ui_ng/src/i18n/lang/zh-cn-lang.json
src/ui_ng/src/i18n/lang/zh-cn-lang.json
+2
-2
No files found.
src/ui_ng/lib/package.json
View file @
e1814597
...
...
@@ -43,4 +43,4 @@
"web-animations-js"
:
"^2.2.1"
,
"zone.js"
:
"^0.8.4"
}
}
}
\ No newline at end of file
src/ui_ng/src/app/account/account-settings/account-settings-modal.component.html
View file @
e1814597
...
...
@@ -7,14 +7,17 @@
<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>
<input
type=
"text"
name=
"account_settings_username"
[(ngModel)]=
"account.username"
disabled
id=
"account_settings_username"
size=
"33"
>
<
clr-tooltip
*ngIf=
"canRename"
>
<button
(dbl
click)=
"o
pe
nRename
Alert
()"
class=
"btn btn-
link
"
>
<clr-icon
clrTooltipTrigger
shape=
"info-circle"
size=
"24"
></clr-icon>
<
div
*ngIf=
"canRename"
class=
"rename-tool"
>
<button
[disabled]=
"RenameOnGoing"
(
click)=
"onRename()"
class=
"btn btn-
outline btn-sm
"
>
{{'PROFILE.ADMIN_RENAME_BUTTON' | translate}}
</button>
<clr-tooltip-content
clrPosition=
"bottom-left"
clrSize=
"md"
*clrIfOpen
>
<span
(click)=
"openRenameAlert()"
>
{{'PROFILE.ADMIN_RENAME_TIP' | translate}}
</span>
</clr-tooltip-content>
</clr-tooltip>
<clr-tooltip>
<clr-icon
clrTooltipTrigger
shape=
"info-circle"
size=
"24"
></clr-icon>
<clr-tooltip-content
clrPosition=
"bottom-left"
clrSize=
"md"
*clrIfOpen
>
<span>
{{'PROFILE.ADMIN_RENAME_TIP' | translate}}
</span>
</clr-tooltip-content>
</clr-tooltip>
</div>
</div>
<div
class=
"form-group form-group-override"
>
<label
for=
"account_settings_email"
class=
"required form-group-label-override"
>
{{'PROFILE.EMAIL' | translate}}
</label>
...
...
src/ui_ng/src/app/account/account-settings/account-settings-modal.component.scss
View file @
e1814597
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
src/ui_ng/src/app/account/account-settings/account-settings-modal.component.ts
View file @
e1814597
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
;
accountFormRef
:
NgForm
;
@
ViewChild
(
"
accountSettingsFrom
"
)
accountForm
:
NgForm
;
@
ViewChild
(
InlineAlertComponent
)
inlineAlert
:
InlineAlertComponent
;
constructor
(
private
session
:
SessionService
,
private
msgHandler
:
MessageHandlerService
,
private
router
:
Router
,
private
searchTrigger
:
SearchTriggerService
)
{
}
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
];
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
;
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
());
}
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
();
}
});
}
}
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
});
}
}
}
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
;
}
}
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
;
}
// 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
});
}
}
return
false
;
}
}
else
{
// Reset
this
.
validationStateMap
[
key
]
=
true
;
this
.
emailTooltip
=
"
TOOLTIP.EMAIL
"
;
}
}
public
get
isValid
():
boolean
{
return
this
.
accountForm
&&
this
.
accountForm
.
valid
&&
this
.
error
===
null
&&
this
.
validationStateMap
[
"
account_settings_email
"
];
// backend check is valid as well
isUserDataChange
():
boolean
{
if
(
!
this
.
originalStaticData
||
!
this
.
account
)
{
return
false
;
}
public
get
showProgress
():
boolean
{
return
this
.
isOnCalling
;
for
(
let
prop
in
this
.
originalStaticData
)
{
if
(
this
.
originalStaticData
[
prop
]
!==
this
.
account
[
prop
])
{
return
true
;
}
}
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
"
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
);
});
}
confirmRename
():
void
{
if
(
this
.
canRename
)
{
this
.
session
.
renameAdmin
(
this
.
account
)
.
then
(()
=>
{
this
.
msgHandler
.
showSuccess
(
"
PROFILE.RENAME_SUCCESS
"
);
})
.
catch
(
error
=>
{
this
.
msgHandler
.
handleError
(
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
();
});
}
})
.
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
};
// 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
;
}
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
;
}
}
src/ui_ng/src/app/shared/inline-alert/inline-alert.component.ts
View file @
e1814597
...
...
@@ -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
;