diff --git a/src/ui_ng/lib/src/tag/tag.component.html.ts b/src/ui_ng/lib/src/tag/tag.component.html.ts
index 5024f6b32..d621e603a 100644
--- a/src/ui_ng/lib/src/tag/tag.component.html.ts
+++ b/src/ui_ng/lib/src/tag/tag.component.html.ts
@@ -44,7 +44,7 @@ export const TAG_TEMPLATE = `
{{t.name}}
{{t.name}}
-
{{t.size}}
+
{{sizeTransform(t.size)}}
diff --git a/src/ui_ng/lib/src/tag/tag.component.ts b/src/ui_ng/lib/src/tag/tag.component.ts
index 10f1c145c..9d5ea5cf8 100644
--- a/src/ui_ng/lib/src/tag/tag.component.ts
+++ b/src/ui_ng/lib/src/tag/tag.component.ts
@@ -21,25 +21,25 @@ import {
ChangeDetectionStrategy,
ChangeDetectorRef,
ElementRef
-} from '@angular/core';
+} from "@angular/core";
-import { TagService, VulnerabilitySeverity, RequestQueryParams } from '../service/index';
-import { ErrorHandler } from '../error-handler/error-handler';
-import { ChannelService } from '../channel/index';
+import { TagService, VulnerabilitySeverity, RequestQueryParams } from "../service/index";
+import { ErrorHandler } from "../error-handler/error-handler";
+import { ChannelService } from "../channel/index";
import {
ConfirmationTargets,
ConfirmationState,
ConfirmationButtons
-} from '../shared/shared.const';
+} from "../shared/shared.const";
-import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation-dialog.component';
-import { ConfirmationMessage } from '../confirmation-dialog/confirmation-message';
-import { ConfirmationAcknowledgement } from '../confirmation-dialog/confirmation-state-message';
+import { ConfirmationDialogComponent } from "../confirmation-dialog/confirmation-dialog.component";
+import { ConfirmationMessage } from "../confirmation-dialog/confirmation-message";
+import { ConfirmationAcknowledgement } from "../confirmation-dialog/confirmation-state-message";
-import { Tag, TagClickEvent } from '../service/interface';
+import { Tag, TagClickEvent } from "../service/interface";
-import { TAG_TEMPLATE } from './tag.component.html';
-import { TAG_STYLE } from './tag.component.css';
+import { TAG_TEMPLATE } from "./tag.component.html";
+import { TAG_STYLE } from "./tag.component.css";
import {
toPromise,
@@ -49,17 +49,17 @@ import {
doSorting,
VULNERABILITY_SCAN_STATUS,
DEFAULT_PAGE_SIZE
-} from '../utils';
+} from "../utils";
-import { TranslateService } from '@ngx-translate/core';
+import { TranslateService } from "@ngx-translate/core";
-import { State, Comparator } from 'clarity-angular';
-import {CopyInputComponent} from '../push-image/copy-input.component';
+import { State, Comparator } from "clarity-angular";
+import {CopyInputComponent} from "../push-image/copy-input.component";
import {BatchInfo, BathInfoChanges} from "../confirmation-dialog/confirmation-batch-message";
import {Observable} from "rxjs/Observable";
@Component({
- selector: 'hbr-tag',
+ selector: "hbr-tag",
template: TAG_TEMPLATE,
styles: [TAG_STYLE],
changeDetection: ChangeDetectionStrategy.OnPush
@@ -87,22 +87,22 @@ export class TagComponent implements OnInit {
showTagManifestOpened: boolean;
manifestInfoTitle: string;
digestId: string;
- staticBackdrop: boolean = true;
- closable: boolean = false;
+ staticBackdrop = true;
+ closable = false;
lastFilteredTagName: string;
batchDelectionInfos: BatchInfo[] = [];
- createdComparator: Comparator
= new CustomComparator('created', 'date');
+ createdComparator: Comparator = new CustomComparator("created", "date");
- loading: boolean = false;
- copyFailed: boolean = false;
+ loading = false;
+ copyFailed = false;
selectedRow: Tag[] = [];
- @ViewChild('confirmationDialog')
+ @ViewChild("confirmationDialog")
confirmationDialog: ConfirmationDialogComponent;
- @ViewChild('digestTarget') textInput: ElementRef;
- @ViewChild('copyInput') copyInput: CopyInputComponent;
+ @ViewChild("digestTarget") textInput: ElementRef;
+ @ViewChild("copyInput") copyInput: CopyInputComponent;
pageSize: number = DEFAULT_PAGE_SIZE;
currentPage = 1;
@@ -119,16 +119,16 @@ export class TagComponent implements OnInit {
ngOnInit() {
if (!this.projectId) {
- this.errorHandler.error('Project ID cannot be unset.');
+ this.errorHandler.error("Project ID cannot be unset.");
return;
}
if (!this.repoName) {
- this.errorHandler.error('Repo name cannot be unset.');
+ this.errorHandler.error("Repo name cannot be unset.");
return;
}
this.retrieve();
- this.lastFilteredTagName = '';
+ this.lastFilteredTagName = "";
}
selectedChange(): void {
@@ -147,7 +147,7 @@ export class TagComponent implements OnInit {
st.page.size = this.pageSize;
st.page.from = 0;
st.page.to = this.pageSize - 1;
- st.filters = [{property: 'name', value: this.lastFilteredTagName}];
+ st.filters = [{property: "name", value: this.lastFilteredTagName}];
this.clrLoad(st);
}
@@ -161,8 +161,8 @@ export class TagComponent implements OnInit {
// Pagination
let params: RequestQueryParams = new RequestQueryParams();
- params.set('page', '' + pageNumber);
- params.set('page_size', '' + this.pageSize);
+ params.set("page", "" + pageNumber);
+ params.set("page_size", "" + this.pageSize);
this.loading = true;
@@ -188,7 +188,7 @@ export class TagComponent implements OnInit {
}
refresh() {
- this.doSearchTagNames('');
+ this.doSearchTagNames("");
}
@@ -217,9 +217,6 @@ export class TagComponent implements OnInit {
if (t.signature !== null) {
signatures.push(t.name);
}
-
- // size
- t.size = this.sizeTransform(t.size);
});
this.tags = items;
let signedName: {[key: string]: string[]} = {};
@@ -241,13 +238,13 @@ export class TagComponent implements OnInit {
sizeTransform(tagSize: string): string {
let size: number = Number.parseInt(tagSize);
if (Math.pow(1024, 1) <= size && size < Math.pow(1024, 2)) {
- return (size / Math.pow(1024, 1)).toFixed(2) + 'KB';
+ return (size / Math.pow(1024, 1)).toFixed(2) + "KB";
} else if (Math.pow(1024, 2) <= size && size < Math.pow(1024, 3)) {
- return (size / Math.pow(1024, 2)).toFixed(2) + 'MB';
+ return (size / Math.pow(1024, 2)).toFixed(2) + "MB";
} else if (Math.pow(1024, 3) <= size && size < Math.pow(1024, 4)) {
- return (size / Math.pow(1024, 3)).toFixed(2) + 'MB';
+ return (size / Math.pow(1024, 3)).toFixed(2) + "MB";
} else {
- return size + 'B';
+ return size + "B";
}
}
@@ -263,10 +260,10 @@ export class TagComponent implements OnInit {
});
let titleKey: string, summaryKey: string, content: string, buttons: ConfirmationButtons;
- titleKey = 'REPOSITORY.DELETION_TITLE_TAG';
- summaryKey = 'REPOSITORY.DELETION_SUMMARY_TAG';
+ titleKey = "REPOSITORY.DELETION_TITLE_TAG";
+ summaryKey = "REPOSITORY.DELETION_SUMMARY_TAG";
buttons = ConfirmationButtons.DELETE_CANCEL;
- content = tagNames.join(' , ');
+ content = tagNames.join(" , ");
let message = new ConfirmationMessage(
titleKey,
summaryKey,
@@ -300,9 +297,9 @@ export class TagComponent implements OnInit {
delOperate(signature: any, name: string) {
let findedList = this.batchDelectionInfos.find(data => data.name === name);
if (signature) {
- Observable.forkJoin(this.translateService.get('BATCH.DELETED_FAILURE'),
- this.translateService.get('REPOSITORY.DELETION_SUMMARY_TAG_DENIED')).subscribe(res => {
- let wrongInfo: string = res[1] + 'notary -s https://' + this.registryUrl + ':4443 -d ~/.docker/trust remove -p ' + this.registryUrl + '/' + this.repoName + ' ' + name;
+ Observable.forkJoin(this.translateService.get("BATCH.DELETED_FAILURE"),
+ this.translateService.get("REPOSITORY.DELETION_SUMMARY_TAG_DENIED")).subscribe(res => {
+ let wrongInfo: string = res[1] + "notary -s https://" + this.registryUrl + ":4443 -d ~/.docker/trust remove -p " + this.registryUrl + "/" + this.repoName + " " + name;
findedList = BathInfoChanges(findedList, res[0], false, true, wrongInfo);
});
} else {
@@ -310,12 +307,12 @@ export class TagComponent implements OnInit {
.deleteTag(this.repoName, name))
.then(
response => {
- this.translateService.get('BATCH.DELETED_SUCCESS')
+ this.translateService.get("BATCH.DELETED_SUCCESS")
.subscribe(res => {
findedList = BathInfoChanges(findedList, res);
});
}).catch(error => {
- this.translateService.get('BATCH.DELETED_FAILURE').subscribe(res => {
+ this.translateService.get("BATCH.DELETED_FAILURE").subscribe(res => {
findedList = BathInfoChanges(findedList, res, false, true);
});
});
@@ -324,7 +321,7 @@ export class TagComponent implements OnInit {
showDigestId(tag: Tag[]) {
if (tag && (tag.length === 1)) {
- this.manifestInfoTitle = 'REPOSITORY.COPY_DIGEST_ID';
+ this.manifestInfoTitle = "REPOSITORY.COPY_DIGEST_ID";
this.digestId = tag[0].digest;
this.showTagManifestOpened = true;
this.copyFailed = false;
@@ -388,7 +385,7 @@ export class TagComponent implements OnInit {
if (t && t.length) {
t.forEach((data: any) => {
let tagId = data.name;
- this.channel.publishScanEvent(this.repoName + '/' + tagId);
+ this.channel.publishScanEvent(this.repoName + "/" + tagId);
});
}
}
diff --git a/src/ui_ng/package.json b/src/ui_ng/package.json
index dbba99693..32549fb92 100644
--- a/src/ui_ng/package.json
+++ b/src/ui_ng/package.json
@@ -31,7 +31,7 @@
"clarity-icons": "^0.10.17",
"clarity-ui": "^0.10.17",
"core-js": "^2.4.1",
- "harbor-ui": "0.6.29",
+ "harbor-ui": "0.6.30",
"intl": "^1.2.5",
"mutationobserver-shim": "^0.3.2",
"ngx-cookie": "^1.0.0",
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 acdd89867..4edd36b69 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
@@ -11,38 +11,35 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
-import { Component, OnInit, ViewChild, AfterViewChecked } from '@angular/core';
-import { NgForm } from '@angular/forms';
+import { Component, OnInit, ViewChild, AfterViewChecked } from "@angular/core";
+import { NgForm } from "@angular/forms";
+import { Router, NavigationExtras } from "@angular/router";
-import { SessionUser } from '../../shared/session-user';
-import { SessionService } from '../../shared/session.service';
-import { InlineAlertComponent } from '../../shared/inline-alert/inline-alert.component';
-import { MessageHandlerService } from '../../shared/message-handler/message-handler.service';
+import { SessionUser } from "../../shared/session-user";
+import { SessionService } from "../../shared/session.service";
+import { InlineAlertComponent } from "../../shared/inline-alert/inline-alert.component";
+import { MessageHandlerService } from "../../shared/message-handler/message-handler.service";
+import { SearchTriggerService } from "../../base/global-search/search-trigger.service";
+import { CommonRoutes } from "../../shared/shared.const";
@Component({
selector: "account-settings-modal",
templateUrl: "account-settings-modal.component.html",
- styleUrls: ['../../common.css']
+ styleUrls: ["../../common.css"]
})
export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
- opened: boolean = false;
- staticBackdrop: boolean = true;
+ opened = false;
+ staticBackdrop = true;
account: SessionUser;
error: any = null;
originalStaticData: SessionUser;
- emailTooltip: string = 'TOOLTIP.EMAIL';
- private validationStateMap: any = {
- "account_settings_email": true,
- "account_settings_full_name": true
- };
+ emailTooltip = "TOOLTIP.EMAIL";
mailAlreadyChecked = {};
-
- isOnCalling: boolean = false;
- formValueChanged: boolean = false;
- checkOnGoing: boolean = false;
-
- RenameOnGoing: boolean = false;
+ isOnCalling = false;
+ formValueChanged = false;
+ checkOnGoing = false;
+ RenameOnGoing = false;
accountFormRef: NgForm;
@ViewChild("accountSettingsFrom") accountForm: NgForm;
@@ -51,10 +48,18 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
constructor(
private session: SessionService,
- private msgHandler: MessageHandlerService) { }
+ 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
+ // Value copy
this.account = Object.assign({}, this.session.getCurrentUser());
}
@@ -64,11 +69,11 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
handleValidation(key: string, flag: boolean): void {
if (flag) {
- //Checking
+ // Checking
let cont = this.accountForm.controls[key];
if (cont) {
this.validationStateMap[key] = cont.valid;
- //Check email existing from backend
+ // 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]) {
@@ -79,7 +84,7 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
return;
}
- //Mail changed
+ // Mail changed
this.checkOnGoing = true;
this.session.checkUserExisting("email", this.account.email)
.then((res: boolean) => {
@@ -90,17 +95,17 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
}
this.mailAlreadyChecked[this.account.email] = {
result: res
- }; //Tag it checked
+ }; // Tag it checked
})
.catch(error => {
this.checkOnGoing = false;
- this.validationStateMap[key] = false;//Not valid @ backend
+ this.validationStateMap[key] = false; // Not valid @ backend
});
}
}
}
} else {
- //Reset
+ // Reset
this.validationStateMap[key] = true;
this.emailTooltip = "TOOLTIP.EMAIL";
}
@@ -124,7 +129,7 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
return this.accountForm &&
this.accountForm.valid &&
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 {
@@ -136,13 +141,13 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
}
public get renamable(): 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.account.username === "admin" && this.account.user_id === 1;
}
openRenameAlert(): void {
this.RenameOnGoing = true;
this.inlineAlert.showInlineConfirmation({
- message: 'PROFILE.RENAME_CONFIRM_INFO'
+ message: "PROFILE.RENAME_CONFIRM_INFO"
});
}
@@ -150,7 +155,7 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
if (this.renamable) {
this.session.renameAdmin(this.account)
.then(() => {
- this.msgHandler.showSuccess('PROFILE.RENAME_SUCCESS');
+ this.msgHandler.showSuccess("PROFILE.RENAME_SUCCESS");
})
.catch(error => {
this.msgHandler.handleError(error);
@@ -173,19 +178,31 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
}
}
+ // 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
+ // 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
+ // Confirm inline alert is closed
this.inlineAlert.close();
- //Clear check history
+ // Clear check history
this.mailAlreadyChecked = {};
- //Reset validation status
+ // Reset validation status
this.validationStateMap = {
"account_settings_email": true,
"account_settings_full_name": true
@@ -195,11 +212,14 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
}
close() {
+ if (this.RenameOnGoing) {
+ this.RenameOnGoing = false;
+ }
if (this.formValueChanged) {
if (!this.isUserDataChange()) {
this.opened = false;
} else {
- //Need user confirmation
+ // Need user confirmation
this.inlineAlert.showInlineConfirmation({
message: "ALERT.FORM_CHANGE_CONFIRMATION"
});
@@ -214,7 +234,7 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
return;
}
- //Double confirm session is valid
+ // Double confirm session is valid
let cUser = this.session.getCurrentUser();
if (!cUser) {
return;
@@ -249,9 +269,9 @@ export class AccountSettingsModalComponent implements OnInit, AfterViewChecked {
if (this.RenameOnGoing) {
this.confirmRename();
this.RenameOnGoing = false;
+ this.logOut();
}
this.inlineAlert.close();
this.opened = false;
}
-
}
\ No newline at end of file
diff --git a/src/ui_ng/src/app/app-config.ts b/src/ui_ng/src/app/app-config.ts
index 0702cba12..ab63b2dfc 100644
--- a/src/ui_ng/src/app/app-config.ts
+++ b/src/ui_ng/src/app/app-config.ts
@@ -14,25 +14,6 @@
import { ClairDBStatus } from 'harbor-ui';
export class AppConfig {
- constructor() {
- //Set default value
- this.with_notary = false;
- this.with_admiral = false;
- this.with_clair = false;
- this.admiral_endpoint = "";
- this.auth_mode = "db_auth";
- this.registry_url = "";
- this.project_creation_restriction = "everyone";
- this.self_registration = true;
- this.has_ca_root = false;
- this.harbor_version = "1.2.0";//default
- this.clair_vulnerability_status = {
- overall_last_update: 0,
- details: []
- };
- this.next_scan_all = 0;
- }
-
with_notary: boolean;
with_admiral: boolean;
with_clair: boolean;
@@ -45,4 +26,25 @@ export class AppConfig {
harbor_version: string;
clair_vulnerability_status?: ClairDBStatus;
next_scan_all: number;
+ registry_storage_provider_name: string;
+
+ constructor() {
+ // Set default value
+ this.with_notary = false;
+ this.with_admiral = false;
+ this.with_clair = false;
+ this.admiral_endpoint = "";
+ this.auth_mode = "db_auth";
+ this.registry_url = "";
+ this.project_creation_restriction = "everyone";
+ this.self_registration = true;
+ this.has_ca_root = false;
+ this.harbor_version = "1.2.0";
+ this.clair_vulnerability_status = {
+ overall_last_update: 0,
+ details: []
+ };
+ this.next_scan_all = 0;
+ this.registry_storage_provider_name = "";
+ }
}
\ No newline at end of file
diff --git a/src/ui_ng/src/app/base/navigator/navigator.component.ts b/src/ui_ng/src/app/base/navigator/navigator.component.ts
index f25239a5c..d0ee3f94c 100644
--- a/src/ui_ng/src/app/base/navigator/navigator.component.ts
+++ b/src/ui_ng/src/app/base/navigator/navigator.component.ts
@@ -107,15 +107,15 @@ export class NavigatorComponent implements OnInit {
public get canChangePassword(): boolean {
let user = this.session.getCurrentUser();
let config = this.appConfigService.getConfig();
-
- return user && ((config && !(config.auth_mode === 'ldap_auth' || config.auth_mode === 'uaa_auth')) || (user.user_id === 1 && user.username === 'admin'));
+
+ return user && ((config && !(config.auth_mode === "ldap_auth" || config.auth_mode === "uaa_auth")) || (user.user_id === 1 && user.username === "admin"));
}
matchLang(lang: string): boolean {
return lang.trim() === this.selectedLang;
}
- //Open the account setting dialog
+ // Open the account setting dialog
openAccountSettingsModal(): void {
this.showAccountSettingsModal.emit({
modalName: modalEvents.USER_PROFILE,
@@ -123,7 +123,7 @@ export class NavigatorComponent implements OnInit {
});
}
- //Open change password dialog
+ // Open change password dialog
openChangePwdModal(): void {
this.showPwdChangeModal.emit({
modalName: modalEvents.CHANGE_PWD,
diff --git a/src/ui_ng/src/app/project/create-project/create-project.component.html b/src/ui_ng/src/app/project/create-project/create-project.component.html
index 9d93180d1..a067a3211 100644
--- a/src/ui_ng/src/app/project/create-project/create-project.component.html
+++ b/src/ui_ng/src/app/project/create-project/create-project.component.html
@@ -1,6 +1,6 @@
{{'PROJECT.NEW_PROJECT' | translate}}
-
+