Merge remote-tracking branch 'upstream/master' into batchDelection

This commit is contained in:
pfh 2018-01-30 11:45:26 +08:00
commit 5e14601d2e
13 changed files with 71 additions and 30 deletions

View File

@ -17,9 +17,25 @@ In addition, the deployment instructions on Kubernetes has been created by the c
## Prerequisites for the target host
Harbor is deployed as several Docker containers, and, therefore, can be deployed on any Linux distribution that supports Docker. The target host requires Python, Docker, and Docker Compose to be installed.
* Python should be version 2.7 or higher. Note that you may have to install Python on Linux distributions (Gentoo, Arch) that do not come with a Python interpreter installed by default
* Docker engine should be version 1.10 or higher. For installation instructions, please refer to: https://docs.docker.com/engine/installation/
* Docker Compose needs to be version 1.6.0 or higher. For installation instructions, please refer to: https://docs.docker.com/compose/install/
### Hardware
|Resource|Capacity|Description|
|---|---|---|
|CPU|minimal 2 CPU|4 CPU is prefered|
|Mem|minimal 4GB|8GB is prefered|
|Disk|minimal 40GB|160GB is prefered|
### Software
|Software|Version|Description|
|---|---|---|
|Python|version 2.7 or higher|Note that you may have to install Python on Linux distributions (Gentoo, Arch) that do not come with a Python interpreter installed by default|
|Docker engine|version 1.10 or higher|For installation instructions, please refer to: https://docs.docker.com/engine/installation/|
|Docker Compose|version 1.6.0 or higher|For installation instructions, please refer to: https://docs.docker.com/compose/install/|
|Openssl|latest is prefered|Generate certificate and keys for Harbor|
### Network ports
|Port|Protocol|Description|
|---|---|---|
|443|HTTPS|Harbor UI and API will accept requests on this port for https protocol|
|4443|HTTS|Connections to the Docker Content Trust service for Harbor, only needed when Notary is enabled|
|80|HTTP|Harbor UI and API will accept requests on this port for http protocol|
## Installation Steps

View File

@ -1,6 +1,6 @@
{
"name": "harbor-ui",
"version": "0.6.30",
"version": "0.6.41",
"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",

View File

@ -1,6 +1,6 @@
{
"name": "harbor-ui",
"version": "0.6.30",
"version": "0.6.41",
"description": "Harbor shared UI components based on Clarity and Angular4",
"author": "VMware",
"module": "index.js",

View File

@ -0,0 +1,2 @@
export const LIST_REPLICATION_RULE_CSS = `
`

View File

@ -18,7 +18,15 @@ export const LIST_REPLICATION_RULE_TEMPLATE: string = `
<clr-dg-cell *ngIf="!projectScope">
<a href="javascript:void(0)" (click)="redirectTo(p)">{{p.projects?.length>0 ? p.projects[0].name : ''}}</a>
</clr-dg-cell>
<clr-dg-cell>{{p.description ? p.description : '-'}}</clr-dg-cell>
<clr-dg-cell>
{{p.description ? trancatedDescription(p.description) : '-'}}
<clr-tooltip>
<clr-icon *ngIf="p.description && p.description.length > 35" clrTooltipTrigger shape="ellipsis-horizontal" size="18"></clr-icon>
<clr-tooltip-content clrPosition="bottom-right" clrSize="md" *clrIfOpen>
<span>{{p.description}}</span>
</clr-tooltip-content>
</clr-tooltip>
</clr-dg-cell>
<clr-dg-cell>{{p.targets?.length>0 ? p.targets[0].name : ''}}</clr-dg-cell>
<clr-dg-cell>{{p.trigger ? p.trigger.kind : ''}}</clr-dg-cell>
</clr-dg-row>

View File

@ -42,12 +42,14 @@ import { toPromise, CustomComparator } from '../utils';
import { State, Comparator } from 'clarity-angular';
import { LIST_REPLICATION_RULE_TEMPLATE } from './list-replication-rule.component.html';
import { LIST_REPLICATION_RULE_CSS } from './list-replication-rule.component.css';
import {BatchInfo, BathInfoChanges} from "../confirmation-dialog/confirmation-batch-message";
import {Observable} from "rxjs/Observable";
@Component({
selector: 'hbr-list-replication-rule',
template: LIST_REPLICATION_RULE_TEMPLATE,
styles: [LIST_REPLICATION_RULE_CSS],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class ListReplicationRuleComponent implements OnInit, OnChanges {
@ -102,6 +104,14 @@ export class ListReplicationRuleComponent implements OnInit, OnChanges {
return !this.readonly && !this.projectId ? true : false;
}
trancatedDescription(desc: string): string {
if (desc.length > 35 ) {
return desc.substr(0, 35);
} else {
return desc;
}
}
ngOnInit(): void {
//Global scope
if (!this.projectScope) {

View File

@ -24,11 +24,9 @@ export const TAG_TEMPLATE = `
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<clr-datagrid [clrDgLoading]="loading" [class.embeded-datagrid]="isEmbedded" [(clrDgSelected)]="selectedRow" (clrDgSelectedChange)="selectedChange()">
<clr-dg-action-bar>
<div class="btn-group">
<button type="button" class="btn btn-sm btn-secondary" [disabled]="!(canScanNow(selectedRow) && selectedRow.length==1)" (click)="scanNow(selectedRow)">{{'VULNERABILITY.SCAN_NOW' | translate}}</button>
<button type="button" class="btn btn-sm btn-secondary" [disabled]="!(selectedRow.length==1)" (click)="showDigestId(selectedRow)" >{{'REPOSITORY.COPY_DIGEST_ID' | translate}}</button>
<button type="button" class="btn btn-sm btn-secondary" *ngIf="hasProjectAdminRole" (click)="deleteTags(selectedRow)" [disabled]="!selectedRow.length">{{'REPOSITORY.DELETE' | translate}}</button>
</div>
<button type="button" class="btn btn-sm btn-secondary" [disabled]="!(canScanNow(selectedRow) && selectedRow.length==1)" (click)="scanNow(selectedRow)"><clr-icon shape="shield-check" size="16"></clr-icon>&nbsp;{{'VULNERABILITY.SCAN_NOW' | translate}}</button>
<button type="button" class="btn btn-sm btn-secondary" [disabled]="!(selectedRow.length==1)" (click)="showDigestId(selectedRow)" ><clr-icon shape="copy" size="16"></clr-icon>&nbsp;{{'REPOSITORY.COPY_DIGEST_ID' | translate}}</button>
<button type="button" class="btn btn-sm btn-secondary" *ngIf="hasProjectAdminRole" (click)="deleteTags(selectedRow)" [disabled]="!selectedRow.length"><clr-icon shape="times" size="16"></clr-icon>&nbsp;{{'REPOSITORY.DELETE' | translate}}</button>
</clr-dg-action-bar>
<clr-dg-column style="width: 160px;" [clrDgField]="'name'">{{'REPOSITORY.TAG' | translate}}</clr-dg-column>
<clr-dg-column style="width: 90px;" [clrDgField]="'size'">{{'REPOSITORY.SIZE' | translate}}</clr-dg-column>

View File

@ -69,11 +69,6 @@
"check-else",
"check-whitespace"
],
"quotemark": [
true,
"double",
"avoid-escape"
],
"radix": true,
"semicolon": [
"always"

View File

@ -31,7 +31,7 @@
"clarity-icons": "^0.10.17",
"clarity-ui": "^0.10.17",
"core-js": "^2.4.1",
"harbor-ui": "0.6.37",
"harbor-ui": "0.6.41",
"intl": "^1.2.5",
"mutationobserver-shim": "^0.3.2",
"ngx-cookie": "^1.0.0",

View File

@ -12,7 +12,7 @@
<clr-icon clrTooltipTrigger shape="info-circle" size="24"></clr-icon>
</button>
<clr-tooltip-content clrPosition="bottom-left" clrSize="md" *clrIfOpen>
<span (click)="openRenameAlert()"> {{'PROFILE.ADMIN_RENAME_TIP'}}</span>
<span (click)="openRenameAlert()"> {{'PROFILE.ADMIN_RENAME_TIP' | translate}}</span>
</clr-tooltip-content>
</clr-tooltip>
</div>

View File

@ -221,7 +221,15 @@ export class ListProjectComponent implements OnDestroy {
this.batchDelectionInfos.push(initBatchMessage);
});
this.deletionDialogService.addBatchInfoList(this.batchDelectionInfos);
this.delProjects(p);
let deletionMessage = new ConfirmationMessage(
"PROJECT.DELETION_TITLE",
"PROJECT.DELETION_SUMMARY",
nameArr.join(","),
p,
ConfirmationTargets.PROJECT,
ConfirmationButtons.DELETE_CANCEL
);
this.deletionDialogService.openComfirmDialog(deletionMessage);
}
}
delProjects(projects: Project[]) {

View File

@ -63,6 +63,7 @@ export class MemberComponent implements OnInit, OnDestroy {
isDelete = false;
isChangeRole = false;
batchActionInfos: BatchInfo[] = [];
batchDeletionInfos: BatchInfo[] = [];
constructor(
private route: ActivatedRoute,
@ -206,17 +207,25 @@ export class MemberComponent implements OnInit, OnDestroy {
this.isDelete = true;
this.isChangeRole = false;
let nameArr: string[] = [];
this.batchActionInfos = [];
this.batchDeletionInfos = [];
if (m && m.length) {
m.forEach(data => {
nameArr.push(data.username);
let initBatchMessage = new BatchInfo ();
initBatchMessage.name = data.username;
this.batchActionInfos.push(initBatchMessage);
this.batchDeletionInfos.push(initBatchMessage);
});
this.OperateDialogService.addBatchInfoList(this.batchActionInfos);
this.OperateDialogService.addBatchInfoList(this.batchDeletionInfos);
this.deleteMem(m);
let deletionMessage = new ConfirmationMessage(
"MEMBER.DELETION_TITLE",
"MEMBER.DELETION_SUMMARY",
nameArr.join(","),
m,
ConfirmationTargets.PROJECT_MEMBER,
ConfirmationButtons.DELETE_CANCEL
);
this.OperateDialogService.openComfirmDialog(deletionMessage);
}
}
@ -225,7 +234,7 @@ export class MemberComponent implements OnInit, OnDestroy {
let promiseLists: any[] = [];
members.forEach(member => {
if (member.user_id === this.currentUser.user_id) {
let findedList = this.batchActionInfos.find(data => data.name === member.username);
let findedList = this.batchDeletionInfos.find(data => data.name === member.username);
this.translate.get("BATCH.DELETED_FAILURE").subscribe(res => {
findedList = BathInfoChanges(findedList, res, false, true);
});
@ -243,7 +252,7 @@ export class MemberComponent implements OnInit, OnDestroy {
}
delOperate(projectId: number, memberId: number, username: string) {
let findedList = this.batchActionInfos.find(data => data.name === username);
let findedList = this.batchDeletionInfos.find(data => data.name === username);
return this.memberService
.deleteMember(projectId, memberId)
.then(

View File

@ -69,11 +69,6 @@
"check-else",
"check-whitespace"
],
"quotemark": [
true,
"double",
"avoid-escape"
],
"radix": true,
"semicolon": [
true