Merge pull request #1940 from steven-zou/master

Fix UI/UX issues
This commit is contained in:
Daniel Jiang 2017-04-06 17:58:26 +08:00 committed by GitHub
commit 78ce1a4ba4
16 changed files with 127 additions and 77 deletions

View File

@ -1,5 +1,6 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Harbor</title>
@ -7,11 +8,20 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico?v=2">
</head>
<body>
<harbor-app>Loading...</harbor-app>
<script type="text/javascript" src="/static/inline.bundle.js"></script>
<script type="text/javascript" src="/static/scripts.bundle.js">
</script><script type="text/javascript" src="/static/styles.bundle.js">
</script><script type="text/javascript" src="/static/vendor.bundle.js"></script>
<script type="text/javascript" src="/static/main.bundle.js"></script></body>
</html>
<body style="overflow-y: hidden;">
<harbor-app>
<div class="spinner spinner-lg app-loading">
Loading...
</div>
</harbor-app>
<script type="text/javascript" src="/static/inline.bundle.js"></script>
<script type="text/javascript" src="/static/scripts.bundle.js">
</script>
<script type="text/javascript" src="/static/styles.bundle.js">
</script>
<script type="text/javascript" src="/static/vendor.bundle.js"></script>
<script type="text/javascript" src="/static/main.bundle.js"></script>
</body>
</html>

View File

@ -4,7 +4,7 @@
"description": "Harbor UI with Clarity",
"angular-cli": {},
"scripts": {
"start": "ng serve --ssl 1 --ssl-key --ssl-cert --host 0.0.0.0 --proxy-config proxy.config.json",
"start": "ng serve --ssl 1 --ssl-key ssl/server.key --ssl-cert ssl/server.crt --host 0.0.0.0 --proxy-config proxy.config.json",
"lint": "tslint \"src/**/*.ts\"",
"test": "ng test --single-run",
"pree2e": "webdriver-manager update",

View File

@ -16,7 +16,7 @@
email
id="account_settings_email" size="30"
(input)='handleValidation("account_settings_email", false)'
(focusout)='handleValidation("account_settings_email", true)'>
(blur)='handleValidation("account_settings_email", true)'>
<span class="tooltip-content">
{{emailTooltip | translate}}
</span>
@ -25,7 +25,7 @@
<div class="form-group form-group-override">
<label for="account_settings_full_name" class="required form-group-label-override">{{'PROFILE.FULL_NAME' | translate}}</label>
<label for="account_settings_full_name" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-top-left" [class.invalid]='!getValidationState("account_settings_full_name")'>
<input type="text" name="account_settings_full_name" #fullNameInput="ngModel" [(ngModel)]="account.realname" required maxLengthExt="20" id="account_settings_full_name" size="30" (input)='handleValidation("account_settings_full_name", false)' (focusout)='handleValidation("account_settings_full_name", true)'>
<input type="text" name="account_settings_full_name" #fullNameInput="ngModel" [(ngModel)]="account.realname" required maxLengthExt="20" id="account_settings_full_name" size="30" (input)='handleValidation("account_settings_full_name", false)' (blur)='handleValidation("account_settings_full_name", true)'>
<span class="tooltip-content">
{{'TOOLTIP.FULL_NAME' | translate}}
</span>

View File

@ -14,7 +14,7 @@
id="reset_pwd_email"
size="40"
(input)="handleValidation(true)"
(focusout)="handleValidation(false)">
(blur)="handleValidation(false)">
<span class="tooltip-content">
{{'TOOLTIP.EMAIL' | translate}}
</span>
@ -25,7 +25,7 @@
</div>
<div class="modal-footer">
<span class="spinner spinner-inline" style="top:8px;" [hidden]="showProgress === false"></span>
<button type="button" class="btn btn-outline" (click)="close()">{{btnCancelCaption | translate}}</button>
<button type="button" class="btn" [class.btn-outline]="!isSuccess" [class.btn-primary]="isSuccess" (click)="close()">{{btnCancelCaption | translate}}</button>
<button *ngIf="!isSuccess" type="button" class="btn btn-primary" [disabled]="!isValid || showProgress" (click)="send()">{{'BUTTON.SEND' | translate}}</button>
</div>
</clr-modal>

View File

@ -27,7 +27,7 @@
[(ngModel)]="newPwd"
#newPassInput="ngModel" size="42"
(input)='handleValidation("newPassword", false)'
(focusout)='handleValidation("newPassword", true)'>
(blur)='handleValidation("newPassword", true)'>
<span class="tooltip-content">
{{'TOOLTIP.PASSWORD' | translate}}
</span>
@ -44,7 +44,7 @@
[(ngModel)]="reNewPwd"
#reNewPassInput="ngModel" size="42"
(input)='handleValidation("reNewPassword", false)'
(focusout)='handleValidation("reNewPassword", true)'>
(blur)='handleValidation("reNewPassword", true)'>
<span class="tooltip-content">
{{'TOOLTIP.CONFIRM_PWD' | translate}}
</span>

View File

@ -1,12 +1,13 @@
<clr-modal [(clrModalOpen)]="opened" [clrModalStaticBackdrop]="true" [clrModalClosable]="false">
<h3 class="modal-title">{{'RESET_PWD.TITLE' | translate}}</h3>
<label class="modal-title reset-modal-title-override">{{'RESET_PWD.CAPTION2' | translate}}</label>
<inline-alert class="modal-title"></inline-alert>
<div class="modal-body" style="overflow-y: hidden;">
<form #resetPwdForm="ngForm" class="form">
<section class="form-block">
<div class="form-group">
<label for="newPassword" class="form-group-label-override">{{'CHANGE_PWD.NEW_PWD' | translate}}</label>
<label for="newPassword" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-bottom-left" [class.invalid]='getValidationState("newPassword") === false'>
<label for="newPassword" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-bottom-left" [class.invalid]='!getValidationState("newPassword")'>
<input [disabled]="resetOk" type="password" id="newPassword" placeholder='{{"PLACEHOLDER.NEW_PWD" | translate}}'
required
pattern="^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?!.*\s).{8,20}$"
@ -14,8 +15,8 @@
[(ngModel)]="password"
#newPassInput="ngModel"
size="25"
(input)='handleValidation("newPassword", true)'
(focusout)='handleValidation("newPassword", false)'>
(input)='handleValidation("newPassword", false)'
(blur)='handleValidation("newPassword", true)'>
<span class="tooltip-content">
{{'TOOLTIP.PASSWORD' | translate}}
</span>
@ -23,7 +24,7 @@
</div>
<div class="form-group">
<label for="reNewPassword" class="form-group-label-override">{{'CHANGE_PWD.CONFIRM_PWD' | translate}}</label>
<label for="reNewPassword" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-bottom-left" [class.invalid]='getValidationState("reNewPassword") === false'>
<label for="reNewPassword" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-top-left" [class.invalid]='!getValidationState("reNewPassword")'>
<input [disabled]="resetOk" type="password" id="reNewPassword" placeholder='{{"PLACEHOLDER.CONFIRM_PWD" | translate}}'
required
pattern="^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?!.*\s).{8,20}$"
@ -31,21 +32,19 @@
[(ngModel)]="confirmPwd"
#reNewPassInput
size="25"
(input)='handleValidation("reNewPassword", true)'
(focusout)='handleValidation("reNewPassword", false)'>
(input)='handleValidation("reNewPassword", false)'
(blur)='handleValidation("reNewPassword", true)'>
<span class="tooltip-content">
{{'TOOLTIP.CONFIRM_PWD' | translate}}
</span>
</label>
</div>
</section>
<inline-alert></inline-alert>
<div style="height: 30px;"></div>
</form>
</div>
<div class="modal-footer">
<span class="spinner spinner-inline" style="top:8px;" [hidden]="showProgress === false"></span>
<button type="button" class="btn btn-outline" (click)="close()">{{btnCancelCaption | translate}}</button>
<button type="button" class="btn" [class.btn-outline]="!resetOk" [class.btn-primary]="resetOk" (click)="close()">{{btnCancelCaption | translate}}</button>
<button *ngIf="!resetOk" type="button" class="btn btn-primary" [disabled]="!isValid || showProgress" (click)="send()">{{'BUTTON.OK' | translate}}</button>
</div>
</clr-modal>

View File

@ -56,8 +56,7 @@ export class ResetPasswordComponent implements OnInit {
public getValidationState(key: string): boolean {
return this.validationState &&
this.validationState[key] &&
key === 'reNewPassword' ? this.samePassword() : true;
this.validationState[key];
}
public open(): void {
@ -109,10 +108,8 @@ export class ResetPasswordComponent implements OnInit {
}
public handleValidation(key: string, flag: boolean): void {
if (flag) {
if (!this.validationState[key]) {
this.validationState[key] = true;
}
if (!flag) {
this.validationState[key] = true;
} else {
this.validationState[key] = this.getControlValidationState(key);
if (this.validationState[key]) {

View File

@ -38,6 +38,7 @@
.more-info-link {
position: relative;
top: 90px;
left: 330px;
top: 80px;
left: 294px;
padding-right: 36px;
}

View File

@ -13,5 +13,15 @@
}
.content-area-override {
padding: 24px 36px !important;
padding: 36px !important;
padding-right: 21px !important;
}
.global-message-alert {
position: fixed;
top: 55px;
left: 260px;
width: 100%;
z-index: 999;
padding-right: 276px;
}

View File

@ -3,7 +3,9 @@
<navigator (showAccountSettingsModal)="openModal($event)" (showPwdChangeModal)="openModal($event)"></navigator>
<div class="content-container">
<div class="content-area" [class.container-override]="showSearch" [class.content-area-override]="!shouldOverrideContent" [class.start-content-padding]="shouldOverrideContent">
<global-message [isAppLevel]="false"></global-message>
<div class="global-message-alert">
<global-message [isAppLevel]="false"></global-message>
</div>
<!-- Only appear when searching -->
<search-result></search-result>
<router-outlet></router-outlet>

View File

@ -65,7 +65,8 @@
<button type="button" class="btn btn-outline" (click)="cancel()" [disabled]="!isValid() || !hasChanges()">{{'BUTTON.CANCEL' | translate}}</button>
<button type="button" class="btn btn-outline" (click)="testMailServer()" *ngIf="showTestServerBtn" [disabled]="!isMailConfigValid()">{{'BUTTON.TEST_MAIL' | translate}}</button>
<button type="button" class="btn btn-outline" (click)="testLDAPServer()" *ngIf="showLdapServerBtn" [disabled]="!isLDAPConfigValid()">{{'BUTTON.TEST_LDAP' | translate}}</button>
<span class="spinner spinner-inline" [hidden]="!testingInProgress"></span>
<span id="forTestingMail" class="spinner spinner-inline" [hidden]="hideMailTestingSpinner"></span>
<span id="forTestingLDAP" class="spinner spinner-inline" [hidden]="hideLDAPTestingSpinner"></span>
</div>
</div>
</div>

View File

@ -17,7 +17,7 @@ import { AppConfigService } from '../app-config.service';
import { SessionService } from '../shared/session.service';
import { MessageHandlerService } from '../shared/message-handler/message-handler.service';
const fakePass = "fakepassword";
const fakePass = "aWpLOSYkIzJTTU4wMDkx";
const TabLinkContentMap = {
"config-auth": "authentication",
"config-replication": "replication",
@ -36,7 +36,8 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
private currentTabId: string = "config-auth";//default tab
private originalCopy: Configuration;
private confirmSub: Subscription;
private testingOnGoing: boolean = false;
private testingMailOnGoing: boolean = false;
private testingLDAPOnGoing: boolean = false;
@ViewChild("repoConfigFrom") repoConfigForm: NgForm;
@ViewChild("systemConfigFrom") systemConfigForm: NgForm;
@ -131,10 +132,6 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
return this.onGoing;
}
public get testingInProgress(): boolean {
return this.testingOnGoing;
}
public isValid(): boolean {
return this.repoConfigForm &&
this.repoConfigForm.valid &&
@ -152,7 +149,8 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
public isMailConfigValid(): boolean {
return this.mailConfig &&
this.mailConfig.isValid();
this.mailConfig.isValid() &&
!this.testingMailOnGoing;
}
public get showTestServerBtn(): boolean {
@ -165,8 +163,18 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
this.allConfig.auth_mode.value === "ldap_auth";
}
public get hideMailTestingSpinner(): boolean {
return !this.testingMailOnGoing || !this.showTestServerBtn;
}
public get hideLDAPTestingSpinner(): boolean {
return !this.testingLDAPOnGoing || !this.showLdapServerBtn;
}
public isLDAPConfigValid(): boolean {
return this.authConfig && this.authConfig.isValid();
return this.authConfig &&
this.authConfig.isValid() &&
!this.testingLDAPOnGoing;
}
public tabLinkClick(tabLink: string) {
@ -239,6 +247,9 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
* @memberOf ConfigurationComponent
*/
public testMailServer(): void {
if(this.testingMailOnGoing){
return;//Should not come here
}
let mailSettings = {};
for (let prop in this.allConfig) {
if (prop.startsWith("email_")) {
@ -255,23 +266,27 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
delete mailSettings["email_password"];
}
this.testingOnGoing = true;
this.testingMailOnGoing = true;
this.configService.testMailServer(mailSettings)
.then(response => {
this.testingOnGoing = false;
this.testingMailOnGoing = false;
this.msgHandler.showSuccess("CONFIG.TEST_MAIL_SUCCESS");
})
.catch(error => {
this.testingOnGoing = false;
this.testingMailOnGoing = false;
let err = error._body;
if(!err){
if (!err) {
err = "UNKNOWN";
}
this.msgHandler.showError("CONFIG.TEST_MAIL_FAILED", {'param': err});
this.msgHandler.showError("CONFIG.TEST_MAIL_FAILED", { 'param': err });
});
}
public testLDAPServer(): void {
if(this.testingLDAPOnGoing){
return;//Should not come here
}
let ldapSettings = {};
for (let prop in this.allConfig) {
if (prop.startsWith("ldap_")) {
@ -281,25 +296,25 @@ export class ConfigurationComponent implements OnInit, OnDestroy {
let allChanges = this.getChanges();
let ldapSearchPwd = allChanges["ldap_search_password"];
if(ldapSearchPwd){
if (ldapSearchPwd) {
ldapSettings['ldap_search_password'] = ldapSearchPwd;
}else{
} else {
delete ldapSettings['ldap_search_password'];
}
this.testingOnGoing = true;
this.testingLDAPOnGoing = true;
this.configService.testLDAPServer(ldapSettings)
.then(respone => {
this.testingOnGoing = false;
this.testingLDAPOnGoing = false;
this.msgHandler.showSuccess("CONFIG.TEST_LDAP_SUCCESS");
})
.catch(error => {
this.testingOnGoing = false;
this.testingLDAPOnGoing = false;
let err = error._body;
if(!err){
if (!err) {
err = "UNKNOWN";
}
this.msgHandler.showError("CONFIG.TEST_LDAP_FAILED", {'param': err});
this.msgHandler.showError("CONFIG.TEST_LDAP_FAILED", { 'param': err });
});
}

View File

@ -1,6 +1,6 @@
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div class="row flex-items-xs-between flex-items-xs-top">
<div class="row flex-items-xs-between flex-items-xs-top" style="padding-left: 15px; padding-right: 15px;">
<h2 class="header-title">{{'PROJECT.PROJECTS' | translate}}</h2>
<div>
<statistics-panel></statistics-panel>
@ -13,7 +13,7 @@
</div>
<div class="option-right">
<div class="select" style="float: left;">
<select (change)="doFilterProjects($event)">
<select (change)="doFilterProjects($event)">
<option value="0">{{projectTypes[0] | translate}}</option>
<option value="1">{{projectTypes[1] | translate}}</option>
</select>

View File

@ -58,30 +58,32 @@
*/
.esxc-gauge-small .esxc-gauge-container {
width: 100px;
height: 50px;
width: 60px;
height: 30px;
top: -8px;
left: 8px;
}
.esxc-gauge-small .esxc-gauge-circle-fill {
height: 100px;
border-radius: 50px;
clip: rect(50px, 100px, 100px, 0);
height: 60px;
border-radius: 30px;
clip: rect(30px, 60px, 60px, 0);
}
.esxc-gauge-small .esxc-gauge-circle-bg {
height: 100px;
border-radius: 50px;
height: 60px;
border-radius: 30px;
}
.esxc-gauge-small .esxc-gauge-circle-inner {
width: 80px;
height: 80px;
border-radius: 40px;
margin: 10px;
width: 50px;
height: 50px;
border-radius: 25px;
margin: 5px;
}
.esxc-gauge-small .esxc-gauge-circle-caption {
margin-top: 20px;
margin-top: 6px;
}
@ -144,8 +146,11 @@
margin-top: 95px;
}
/*Sall size*/
.esxc-gauge-small .esxc-gauge-circle-caption .esxc-value {
font-size: 24px;
font-size: 16px;
font-weight: bold;
}
@ -161,6 +166,8 @@
font-size: 16px;
text-align: center;
margin-top: 3px;
position: relative;
bottom: -2px;
}
.esxc-gauge-small .esxc-title .esxc-bar-title {
@ -172,6 +179,8 @@
.esxc-gauge-small .esxc-limit {
text-align: center;
position: relative;
top: -8px;
}
.esxc-gauge-small .esxc-limit .esxc-value {
@ -190,6 +199,9 @@
text-align: right;
}
/*medium size*/
.esxc-gauge-medium .esxc-gauge-circle-caption {
margin-top: 40px;
color: #000;
@ -232,6 +244,9 @@
margin-top: -8px;
}
/*large size*/
.esxc-gauge-large .esxc-gauge-circle-caption .esxc-value {
font-size: 40px;
}

View File

@ -6,7 +6,7 @@
<label for="username" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-bottom-left" [class.invalid]='getValidationState("username")'>
<input type="text" required pattern='[^"~#$%]+' maxLengthExt="20" #usernameInput="ngModel" name="username" [(ngModel)]="newUser.username" id="username" size="36"
(input)='handleValidation("username", false)'
(focusout)='handleValidation("username", true)'>
(blur)='handleValidation("username", true)'>
<span class="tooltip-content">
{{usernameTooltip | translate}}
</span>
@ -20,7 +20,7 @@
email
id="email" size="36"
(input)='handleValidation("email", false)'
(focusout)='handleValidation("email", true)'>
(blur)='handleValidation("email", true)'>
<span class="tooltip-content">
{{emailTooltip | translate}}
</span>
@ -33,7 +33,7 @@
<label for="realname" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-bottom-left" [class.invalid]='getValidationState("realname")'>
<input type="text" name="realname" #fullNameInput="ngModel" [(ngModel)]="newUser.realname" required maxLengthExt="20" id="realname" size="36"
(input)='handleValidation("realname", false)'
(focusout)='handleValidation("realname", true)'>
(blur)='handleValidation("realname", true)'>
<span class="tooltip-content">
{{'TOOLTIP.FULL_NAME' | translate}}
</span>
@ -49,7 +49,7 @@
[(ngModel)]="newUser.password"
#newPassInput="ngModel" size="36"
(input)='handleValidation("newPassword", false)'
(focusout)='handleValidation("newPassword", true)'>
(blur)='handleValidation("newPassword", true)'>
<span class="tooltip-content">
{{'TOOLTIP.PASSWORD' | translate}}
</span>
@ -66,7 +66,7 @@
[(ngModel)]="confirmedPwd"
#confirmPassInput="ngModel" size="36"
(input)='handleValidation("confirmPassword", false)'
(focusout)='handleValidation("confirmPassword", true)'>
(blur)='handleValidation("confirmPassword", true)'>
<span class="tooltip-content">
{{'TOOLTIP.CONFIRM_PWD' | translate}}
</span>
@ -77,7 +77,7 @@
<label for="comment" aria-haspopup="true" role="tooltip" class="tooltip tooltip-validation tooltip-md tooltip-bottom-left" [class.invalid]='getValidationState("comment")'>
<input type="text" #commentInput="ngModel" name="comment" [(ngModel)]="newUser.comment" maxLengthExt="20" id="comment" size="36"
(input)='handleValidation("comment", false)'
(focusout)='handleValidation("comment", true)'>
(blur)='handleValidation("comment", true)'>
<span class="tooltip-content">
{{'TOOLTIP.COMMENT' | translate}}
</span>

View File

@ -1,6 +1,6 @@
<div class="row flex-items-xs-between flex-items-xs-middle">
<div></div>
<div id="right_statistic_panel" style="margin-right: 18px;">
<div id="right_statistic_panel" style="margin-right: 18px; margin-top: 8px;">
<div class="statistic-block">
<div class="statistic-column-block">
<div>