diff --git a/src/ui_ng/lib/package.json b/src/ui_ng/lib/package.json index 0c99887f8..bba58816b 100644 --- a/src/ui_ng/lib/package.json +++ b/src/ui_ng/lib/package.json @@ -1,6 +1,6 @@ { "name": "harbor-ui", - "version": "0.6.25", + "version": "0.6.30", "description": "Harbor shared UI components based on Clarity and Angular4", "scripts": { "start": "ng serve --host 0.0.0.0 --port 4500 --proxy-config proxy.config.json", diff --git a/src/ui_ng/lib/pkg/package.json b/src/ui_ng/lib/pkg/package.json index 69d0a683c..f85d0b751 100644 --- a/src/ui_ng/lib/pkg/package.json +++ b/src/ui_ng/lib/pkg/package.json @@ -1,6 +1,6 @@ { "name": "harbor-ui", - "version": "0.6.25", + "version": "0.6.30", "description": "Harbor shared UI components based on Clarity and Angular4", "author": "VMware", "module": "index.js", diff --git a/src/ui_ng/lib/src/endpoint/endpoint.component.html.ts b/src/ui_ng/lib/src/endpoint/endpoint.component.html.ts index 17f4d981c..2e7b68960 100644 --- a/src/ui_ng/lib/src/endpoint/endpoint.component.html.ts +++ b/src/ui_ng/lib/src/endpoint/endpoint.component.html.ts @@ -1,4 +1,4 @@ -export const ENDPOINT_TEMPLATE: string = ` +export const ENDPOINT_TEMPLATE = `
@@ -13,12 +13,10 @@ export const ENDPOINT_TEMPLATE: string = `
- -
- - - -
+ + + + {{'DESTINATION.NAME' | translate}} {{'DESTINATION.URL' | translate}} @@ -28,15 +26,15 @@ export const ENDPOINT_TEMPLATE: string = ` {{t.name}} {{t.endpoint}} - - {{!t.insecure}} + + {{!t.insecure}} {{t.creation_time | date: 'short'}} - {{pagination.firstItem + 1}} - {{pagination.lastItem + 1}} {{'DESTINATION.OF' | translate}} - {{pagination.totalItems}} {{'DESTINATION.ITEMS' | translate}} - + {{pagination.firstItem + 1}} - {{pagination.lastItem + 1}} {{'DESTINATION.OF' | translate}} + {{pagination.totalItems}} {{'DESTINATION.ITEMS' | translate}} +
diff --git a/src/ui_ng/lib/src/list-replication-rule/list-replication-rule.component.html.ts b/src/ui_ng/lib/src/list-replication-rule/list-replication-rule.component.html.ts index 2609d09b7..834958f7d 100644 --- a/src/ui_ng/lib/src/list-replication-rule/list-replication-rule.component.html.ts +++ b/src/ui_ng/lib/src/list-replication-rule/list-replication-rule.component.html.ts @@ -1,13 +1,11 @@ export const LIST_REPLICATION_RULE_TEMPLATE: string = `
- -
- - - - -
+ + + + + {{'REPLICATION.NAME' | translate}} {{'REPLICATION.PROJECT' | translate}} diff --git a/src/ui_ng/lib/src/repository-listview/repository-listview.component.html.ts b/src/ui_ng/lib/src/repository-listview/repository-listview.component.html.ts index 77e935a80..41bce261f 100644 --- a/src/ui_ng/lib/src/repository-listview/repository-listview.component.html.ts +++ b/src/ui_ng/lib/src/repository-listview/repository-listview.component.html.ts @@ -13,9 +13,7 @@ export const REPOSITORY_LISTVIEW_TEMPLATE = `
-
- -
+
{{'REPOSITORY.NAME' | translate}} {{'REPOSITORY.TAGS_COUNT' | translate}} diff --git a/src/ui_ng/lib/src/repository/repository.component.html.ts b/src/ui_ng/lib/src/repository/repository.component.html.ts index 2bb443602..5ce94e6ba 100644 --- a/src/ui_ng/lib/src/repository/repository.component.html.ts +++ b/src/ui_ng/lib/src/repository/repository.component.html.ts @@ -24,7 +24,7 @@ export const REPOSITORY_TEMPLATE = `
- +
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 @@ - +
+ + + + {{'MEMBER.ACTION' | translate}} + + + + + + + + - -
- - {{'MEMBER.NEW_MEMBER' | translate }} - {{'MEMBER.DELETE' | translate}} - {{'MEMBER.PROJECT_ADMIN' | translate}} - {{'MEMBER.DEVELOPER' | translate}} - {{'MEMBER.GUEST' | translate}} - -
-
{{'MEMBER.NAME' | translate}} {{'MEMBER.ROLE' | translate}} {{m.username}} - {{roleInfo[m.role_id] | translate}} + + Loading... + {{roleInfo[m.role_id] | translate}} + {{pagination.firstItem + 1}} - {{pagination.lastItem +1 }} {{'MEMBER.OF' | translate}} diff --git a/src/ui_ng/src/app/project/member/member.component.ts b/src/ui_ng/src/app/project/member/member.component.ts index 01cba055a..0c9b1a457 100644 --- a/src/ui_ng/src/app/project/member/member.component.ts +++ b/src/ui_ng/src/app/project/member/member.component.ts @@ -11,39 +11,37 @@ // 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, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; -import { ActivatedRoute, Params, Router } from '@angular/router'; -import { Response } from '@angular/http'; +import { Component, OnInit, ViewChild, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef } from "@angular/core"; +import { ActivatedRoute, Router } from "@angular/router"; -import { SessionUser } from '../../shared/session-user'; -import { Member } from './member'; -import { MemberService } from './member.service'; +import { SessionUser } from "../../shared/session-user"; +import { Member } from "./member"; +import { MemberService } from "./member.service"; -import { AddMemberComponent } from './add-member/add-member.component'; +import { AddMemberComponent } from "./add-member/add-member.component"; -import { MessageHandlerService } from '../../shared/message-handler/message-handler.service'; -import { ConfirmationTargets, ConfirmationState, ConfirmationButtons } from '../../shared/shared.const'; +import { MessageHandlerService } from "../../shared/message-handler/message-handler.service"; +import { ConfirmationTargets, ConfirmationState, ConfirmationButtons } from "../../shared/shared.const"; -import { ConfirmationDialogService } from '../../shared/confirmation-dialog/confirmation-dialog.service'; -import { ConfirmationMessage } from '../../shared/confirmation-dialog/confirmation-message'; -import { SessionService } from '../../shared/session.service'; +import { ConfirmationDialogService } from "../../shared/confirmation-dialog/confirmation-dialog.service"; +import { ConfirmationMessage } from "../../shared/confirmation-dialog/confirmation-message"; +import { SessionService } from "../../shared/session.service"; -import { RoleInfo } from '../../shared/shared.const'; +import { RoleInfo } from "../../shared/shared.const"; -import { Observable } from 'rxjs/Observable'; -import 'rxjs/add/operator/switchMap'; -import 'rxjs/add/operator/catch'; -import 'rxjs/add/operator/map'; -import 'rxjs/add/observable/throw'; -import { Subscription } from 'rxjs/Subscription'; +import "rxjs/add/operator/switchMap"; +import "rxjs/add/operator/catch"; +import "rxjs/add/operator/map"; +import "rxjs/add/observable/throw"; +import { Subscription } from "rxjs/Subscription"; -import { Project } from '../../project/project'; +import { Project } from "../../project/project"; import {TranslateService} from "@ngx-translate/core"; import {BatchInfo, BathInfoChanges} from "../../shared/confirmation-dialog/confirmation-batch-message"; @Component({ - templateUrl: 'member.component.html', - styleUrls: ['./member.component.css'], + templateUrl: "member.component.html", + styleUrls: ["./member.component.css"], changeDetection: ChangeDetectionStrategy.OnPush }) export class MemberComponent implements OnInit, OnDestroy { @@ -60,22 +58,22 @@ export class MemberComponent implements OnInit, OnDestroy { hasProjectAdminRole: boolean; searchMember: string; - selectedRow: Member[] = [] + selectedRow: Member[] = []; roleNum: number; - isDelete: boolean =false; - isChangeRole: boolean =false; - batchDelectionInfos: BatchInfo[] = []; + isDelete = false; + isChangeRole = false; + batchActionInfos: BatchInfo[] = []; constructor( private route: ActivatedRoute, private router: Router, - private memberService: MemberService, + private memberService: MemberService, private translate: TranslateService, private messageHandlerService: MessageHandlerService, private OperateDialogService: ConfirmationDialogService, private session: SessionService, private ref: ChangeDetectorRef) { - + this.delSub = OperateDialogService.confirmationConfirm$.subscribe(message => { if (message && message.state === ConfirmationState.CONFIRMED && @@ -88,8 +86,8 @@ export class MemberComponent implements OnInit, OnDestroy { } } }); - let hnd = setInterval(()=>ref.markForCheck(), 100); - setTimeout(()=>clearInterval(hnd), 1000); + let hnd = setInterval(() => ref.markForCheck(), 100); + setTimeout(() => clearInterval(hnd), 1000); } retrieve(projectId: number, username: string) { @@ -99,11 +97,11 @@ export class MemberComponent implements OnInit, OnDestroy { .subscribe( response => { this.members = response; - let hnd = setInterval(()=>this.ref.markForCheck(), 100); - setTimeout(()=>clearInterval(hnd), 1000); + let hnd = setInterval(() => this.ref.markForCheck(), 100); + setTimeout(() => clearInterval(hnd), 1000); }, error => { - this.router.navigate(['/harbor', 'projects']); + this.router.navigate(["/harbor", "projects"]); this.messageHandlerService.handleError(error); }); } @@ -115,15 +113,15 @@ export class MemberComponent implements OnInit, OnDestroy { } ngOnInit() { - //Get projectId from route params snapshot. - this.projectId = +this.route.snapshot.parent.params['id']; - //Get current user from registered resolver. + // Get projectId from route params snapshot. + this.projectId = +this.route.snapshot.parent.params["id"]; + // Get current user from registered resolver. this.currentUser = this.session.getCurrentUser(); let resolverData = this.route.snapshot.parent.data; - if(resolverData) { - this.hasProjectAdminRole = (resolverData['projectResolver']).has_project_admin_role; + if (resolverData) { + this.hasProjectAdminRole = (resolverData["projectResolver"]).has_project_admin_role; } - this.retrieve(this.projectId, ''); + this.retrieve(this.projectId, ""); } openAddMemberModal() { @@ -131,8 +129,8 @@ export class MemberComponent implements OnInit, OnDestroy { } addedMember($event: any) { - this.searchMember = ''; - this.retrieve(this.projectId, ''); + this.searchMember = ""; + this.retrieve(this.projectId, ""); } changeRole(m: Member[], roleId: number) { @@ -141,24 +139,16 @@ export class MemberComponent implements OnInit, OnDestroy { this.isChangeRole = true; this.roleNum = roleId; let nameArr: string[] = []; - this.batchDelectionInfos = []; + this.batchActionInfos = []; m.forEach(data => { nameArr.push(data.username); let initBatchMessage = new BatchInfo(); initBatchMessage.name = data.username; - this.batchDelectionInfos.push(initBatchMessage); + this.batchActionInfos.push(initBatchMessage); }); - this.OperateDialogService.addBatchInfoList(this.batchDelectionInfos); + this.OperateDialogService.addBatchInfoList(this.batchActionInfos); - let switchMessage = new ConfirmationMessage( - 'MEMBER.SWITCH_TITLE', - 'MEMBER.SWITCH_SUMMARY', - nameArr.join(','), - m, - ConfirmationTargets.PROJECT_MEMBER, - ConfirmationButtons.SWITCH_CANCEL - ); - this.OperateDialogService.openComfirmDialog(switchMessage); + this.changeOpe(m); } } @@ -167,64 +157,66 @@ export class MemberComponent implements OnInit, OnDestroy { let promiseList: any[] = []; members.forEach(member => { if (member.user_id === this.currentUser.user_id) { - let findedList = this.batchDelectionInfos.find(data => data.name === member.username); - this.translate.get('BATCH.SWITCH_FAILURE').subscribe(res => { - findedList = BathInfoChanges(findedList, res, false, true); + let foundMember = this.batchActionInfos.find(batchInfo => batchInfo.name === member.username); + this.translate.get("BATCH.SWITCH_FAILURE").subscribe(res => { + this.messageHandlerService.handleError(res + ": " + foundMember.name); + foundMember = BathInfoChanges(foundMember, res, false, true); }); - }else { + } else { promiseList.push(this.changeOperate(this.projectId, member.user_id, this.roleNum, member.username)); } - }); Promise.all(promiseList).then(num => { - this.retrieve(this.projectId, ''); + this.retrieve(this.projectId, ""); }, ); } } changeOperate(projectId: number, memberId: number, roleId: number, username: string) { - let findedList = this.batchDelectionInfos.find(data => data.name === username); + let foundMember = this.batchActionInfos.find(batchInfo => batchInfo.name === username); return this.memberService .changeMemberRole(projectId, memberId, roleId) .then( response => { - this.translate.get('BATCH.SWITCH_SUCCESS').subscribe(res => { - findedList = BathInfoChanges(findedList, res); + this.translate.get("BATCH.SWITCH_SUCCESS").subscribe(res => { + foundMember = BathInfoChanges(foundMember, res); }); }, error => { - this.translate.get('BATCH.SWITCH_FAILURE').subscribe(res => { - findedList = BathInfoChanges(findedList, res, false, true); + this.translate.get("BATCH.SWITCH_FAILURE").subscribe(res => { + this.messageHandlerService.handleError(res + ": " + username); + foundMember = BathInfoChanges(foundMember, res, false, true); }); } ); } + ChangeRoleOngoing(username: string) { + if (this.batchActionInfos) { + let memberActionInfo = this.batchActionInfos.find(batchInfo => batchInfo.name === username); + return memberActionInfo && memberActionInfo.status === "pending"; + } else { + return false; + } + } + deleteMembers(m: Member[]) { this.isDelete = true; this.isChangeRole = false; let nameArr: string[] = []; - this.batchDelectionInfos = []; + this.batchActionInfos = []; if (m && m.length) { m.forEach(data => { nameArr.push(data.username); let initBatchMessage = new BatchInfo (); initBatchMessage.name = data.username; - this.batchDelectionInfos.push(initBatchMessage); + this.batchActionInfos.push(initBatchMessage); }); - this.OperateDialogService.addBatchInfoList(this.batchDelectionInfos); + this.OperateDialogService.addBatchInfoList(this.batchActionInfos); - let deletionMessage = new ConfirmationMessage( - 'MEMBER.DELETION_TITLE', - 'MEMBER.DELETION_SUMMARY', - nameArr.join(','), - m, - ConfirmationTargets.PROJECT_MEMBER, - ConfirmationButtons.DELETE_CANCEL - ); - this.OperateDialogService.openComfirmDialog(deletionMessage); + this.deleteMem(m); } } @@ -233,8 +225,8 @@ export class MemberComponent implements OnInit, OnDestroy { let promiseLists: any[] = []; members.forEach(member => { if (member.user_id === this.currentUser.user_id) { - let findedList = this.batchDelectionInfos.find(data => data.name === member.username); - this.translate.get('BATCH.DELETED_FAILURE').subscribe(res => { + let findedList = this.batchActionInfos.find(data => data.name === member.username); + this.translate.get("BATCH.DELETED_FAILURE").subscribe(res => { findedList = BathInfoChanges(findedList, res, false, true); }); }else { @@ -245,23 +237,23 @@ export class MemberComponent implements OnInit, OnDestroy { Promise.all(promiseLists).then(item => { this.selectedRow = []; - this.retrieve(this.projectId, ''); + this.retrieve(this.projectId, ""); }); } } delOperate(projectId: number, memberId: number, username: string) { - let findedList = this.batchDelectionInfos.find(data => data.name === username); + let findedList = this.batchActionInfos.find(data => data.name === username); return this.memberService .deleteMember(projectId, memberId) .then( response => { - this.translate.get('BATCH.DELETED_SUCCESS').subscribe(res => { + this.translate.get("BATCH.DELETED_SUCCESS").subscribe(res => { findedList = BathInfoChanges(findedList, res); }); }, error => { - this.translate.get('BATCH.DELETED_FAILURE').subscribe(res => { + this.translate.get("BATCH.DELETED_FAILURE").subscribe(res => { findedList = BathInfoChanges(findedList, res, false, true); }); } @@ -269,7 +261,7 @@ export class MemberComponent implements OnInit, OnDestroy { } SelectedChange(): void { - //this.forceRefreshView(5000); + // this.forceRefreshView(5000); } doSearch(searchMember: string) { @@ -278,6 +270,6 @@ export class MemberComponent implements OnInit, OnDestroy { } refresh() { - this.retrieve(this.projectId, ''); + this.retrieve(this.projectId, ""); } } \ No newline at end of file diff --git a/src/ui_ng/src/app/project/project.component.html b/src/ui_ng/src/app/project/project.component.html index f4b4c9781..7b76a8678 100644 --- a/src/ui_ng/src/app/project/project.component.html +++ b/src/ui_ng/src/app/project/project.component.html @@ -10,10 +10,10 @@
+ + + +
diff --git a/src/ui_ng/src/app/shared/confirmation-dialog/confirmation-batch-message.ts b/src/ui_ng/src/app/shared/confirmation-dialog/confirmation-batch-message.ts index b4b160ee1..42b7cc24d 100644 --- a/src/ui_ng/src/app/shared/confirmation-dialog/confirmation-batch-message.ts +++ b/src/ui_ng/src/app/shared/confirmation-dialog/confirmation-batch-message.ts @@ -10,10 +10,10 @@ export class BatchInfo { errorState: boolean; errorInfo: string; constructor() { - this.status = 'pending'; + this.status = "pending"; this.loading = false; this.errorState = false; - this.errorInfo = ''; + this.errorInfo = ""; } } diff --git a/src/ui_ng/src/app/shared/confirmation-dialog/confirmation-dialog.component.ts b/src/ui_ng/src/app/shared/confirmation-dialog/confirmation-dialog.component.ts index 1db093bda..8969e8720 100644 --- a/src/ui_ng/src/app/shared/confirmation-dialog/confirmation-dialog.component.ts +++ b/src/ui_ng/src/app/shared/confirmation-dialog/confirmation-dialog.component.ts @@ -113,7 +113,7 @@ export class ConfirmationDialogComponent implements OnDestroy { } operate(): void { - if(!this.message){//Inproper condition + if (!this.message) {// Improper condition this.close(); return; } diff --git a/src/ui_ng/src/app/shared/statictics/statistics-panel.component.ts b/src/ui_ng/src/app/shared/statictics/statistics-panel.component.ts index 9edfeb3f9..3d172d0a6 100644 --- a/src/ui_ng/src/app/shared/statictics/statistics-panel.component.ts +++ b/src/ui_ng/src/app/shared/statictics/statistics-panel.component.ts @@ -11,22 +11,24 @@ // 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, Input, OnInit, OnDestroy } from '@angular/core'; -import { Subscription } from 'rxjs/Subscription'; +import { Component, Input, OnInit, OnDestroy } from "@angular/core"; +import { Subscription } from "rxjs/Subscription"; -import { StatisticsService } from './statistics.service'; -import { Statistics } from './statistics'; +import { StatisticsService } from "./statistics.service"; +import { Statistics } from "./statistics"; -import { SessionService } from '../session.service'; -import { Volumes } from './volumes'; +import { SessionService } from "../session.service"; +import { Volumes } from "./volumes"; + +import { MessageHandlerService } from "../message-handler/message-handler.service"; +import { StatisticHandler } from "./statistic-handler.service"; +import { AppConfigService } from "./../../app-config.service"; -import { MessageHandlerService } from '../message-handler/message-handler.service'; -import { StatisticHandler } from './statistic-handler.service'; @Component({ - selector: 'statistics-panel', + selector: "statistics-panel", templateUrl: "statistics-panel.component.html", - styleUrls: ['statistics.component.css'], + styleUrls: ["statistics.component.css"], providers: [StatisticsService] }) @@ -36,16 +38,17 @@ export class StatisticsPanelComponent implements OnInit, OnDestroy { volumesInfo: Volumes = new Volumes(); refreshSub: Subscription; small: number; - + constructor( private statistics: StatisticsService, private msgHandler: MessageHandlerService, private session: SessionService, + private appConfigService: AppConfigService, private statisticHandler: StatisticHandler) { } ngOnInit(): void { - //Refresh + // Refresh this.refreshSub = this.statisticHandler.refreshChan$.subscribe(clear => { this.getStatistics(); }); @@ -95,7 +98,8 @@ export class StatisticsPanelComponent implements OnInit, OnDestroy { } public get isValidStorage(): boolean { - return this.volumesInfo.storage.total != 0; + return this.volumesInfo.storage.total !== 0 && + this.appConfigService.getConfig().registry_storage_provider_name === "filesystem"; } getGBFromBytes(bytes: number): number { diff --git a/src/ui_ng/src/app/user/user.component.html b/src/ui_ng/src/app/user/user.component.html index c7697d4d5..fe8abb160 100644 --- a/src/ui_ng/src/app/user/user.component.html +++ b/src/ui_ng/src/app/user/user.component.html @@ -11,11 +11,9 @@
-
- - - -
+ + +
{{'USER.COLUMN_NAME' | translate}} {{'USER.COLUMN_ADMIN' | translate}} 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 9f97b4449..c4502fa6b 100644 --- a/src/ui_ng/src/i18n/lang/en-us-lang.json +++ b/src/ui_ng/src/i18n/lang/en-us-lang.json @@ -119,8 +119,8 @@ }, "USER": { "ADD_ACTION": "New User", - "ENABLE_ADMIN_ACTION": "Set as Administrator", - "DISABLE_ADMIN_ACTION": "Revoke Administrator", + "ENABLE_ADMIN_ACTION": "SET AS ADMIN", + "DISABLE_ADMIN_ACTION": "REVOKE ADMIN", "DEL_ACTION": "Delete", "FILTER_PLACEHOLDER": "Filter users", "COLUMN_NAME": "Name", @@ -219,7 +219,9 @@ "SWITCHED_SUCCESS": "Switched member role successfully.", "OF": "of", "SWITCH_TITLE": "Confirm project members switch", - "SWITCH_SUMMARY": "Do you want to switch project members {{param}}?" + "SWITCH_SUMMARY": "Do you want to switch project members {{param}}?", + "ACTION": "SET ROLE", + "REMOVE": "REMOVE" }, "AUDIT_LOG": { "USERNAME": "Username", 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 2bccd8aad..38052a222 100644 --- a/src/ui_ng/src/i18n/lang/es-es-lang.json +++ b/src/ui_ng/src/i18n/lang/es-es-lang.json @@ -219,7 +219,9 @@ "SWITCHED_SUCCESS": "Rol del miembro cambiado satisfactoriamente.", "OF": "of", "SWITCH_TITLE": "Confirm project members switch", - "SWITCH_SUMMARY": "Do you want to switch project members {{param}}?" + "SWITCH_SUMMARY": "Do you want to switch project members {{param}}?", + "ACTION": "SET ROLE", + "REMOVE": "REMOVE" }, "AUDIT_LOG": { "USERNAME": "Nombre de usuario", 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 21d154e75..b1994204d 100644 --- a/src/ui_ng/src/i18n/lang/zh-cn-lang.json +++ b/src/ui_ng/src/i18n/lang/zh-cn-lang.json @@ -219,7 +219,9 @@ "SWITCHED_SUCCESS": "切换角色成功。", "OF": "共计", "SWITCH_TITLE": "切换项目成员确认", - "SWITCH_SUMMARY": "你确认切换项目成员 {{param}}??" + "SWITCH_SUMMARY": "你确认切换项目成员 {{param}}??", + "ACTION": "设置角色", + "REMOVE": "移除成员" }, "AUDIT_LOG": { "USERNAME": "用户名", diff --git a/tests/resources/Harbor-Pages/Administration-Users.robot b/tests/resources/Harbor-Pages/Administration-Users.robot index a2284b129..d12e70dbd 100644 --- a/tests/resources/Harbor-Pages/Administration-Users.robot +++ b/tests/resources/Harbor-Pages/Administration-Users.robot @@ -28,7 +28,7 @@ Assign User Admin #select checkbox Click Element //clr-dg-row[contains(.,"${user}")]//label #click assign admin - Click Element //button[contains(.,'Set as')] + Click Element //*[@id="set-admin"] Sleep 1 Switch to User Tag diff --git a/tests/resources/Harbor-Pages/Project-Members.robot b/tests/resources/Harbor-Pages/Project-Members.robot index ddd895c1c..3bf3dabec 100644 --- a/tests/resources/Harbor-Pages/Project-Members.robot +++ b/tests/resources/Harbor-Pages/Project-Members.robot @@ -67,13 +67,8 @@ Change Project Member Role Click Element xpath=//project-detail//clr-dg-row[contains(.,'${user}')]//label Sleep 1 #change role - Click Element //button[@class='btn dropdown-toggle'] + Click Element //*[@id="member-action"] Click Element //button[contains(.,'${role}')] - sleep 1 - Click Element xpath=//clr-modal//button[contains(.,'SWITCH')] - sleep 1 - Click Element xpath=//clr-modal//button[contains(.,'CLOSE')] - Sleep 2 Wait Until Page Contains ${role} @@ -112,10 +107,7 @@ Delete Project Member [arguments] ${member} Click Element xpath=//clr-dg-row[contains(.,'${member}')]//input/../label Click Element xpath=${project_member_delete_button_xpath} - Sleep 1 - Click Element xpath=${project_member_delete_confirmation_xpath} - Sleep 1 - Click Element xpath=//button[contains(.,'CLOSE')] + Sleep 2 User Should Be Owner Of Project [Arguments] ${user} ${pwd} ${project} diff --git a/tests/resources/Harbor-Pages/Project-Members_Elements.robot b/tests/resources/Harbor-Pages/Project-Members_Elements.robot index 755e71845..36f1e48da 100644 --- a/tests/resources/Harbor-Pages/Project-Members_Elements.robot +++ b/tests/resources/Harbor-Pages/Project-Members_Elements.robot @@ -27,5 +27,4 @@ ${project_member_add_confirmation_ok_xpath} //project-detail//add-member//butto ${project_member_search_button_xpath2} //button[contains(.,'New')] ${project_member_add_button_xpath2} //project-detail//add-member//button[2] ${project_member_guest_radio_checkbox} //project-detail//form//input[@id='checkrads_guest'] -${project_member_delete_button_xpath} //button[contains(.,"Delete")] -${project_member_delete_confirmation_xpath} //confiramtion-dialog//button[2] +${project_member_delete_button_xpath} //button[contains(.,"Delete")] \ No newline at end of file diff --git a/tests/resources/Harbor-Pages/Project.robot b/tests/resources/Harbor-Pages/Project.robot index b6dbbf455..fa6fd167f 100644 --- a/tests/resources/Harbor-Pages/Project.robot +++ b/tests/resources/Harbor-Pages/Project.robot @@ -82,8 +82,6 @@ Make Project Private Go Into Project ${project name} Sleep 1 Click Element xpath=//project-detail//a[contains(.,'Configuration')] - #Click element xpath=//project//list-project//clr-dg-row-master[contains(.,'${projectname}')]//clr-dg-action-overflow - #Click element xpath=//project//list-project//clr-dg-action-overflow//button[contains(.,"Make Private")] Checkbox Should Be Selected xpath=//input[@name='public'] Click Element //clr-checkbox[@name='public']//label Click Element //button[contains(.,'SAVE')] @@ -93,15 +91,12 @@ Make Project Public Go Into Project ${project name} Sleep 1 Click Element xpath=//project-detail//a[contains(.,'Configuration')] - #Click element xpath=//project//list-project//clr-dg-row-master[contains(.,'${projectname}')]//clr-dg-action-overflow - #Click element xpath=//project//list-project//clr-dg-action-overflow//button[contains(.,"Make Public")] Checkbox Should Not Be Selected xpath=//input[@name='public'] Click Element //clr-checkbox[@name='public']//label Click Element //button[contains(.,'SAVE')] Delete Repo [Arguments] ${projectname} - #Click Element xpath=//project-detail//clr-dg-row-master[contains(.,"${projectname}")]//clr-dg-action-overflow Click Element xpath=//clr-dg-row[contains(.,"${projectname}")]//clr-checkbox//label Sleep 1 Click Element xpath=//button[contains(.,"Delete")] @@ -113,16 +108,10 @@ Delete Repo Delete Project [Arguments] ${projectname} Sleep 1 - #Click Element //list-project//clr-dg-row-master[contains(.,'${projname}')]//clr-dg-action-overflow - #Click Element //list-project//clr-dg-row-master[contains(.,'${projname}')]//clr-dg-action-overflow//button[contains(.,'Delete')] - #click delete button to confirm Click Element xpath=//clr-dg-row[contains(.,"${projectname}")]//clr-checkbox//label Sleep 1 Click Element xpath=//button[contains(.,"Delete")] - Sleep 1 - Click Element xpath=//clr-modal//button[2] - Sleep 1 - Click Element xpath=//button[contains(.,"CLOSE")] + Sleep 2 Project Should Not Be Deleted [Arguments] ${projname} @@ -205,8 +194,6 @@ Expand Repo Scan Repo [Arguments] ${tagname} - #Click Element //hbr-tag//clr-dg-row-master[contains(.,'${tagname}')]//clr-dg-action-overflow - #Click Element //hbr-tag//clr-dg-row-master[contains(.,'${tagname}')]//clr-dg-action-overflow//button[contains(.,'Scan')] #select one tag Click Element //clr-dg-row[contains(.,"${tagname}")]//label Click Element //button[contains(.,'Scan')] diff --git a/tests/resources/Harbor-Pages/ToolKit.robot b/tests/resources/Harbor-Pages/ToolKit.robot index bdd61afb0..ed5bf9b8a 100644 --- a/tests/resources/Harbor-Pages/ToolKit.robot +++ b/tests/resources/Harbor-Pages/ToolKit.robot @@ -52,5 +52,13 @@ Multi-delete Object Click Element //clr-modal//button[contains(.,'DELETE')] Sleep 3 +Multi-delete Object Without Confirmation + [Arguments] @{obj} + :For ${obj} in @{obj} + \ Click Element //clr-dg-row[contains(.,'${obj}')]//label + Sleep 1 + Click Element //button[contains(.,'Delete')] + Sleep 3 + Select All On Current Page Object Click Element //div[@class='datagrid-head']//label diff --git a/tests/robot-cases/Group11-Nightly/Nightly.robot b/tests/robot-cases/Group11-Nightly/Nightly.robot index c20dcd41f..2a53a8a55 100644 --- a/tests/robot-cases/Group11-Nightly/Nightly.robot +++ b/tests/robot-cases/Group11-Nightly/Nightly.robot @@ -149,10 +149,10 @@ Test Case - Project Level Policy Public Goto Project Config Click Project Public Save Project Config - #verify + # Verify Public Should Be Selected Back To Projects - #project${d} default should be private + # Project${d} default should be private Project Should Be Public project${d} Close Browser @@ -166,13 +166,13 @@ Test Case - Project Level Policy Content Trust Goto Project Config Click Content Trust Save Project Config - #verify + # Verify Content Trust Should Be Selected Cannot Pull Unsigned Image ${ip} ${HARBOR_ADMIN} ${HARBOR_PASSWORD} project${d} hello-world:latest Close Browser Test Case - Edit Project Creation - # create normal user and login + # Create normal user and login Init Chrome Driver ${d}= Get Current Date result_format=%m%s Create An New User url=${HARBOR_URL} username=tester${d} email=tester${d}@vmware.com realname=harbortest newPassword=Test1@34 comment=harbortest @@ -206,7 +206,7 @@ Test Case - Edit Self-Registration Self Reg Should Be Disabled Sleep 1 - #restore setting + # Restore setting Enable Self Reg Close Browser @@ -259,7 +259,7 @@ Test Case - Scan A Tag In The Repo Go Into Repo project${d}/hello-world Scan Repo latest Summary Chart Should Display latest - #Edit Repo Info + # Edit Repo Info Close Browser Test Case - Manage Project Member @@ -307,9 +307,8 @@ Test Case - Delete Multi Project Create An New Project projectb${d} Push Image ${ip} test${d} Test1@34 projecta${d} hello-world Filter Object project - Multi-delete Object projecta projectb - #verify delete project with image should not be deleted directly - Partly Success + Multi-delete Object Without Confirmation projecta projectb + # Verify delete project with image should not be deleted directly Page Should Contain projecta${d} Page Should Not Contain projectb${d} Close Browser @@ -327,11 +326,11 @@ Test Case - Delete Multi User Switch To User Tag Filter Object delete Multi-delete Object deletea deleteb deletec - #assert delete - #Delete Success comment temp wait for fixing + # Assert delete + # Delete Success comment temp wait for fixing Click Element //clr-modal//button[contains(.,'CLOSE')] Sleep 1 - #filter object delete + # Filter object delete Page Should Not Contain deletea Close Browser @@ -345,7 +344,7 @@ Test Case - Delete Multi Repo Sleep 2 Go Into Project project${d} Multi-delete Object hello-world busybox - #verify + # Verify Delete Success Close Browser @@ -360,7 +359,7 @@ Test Case - Delete Multi Tag Go Into Project project${d} Go Into Repo hello-world Multi-delete object latest v1 - #verify + # Verify Delete Success Close Browser @@ -377,8 +376,7 @@ Test Case - Delete Multi Member Switch To Member Add Guest Member to project testa${d} Add Guest Member to project testb${d} - Multi-delete Object testa${d} testb${d} - Delete Success + Multi-delete Object Without Confirmation testa${d} testb${d} Page Should Not Contain testa${d} Close Browser