mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-16 23:35:20 +01:00
Add async task progress and delete dialog task progress #4371
norm code
This commit is contained in:
parent
c2c667c6d6
commit
1121c8a76b
17
src/ui_ng/lib/src/_animations/fade-in.animation.ts
Normal file
17
src/ui_ng/lib/src/_animations/fade-in.animation.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// import the required animation functions from the angular animations module
|
||||||
|
import {AnimationTriggerMetadata, trigger, animate, transition, style } from '@angular/animations';
|
||||||
|
|
||||||
|
export const FadeInAnimation: AnimationTriggerMetadata =
|
||||||
|
// trigger name for attaching this animation to an element using the [@triggerName] syntax
|
||||||
|
trigger('FadeInAnimation', [
|
||||||
|
|
||||||
|
// route 'enter' transition
|
||||||
|
transition(':enter', [
|
||||||
|
|
||||||
|
// css styles at start of transition
|
||||||
|
style({ opacity: 0 }),
|
||||||
|
|
||||||
|
// animation and styles at end of transition
|
||||||
|
animate('.3s', style({ opacity: 1 }))
|
||||||
|
]),
|
||||||
|
]);
|
2
src/ui_ng/lib/src/_animations/index.ts
Normal file
2
src/ui_ng/lib/src/_animations/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from './fade-in.animation';
|
||||||
|
export * from './slide-in-out.animation';
|
47
src/ui_ng/lib/src/_animations/slide-in-out.animation.ts
Normal file
47
src/ui_ng/lib/src/_animations/slide-in-out.animation.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// import the required animation functions from the angular animations module
|
||||||
|
import {AnimationTriggerMetadata, trigger, state, animate, transition, style } from '@angular/animations';
|
||||||
|
|
||||||
|
export const SlideInOutAnimation: AnimationTriggerMetadata =
|
||||||
|
// trigger name for attaching this animation to an element using the [@triggerName] syntax
|
||||||
|
trigger('SlideInOutAnimation', [
|
||||||
|
|
||||||
|
// end state styles for route container (host)
|
||||||
|
state('in', style({
|
||||||
|
// the view covers the whole screen with a semi tranparent background
|
||||||
|
position: 'fix',
|
||||||
|
right: 0,
|
||||||
|
width: '350px',
|
||||||
|
bottom: 0
|
||||||
|
// backgroundColor: 'rgba(0, 0, 0, 0.8)'
|
||||||
|
})),
|
||||||
|
state('out', style({
|
||||||
|
// the view covers the whole screen with a semi tranparent background
|
||||||
|
position: 'fix',
|
||||||
|
width: '30px',
|
||||||
|
bottom: 0
|
||||||
|
// backgroundColor: 'rgba(0, 0, 0, 0.8)'
|
||||||
|
})),
|
||||||
|
// route 'enter' transition
|
||||||
|
transition('out => in', [
|
||||||
|
// animation and styles at end of transition
|
||||||
|
animate('.5s ease-in-out', style({
|
||||||
|
// transition the right position to 0 which slides the content into view
|
||||||
|
width: '350px',
|
||||||
|
|
||||||
|
// transition the background opacity to 0.8 to fade it in
|
||||||
|
// backgroundColor: 'rgba(0, 0, 0, 0.8)'
|
||||||
|
}))
|
||||||
|
]),
|
||||||
|
|
||||||
|
// route 'leave' transition
|
||||||
|
transition('in => out', [
|
||||||
|
// animation and styles at end of transition
|
||||||
|
animate('.5s ease-in-out', style({
|
||||||
|
// transition the right position to -400% which slides the content out of view
|
||||||
|
width: '30px',
|
||||||
|
|
||||||
|
// transition the background opacity to 0 to fade it out
|
||||||
|
// backgroundColor: 'rgba(0, 0, 0, 0)'
|
||||||
|
}))
|
||||||
|
])
|
||||||
|
]);
|
@ -5,19 +5,6 @@
|
|||||||
<clr-icon shape="warning" class="is-warning" size="64"></clr-icon>
|
<clr-icon shape="warning" class="is-warning" size="64"></clr-icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="confirmation-content">{{dialogContent}}</div>
|
<div class="confirmation-content">{{dialogContent}}</div>
|
||||||
<div>
|
|
||||||
<ul class="batchInfoUl">
|
|
||||||
<li *ngFor="let info of batchInfors">
|
|
||||||
<span><i class="spinner spinner-inline spinner-pos" [hidden]='!info.loading'></i> {{info.name}}</span>
|
|
||||||
<span *ngIf="!info.errorInfo.length" [style.color]="colorChange(info)">{{info.status}}</span>
|
|
||||||
<span *ngIf="info.errorInfo.length" [style.color]="colorChange(info)">
|
|
||||||
<a (click)="toggleErrorTitle(errorInfo)">{{info.status}}</a>
|
|
||||||
<br>
|
|
||||||
<i #errorInfo style="display: none;">{{info.errorInfo}}</i>
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer" [ngSwitch]="buttons">
|
<div class="modal-footer" [ngSwitch]="buttons">
|
||||||
<ng-template [ngSwitchCase]="0">
|
<ng-template [ngSwitchCase]="0">
|
||||||
@ -30,16 +17,14 @@
|
|||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template [ngSwitchCase]="2">
|
<ng-template [ngSwitchCase]="2">
|
||||||
<button type="button" class="btn btn-outline" (click)="cancel()" [hidden]="isDelete">{{'BUTTON.CANCEL' | translate}}</button>
|
<button type="button" class="btn btn-outline" (click)="cancel()" [hidden]="isDelete">{{'BUTTON.CANCEL' | translate}}</button>
|
||||||
<button type="button" class="btn btn-danger" (click)="operate()" [hidden]="isDelete">{{'BUTTON.DELETE' | translate}}</button>
|
<button type="button" class="btn btn-danger" (click)="confirm()" [hidden]="isDelete">{{'BUTTON.DELETE' | translate}}</button>
|
||||||
<button type="button" class="btn btn-primary" (click)="cancel()" [disabled]="!batchOverStatus" [hidden]="!isDelete">{{'BUTTON.CLOSE' | translate}}</button>
|
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template [ngSwitchCase]="3">
|
<ng-template [ngSwitchCase]="3">
|
||||||
<button type="button" class="btn btn-primary" (click)="cancel()">{{'BUTTON.CLOSE' | translate}}</button>
|
<button type="button" class="btn btn-primary" (click)="cancel()">{{'BUTTON.CLOSE' | translate}}</button>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template [ngSwitchCase]="4">
|
<ng-template [ngSwitchCase]="4">
|
||||||
<button type="button" class="btn btn-outline" (click)="cancel()" [hidden]="isDelete">{{'BUTTON.CANCEL' | translate}}</button>
|
<button type="button" class="btn btn-outline" (click)="cancel()" [hidden]="isDelete">{{'BUTTON.CANCEL' | translate}}</button>
|
||||||
<button type="button" class="btn btn-primary" (click)="operate()" [hidden]="isDelete">{{'BUTTON.REPLICATE' | translate}}</button>
|
<button type="button" class="btn btn-primary" (click)="confirm()" [hidden]="isDelete">{{'BUTTON.REPLICATE' | translate}}</button>
|
||||||
<button type="button" class="btn btn-primary" (click)="cancel()" [disabled]="!batchOverStatus" [hidden]="!isDelete">{{'BUTTON.CLOSE' | translate}}</button>
|
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</div>
|
</div>
|
||||||
</clr-modal>
|
</clr-modal>
|
@ -11,7 +11,7 @@
|
|||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
import {Component, EventEmitter, Input, Output} from '@angular/core';
|
import {Component, EventEmitter, Output} from '@angular/core';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
|
|
||||||
import { ConfirmationMessage } from './confirmation-message';
|
import { ConfirmationMessage } from './confirmation-message';
|
||||||
@ -35,7 +35,6 @@ export class ConfirmationDialogComponent {
|
|||||||
|
|
||||||
@Output() confirmAction = new EventEmitter<ConfirmationAcknowledgement>();
|
@Output() confirmAction = new EventEmitter<ConfirmationAcknowledgement>();
|
||||||
@Output() cancelAction = new EventEmitter<ConfirmationAcknowledgement>();
|
@Output() cancelAction = new EventEmitter<ConfirmationAcknowledgement>();
|
||||||
@Input() batchInfors: BatchInfo[] = [];
|
|
||||||
isDelete = false;
|
isDelete = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -52,12 +51,6 @@ export class ConfirmationDialogComponent {
|
|||||||
this.opened = true;
|
this.opened = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
get batchOverStatus(): boolean {
|
|
||||||
if (this.batchInfors.length) {
|
|
||||||
return this.batchInfors.every(item => item.loading === false);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
colorChange(list: BatchInfo) {
|
colorChange(list: BatchInfo) {
|
||||||
if (!list.loading && !list.errorState) {
|
if (!list.loading && !list.errorState) {
|
||||||
@ -74,7 +67,6 @@ export class ConfirmationDialogComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
close(): void {
|
close(): void {
|
||||||
this.batchInfors = [];
|
|
||||||
this.opened = false;
|
this.opened = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,27 +88,6 @@ export class ConfirmationDialogComponent {
|
|||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
operate(): void {
|
|
||||||
if (!this.message) {// Inproper condition
|
|
||||||
this.close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.batchInfors.length) {
|
|
||||||
this.batchInfors.every(item => item.loading = true);
|
|
||||||
this.isDelete = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let data: any = this.message.data ? this.message.data : {};
|
|
||||||
let target = this.message.targetId ? this.message.targetId : ConfirmationTargets.EMPTY;
|
|
||||||
let message = new ConfirmationAcknowledgement(
|
|
||||||
ConfirmationState.CONFIRMED,
|
|
||||||
data,
|
|
||||||
target
|
|
||||||
);
|
|
||||||
this.confirmAction.emit(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
confirm(): void {
|
confirm(): void {
|
||||||
if (!this.message) {// Inproper condition
|
if (!this.message) {// Inproper condition
|
||||||
this.close();
|
this.close();
|
||||||
|
@ -37,6 +37,7 @@ import {
|
|||||||
ProjectService
|
ProjectService
|
||||||
} from "../service/project.service";
|
} from "../service/project.service";
|
||||||
import { JobLogViewerComponent } from "../job-log-viewer/job-log-viewer.component";
|
import { JobLogViewerComponent } from "../job-log-viewer/job-log-viewer.component";
|
||||||
|
import { OperationService } from "../operation/operation.service";
|
||||||
|
|
||||||
describe("CreateEditRuleComponent (inline template)", () => {
|
describe("CreateEditRuleComponent (inline template)", () => {
|
||||||
let mockRules: ReplicationRule[] = [
|
let mockRules: ReplicationRule[] = [
|
||||||
@ -246,7 +247,8 @@ describe("CreateEditRuleComponent (inline template)", () => {
|
|||||||
{ provide: ReplicationService, useClass: ReplicationDefaultService },
|
{ provide: ReplicationService, useClass: ReplicationDefaultService },
|
||||||
{ provide: EndpointService, useClass: EndpointDefaultService },
|
{ provide: EndpointService, useClass: EndpointDefaultService },
|
||||||
{ provide: ProjectService, useClass: ProjectDefaultService },
|
{ provide: ProjectService, useClass: ProjectDefaultService },
|
||||||
{ provide: JobLogService, useClass: JobLogDefaultService }
|
{ provide: JobLogService, useClass: JobLogDefaultService },
|
||||||
|
{ provide: OperationService }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
@ -38,6 +38,6 @@
|
|||||||
</clr-datagrid>
|
</clr-datagrid>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<confirmation-dialog #confirmationDialog [batchInfors]="batchDelectionInfos" (confirmAction)="confirmDeletion($event)"></confirmation-dialog>
|
<confirmation-dialog #confirmationDialog (confirmAction)="confirmDeletion($event)"></confirmation-dialog>
|
||||||
<hbr-create-edit-endpoint (reload)="reload($event)"></hbr-create-edit-endpoint>
|
<hbr-create-edit-endpoint (reload)="reload($event)"></hbr-create-edit-endpoint>
|
||||||
</div>
|
</div>
|
@ -16,6 +16,7 @@ import {
|
|||||||
EndpointDefaultService
|
EndpointDefaultService
|
||||||
} from "../service/endpoint.service";
|
} from "../service/endpoint.service";
|
||||||
import { IServiceConfig, SERVICE_CONFIG } from "../service.config";
|
import { IServiceConfig, SERVICE_CONFIG } from "../service.config";
|
||||||
|
import { OperationService } from "../operation/operation.service";
|
||||||
|
|
||||||
import { click } from "../utils";
|
import { click } from "../utils";
|
||||||
|
|
||||||
@ -94,7 +95,8 @@ describe("EndpointComponent (inline template)", () => {
|
|||||||
providers: [
|
providers: [
|
||||||
ErrorHandler,
|
ErrorHandler,
|
||||||
{ provide: SERVICE_CONFIG, useValue: config },
|
{ provide: SERVICE_CONFIG, useValue: config },
|
||||||
{ provide: EndpointService, useClass: EndpointDefaultService }
|
{ provide: EndpointService, useClass: EndpointDefaultService },
|
||||||
|
{ provide: OperationService }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
@ -30,9 +30,9 @@ import { EndpointService } from "../service/endpoint.service";
|
|||||||
|
|
||||||
import { ErrorHandler } from "../error-handler/index";
|
import { ErrorHandler } from "../error-handler/index";
|
||||||
|
|
||||||
import { ConfirmationMessage } from "../confirmation-dialog/confirmation-message";
|
import {ConfirmationMessage} from "../confirmation-dialog/confirmation-message";
|
||||||
import { ConfirmationAcknowledgement } from "../confirmation-dialog/confirmation-state-message";
|
import {ConfirmationAcknowledgement} from "../confirmation-dialog/confirmation-state-message";
|
||||||
import { ConfirmationDialogComponent } from "../confirmation-dialog/confirmation-dialog.component";
|
import {ConfirmationDialogComponent} from "../confirmation-dialog/confirmation-dialog.component";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ConfirmationTargets,
|
ConfirmationTargets,
|
||||||
@ -43,11 +43,8 @@ import {
|
|||||||
import { CreateEditEndpointComponent } from "../create-edit-endpoint/create-edit-endpoint.component";
|
import { CreateEditEndpointComponent } from "../create-edit-endpoint/create-edit-endpoint.component";
|
||||||
import { toPromise, CustomComparator } from "../utils";
|
import { toPromise, CustomComparator } from "../utils";
|
||||||
|
|
||||||
import {
|
import {operateChanges, OperateInfo, OperationState} from "../operation/operate";
|
||||||
BatchInfo,
|
import {OperationService} from "../operation/operation.service";
|
||||||
BathInfoChanges
|
|
||||||
} from "../confirmation-dialog/confirmation-batch-message";
|
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "hbr-endpoint",
|
selector: "hbr-endpoint",
|
||||||
@ -77,7 +74,6 @@ export class EndpointComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
timerHandler: any;
|
timerHandler: any;
|
||||||
selectedRow: Endpoint[] = [];
|
selectedRow: Endpoint[] = [];
|
||||||
batchDelectionInfos: BatchInfo[] = [];
|
|
||||||
|
|
||||||
get initEndpoint(): Endpoint {
|
get initEndpoint(): Endpoint {
|
||||||
return {
|
return {
|
||||||
@ -90,12 +86,11 @@ export class EndpointComponent implements OnInit, OnDestroy {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(private endpointService: EndpointService,
|
||||||
private endpointService: EndpointService,
|
|
||||||
private errorHandler: ErrorHandler,
|
private errorHandler: ErrorHandler,
|
||||||
private translateService: TranslateService,
|
private translateService: TranslateService,
|
||||||
private ref: ChangeDetectorRef
|
private operationService: OperationService,
|
||||||
) {
|
private ref: ChangeDetectorRef) {
|
||||||
this.forceRefreshView(1000);
|
this.forceRefreshView(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,6 +104,7 @@ export class EndpointComponent implements OnInit, OnDestroy {
|
|||||||
this.subscription.unsubscribe();
|
this.subscription.unsubscribe();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedChange(): void {
|
selectedChange(): void {
|
||||||
this.forceRefreshView(5000);
|
this.forceRefreshView(5000);
|
||||||
}
|
}
|
||||||
@ -162,37 +158,31 @@ export class EndpointComponent implements OnInit, OnDestroy {
|
|||||||
deleteTargets(targets: Endpoint[]) {
|
deleteTargets(targets: Endpoint[]) {
|
||||||
if (targets && targets.length) {
|
if (targets && targets.length) {
|
||||||
let targetNames: string[] = [];
|
let targetNames: string[] = [];
|
||||||
this.batchDelectionInfos = [];
|
|
||||||
targets.forEach(target => {
|
targets.forEach(target => {
|
||||||
targetNames.push(target.name);
|
targetNames.push(target.name);
|
||||||
let initBatchMessage = new BatchInfo();
|
|
||||||
initBatchMessage.name = target.name;
|
|
||||||
this.batchDelectionInfos.push(initBatchMessage);
|
|
||||||
});
|
});
|
||||||
let deletionMessage = new ConfirmationMessage(
|
let deletionMessage = new ConfirmationMessage(
|
||||||
"REPLICATION.DELETION_TITLE_TARGET",
|
'REPLICATION.DELETION_TITLE_TARGET',
|
||||||
"REPLICATION.DELETION_SUMMARY_TARGET",
|
'REPLICATION.DELETION_SUMMARY_TARGET',
|
||||||
targetNames.join(", ") || "",
|
targetNames.join(', ') || '',
|
||||||
targets,
|
targets,
|
||||||
ConfirmationTargets.TARGET,
|
ConfirmationTargets.TARGET,
|
||||||
ConfirmationButtons.DELETE_CANCEL
|
ConfirmationButtons.DELETE_CANCEL);
|
||||||
);
|
|
||||||
this.confirmationDialogComponent.open(deletionMessage);
|
this.confirmationDialogComponent.open(deletionMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmDeletion(message: ConfirmationAcknowledgement) {
|
confirmDeletion(message: ConfirmationAcknowledgement) {
|
||||||
if (
|
if (message &&
|
||||||
message &&
|
|
||||||
message.source === ConfirmationTargets.TARGET &&
|
message.source === ConfirmationTargets.TARGET &&
|
||||||
message.state === ConfirmationState.CONFIRMED
|
message.state === ConfirmationState.CONFIRMED) {
|
||||||
) {
|
|
||||||
let targetLists: Endpoint[] = message.data;
|
let targetLists: Endpoint[] = message.data;
|
||||||
if (targetLists && targetLists.length) {
|
if (targetLists && targetLists.length) {
|
||||||
let promiseLists: any[] = [];
|
let promiseLists: any[] = [];
|
||||||
targetLists.forEach(target => {
|
targetLists.forEach(target => {
|
||||||
promiseLists.push(this.delOperate(target.id, target.name));
|
promiseLists.push(this.delOperate(target));
|
||||||
});
|
});
|
||||||
Promise.all(promiseLists).then(item => {
|
Promise.all(promiseLists).then((item) => {
|
||||||
this.selectedRow = [];
|
this.selectedRow = [];
|
||||||
this.reload(true);
|
this.reload(true);
|
||||||
this.forceRefreshView(2000);
|
this.forceRefreshView(2000);
|
||||||
@ -201,37 +191,38 @@ export class EndpointComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delOperate(id: number | string, name: string) {
|
delOperate(target: Endpoint) {
|
||||||
let findedList = this.batchDelectionInfos.find(data => data.name === name);
|
// init operation info
|
||||||
return toPromise<number>(this.endpointService.deleteEndpoint(id))
|
let operMessage = new OperateInfo();
|
||||||
.then(response => {
|
operMessage.name = 'OPERATION.DELETE_REGISTRY';
|
||||||
this.translateService.get("BATCH.DELETED_SUCCESS").subscribe(res => {
|
operMessage.data.id = target.id;
|
||||||
findedList = BathInfoChanges(findedList, res);
|
operMessage.state = OperationState.progressing;
|
||||||
|
operMessage.data.name = target.name;
|
||||||
|
this.operationService.publishInfo(operMessage);
|
||||||
|
|
||||||
|
return toPromise<number>(this.endpointService
|
||||||
|
.deleteEndpoint(target.id))
|
||||||
|
.then(
|
||||||
|
response => {
|
||||||
|
this.translateService.get('BATCH.DELETED_SUCCESS')
|
||||||
|
.subscribe(res => {
|
||||||
|
operateChanges(operMessage, OperationState.success);
|
||||||
});
|
});
|
||||||
})
|
}).catch(
|
||||||
.catch(error => {
|
error => {
|
||||||
if (error && error.status === 412) {
|
if (error && error.status === 412) {
|
||||||
Observable.forkJoin(
|
Observable.forkJoin(this.translateService.get('BATCH.DELETED_FAILURE'),
|
||||||
this.translateService.get("BATCH.DELETED_FAILURE"),
|
this.translateService.get('DESTINATION.FAILED_TO_DELETE_TARGET_IN_USED')).subscribe(res => {
|
||||||
this.translateService.get(
|
operateChanges(operMessage, OperationState.failure, res[1]);
|
||||||
"DESTINATION.FAILED_TO_DELETE_TARGET_IN_USED"
|
|
||||||
)
|
|
||||||
).subscribe(res => {
|
|
||||||
findedList = BathInfoChanges(
|
|
||||||
findedList,
|
|
||||||
res[0],
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
res[1]
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.translateService.get("BATCH.DELETED_FAILURE").subscribe(res => {
|
this.translateService.get('BATCH.DELETED_FAILURE').subscribe(res => {
|
||||||
findedList = BathInfoChanges(findedList, res, false, true);
|
operateChanges(operMessage, OperationState.failure, res);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forcely refresh the view
|
// Forcely refresh the view
|
||||||
forceRefreshView(duration: number): void {
|
forceRefreshView(duration: number): void {
|
||||||
// Reset timer
|
// Reset timer
|
||||||
|
@ -24,6 +24,10 @@ import { JOB_LOG_VIEWER_DIRECTIVES } from './job-log-viewer/index';
|
|||||||
import { PROJECT_POLICY_CONFIG_DIRECTIVES } from './project-policy-config/index';
|
import { PROJECT_POLICY_CONFIG_DIRECTIVES } from './project-policy-config/index';
|
||||||
import { HBR_GRIDVIEW_DIRECTIVES } from './gridview/index';
|
import { HBR_GRIDVIEW_DIRECTIVES } from './gridview/index';
|
||||||
import { REPOSITORY_GRIDVIEW_DIRECTIVES } from './repository-gridview/index';
|
import { REPOSITORY_GRIDVIEW_DIRECTIVES } from './repository-gridview/index';
|
||||||
|
import { OPERATION_DIRECTIVES } from './operation/index';
|
||||||
|
import {LABEL_DIRECTIVES} from "./label/index";
|
||||||
|
import {CREATE_EDIT_LABEL_DIRECTIVES} from "./create-edit-label/index";
|
||||||
|
import {LABEL_PIECE_DIRECTIVES} from "./label-piece/index";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
SystemInfoService,
|
SystemInfoService,
|
||||||
@ -47,7 +51,7 @@ import {
|
|||||||
ProjectService,
|
ProjectService,
|
||||||
ProjectDefaultService,
|
ProjectDefaultService,
|
||||||
LabelService,
|
LabelService,
|
||||||
LabelDefaultService
|
LabelDefaultService,
|
||||||
} from './service/index';
|
} from './service/index';
|
||||||
import {
|
import {
|
||||||
ErrorHandler,
|
ErrorHandler,
|
||||||
@ -59,9 +63,7 @@ import { TranslateModule } from '@ngx-translate/core';
|
|||||||
import { TranslateServiceInitializer } from './i18n/index';
|
import { TranslateServiceInitializer } from './i18n/index';
|
||||||
import { DEFAULT_LANG_COOKIE_KEY, DEFAULT_SUPPORTING_LANGS, DEFAULT_LANG } from './utils';
|
import { DEFAULT_LANG_COOKIE_KEY, DEFAULT_SUPPORTING_LANGS, DEFAULT_LANG } from './utils';
|
||||||
import { ChannelService } from './channel/index';
|
import { ChannelService } from './channel/index';
|
||||||
import {LABEL_DIRECTIVES} from "./label/index";
|
import { OperationService } from './operation/operation.service';
|
||||||
import {CREATE_EDIT_LABEL_DIRECTIVES} from "./create-edit-label/index";
|
|
||||||
import {LABEL_PIECE_DIRECTIVES} from "./label-piece/index";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Declare default service configuration; all the endpoints will be defined in
|
* Declare default service configuration; all the endpoints will be defined in
|
||||||
@ -182,6 +184,7 @@ export function initConfig(translateInitializer: TranslateServiceInitializer, co
|
|||||||
LABEL_PIECE_DIRECTIVES,
|
LABEL_PIECE_DIRECTIVES,
|
||||||
HBR_GRIDVIEW_DIRECTIVES,
|
HBR_GRIDVIEW_DIRECTIVES,
|
||||||
REPOSITORY_GRIDVIEW_DIRECTIVES,
|
REPOSITORY_GRIDVIEW_DIRECTIVES,
|
||||||
|
OPERATION_DIRECTIVES
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
LOG_DIRECTIVES,
|
LOG_DIRECTIVES,
|
||||||
@ -207,6 +210,7 @@ export function initConfig(translateInitializer: TranslateServiceInitializer, co
|
|||||||
LABEL_PIECE_DIRECTIVES,
|
LABEL_PIECE_DIRECTIVES,
|
||||||
HBR_GRIDVIEW_DIRECTIVES,
|
HBR_GRIDVIEW_DIRECTIVES,
|
||||||
REPOSITORY_GRIDVIEW_DIRECTIVES,
|
REPOSITORY_GRIDVIEW_DIRECTIVES,
|
||||||
|
OPERATION_DIRECTIVES
|
||||||
],
|
],
|
||||||
providers: []
|
providers: []
|
||||||
})
|
})
|
||||||
@ -237,7 +241,8 @@ export class HarborLibraryModule {
|
|||||||
deps: [TranslateServiceInitializer, SERVICE_CONFIG],
|
deps: [TranslateServiceInitializer, SERVICE_CONFIG],
|
||||||
multi: true
|
multi: true
|
||||||
},
|
},
|
||||||
ChannelService
|
ChannelService,
|
||||||
|
OperationService
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -259,7 +264,8 @@ export class HarborLibraryModule {
|
|||||||
config.jobLogService || { provide: JobLogService, useClass: JobLogDefaultService },
|
config.jobLogService || { provide: JobLogService, useClass: JobLogDefaultService },
|
||||||
config.projectPolicyService || { provide: ProjectService, useClass: ProjectDefaultService },
|
config.projectPolicyService || { provide: ProjectService, useClass: ProjectDefaultService },
|
||||||
config.labelService || {provide: LabelService, useClass: LabelDefaultService},
|
config.labelService || {provide: LabelService, useClass: LabelDefaultService},
|
||||||
ChannelService
|
ChannelService,
|
||||||
|
OperationService
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -24,3 +24,5 @@ export * from './label/index';
|
|||||||
export * from './create-edit-label/index';
|
export * from './create-edit-label/index';
|
||||||
export * from './gridview/index';
|
export * from './gridview/index';
|
||||||
export * from './repository-gridview/index';
|
export * from './repository-gridview/index';
|
||||||
|
export * from './operation/index';
|
||||||
|
export * from './_animations/index';
|
||||||
|
@ -37,5 +37,6 @@
|
|||||||
</clr-datagrid>
|
</clr-datagrid>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<confirmation-dialog #confirmationDialog [batchInfors]="batchDelectionInfos" (confirmAction)="confirmDeletion($event)"></confirmation-dialog>
|
<confirmation-dialog #confirmationDialog (confirmAction)="confirmDeletion($event)"></confirmation-dialog>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import {InlineAlertComponent} from "../inline-alert/inline-alert.component";
|
|||||||
import {ErrorHandler} from "../error-handler/error-handler";
|
import {ErrorHandler} from "../error-handler/error-handler";
|
||||||
|
|
||||||
import {IServiceConfig, SERVICE_CONFIG} from "../service.config";
|
import {IServiceConfig, SERVICE_CONFIG} from "../service.config";
|
||||||
|
import { OperationService } from "../operation/operation.service";
|
||||||
|
|
||||||
describe('LabelComponent (inline template)', () => {
|
describe('LabelComponent (inline template)', () => {
|
||||||
|
|
||||||
@ -79,7 +79,8 @@ describe('LabelComponent (inline template)', () => {
|
|||||||
providers: [
|
providers: [
|
||||||
ErrorHandler,
|
ErrorHandler,
|
||||||
{ provide: SERVICE_CONFIG, useValue: config },
|
{ provide: SERVICE_CONFIG, useValue: config },
|
||||||
{provide: LabelService, useClass: LabelDefaultService}
|
{provide: LabelService, useClass: LabelDefaultService},
|
||||||
|
{ provide: OperationService }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
@ -19,24 +19,23 @@ import {
|
|||||||
ChangeDetectorRef,
|
ChangeDetectorRef,
|
||||||
Input
|
Input
|
||||||
} from "@angular/core";
|
} from "@angular/core";
|
||||||
import { Label } from "../service/interface";
|
import {Label} from "../service/interface";
|
||||||
import { LabelService } from "../service/label.service";
|
import {LabelService} from "../service/label.service";
|
||||||
import { toPromise } from "../utils";
|
import {toPromise} from "../utils";
|
||||||
import { ErrorHandler } from "../error-handler/error-handler";
|
import {ErrorHandler} from "../error-handler/error-handler";
|
||||||
import { CreateEditLabelComponent } from "../create-edit-label/create-edit-label.component";
|
import {CreateEditLabelComponent} from "../create-edit-label/create-edit-label.component";
|
||||||
import {
|
import {ConfirmationMessage} from "../confirmation-dialog/confirmation-message";
|
||||||
BatchInfo,
|
|
||||||
BathInfoChanges
|
|
||||||
} from "../confirmation-dialog/confirmation-batch-message";
|
|
||||||
import { ConfirmationMessage } from "../confirmation-dialog/confirmation-message";
|
|
||||||
import {
|
import {
|
||||||
ConfirmationButtons,
|
ConfirmationButtons,
|
||||||
ConfirmationState,
|
ConfirmationState,
|
||||||
ConfirmationTargets
|
ConfirmationTargets
|
||||||
} from "../shared/shared.const";
|
} from "../shared/shared.const";
|
||||||
import { ConfirmationAcknowledgement } from "../confirmation-dialog/confirmation-state-message";
|
import {ConfirmationAcknowledgement} from "../confirmation-dialog/confirmation-state-message";
|
||||||
import { TranslateService } from "@ngx-translate/core";
|
import {TranslateService} from "@ngx-translate/core";
|
||||||
import { ConfirmationDialogComponent } from "../confirmation-dialog/confirmation-dialog.component";
|
import {ConfirmationDialogComponent} from "../confirmation-dialog/confirmation-dialog.component";
|
||||||
|
import {operateChanges, OperateInfo, OperationState} from "../operation/operate";
|
||||||
|
import {OperationService} from "../operation/operation.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "hbr-label",
|
selector: "hbr-label",
|
||||||
templateUrl: "./label.component.html",
|
templateUrl: "./label.component.html",
|
||||||
@ -48,9 +47,7 @@ export class LabelComponent implements OnInit {
|
|||||||
loading: boolean;
|
loading: boolean;
|
||||||
targets: Label[];
|
targets: Label[];
|
||||||
targetName: string;
|
targetName: string;
|
||||||
|
|
||||||
selectedRow: Label[] = [];
|
selectedRow: Label[] = [];
|
||||||
batchDelectionInfos: BatchInfo[] = [];
|
|
||||||
|
|
||||||
@Input() scope: string;
|
@Input() scope: string;
|
||||||
@Input() projectId = 0;
|
@Input() projectId = 0;
|
||||||
@ -60,12 +57,13 @@ export class LabelComponent implements OnInit {
|
|||||||
createEditLabel: CreateEditLabelComponent;
|
createEditLabel: CreateEditLabelComponent;
|
||||||
@ViewChild("confirmationDialog")
|
@ViewChild("confirmationDialog")
|
||||||
confirmationDialogComponent: ConfirmationDialogComponent;
|
confirmationDialogComponent: ConfirmationDialogComponent;
|
||||||
constructor(
|
|
||||||
private labelService: LabelService,
|
constructor(private labelService: LabelService,
|
||||||
private errorHandler: ErrorHandler,
|
private errorHandler: ErrorHandler,
|
||||||
private translateService: TranslateService,
|
private translateService: TranslateService,
|
||||||
private ref: ChangeDetectorRef
|
private operationService: OperationService,
|
||||||
) {}
|
private ref: ChangeDetectorRef) {
|
||||||
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.retrieve(this.scope);
|
this.retrieve(this.scope);
|
||||||
@ -114,38 +112,31 @@ export class LabelComponent implements OnInit {
|
|||||||
deleteLabels(targets: Label[]): void {
|
deleteLabels(targets: Label[]): void {
|
||||||
if (targets && targets.length) {
|
if (targets && targets.length) {
|
||||||
let targetNames: string[] = [];
|
let targetNames: string[] = [];
|
||||||
this.batchDelectionInfos = [];
|
|
||||||
targets.forEach(target => {
|
targets.forEach(target => {
|
||||||
targetNames.push(target.name);
|
targetNames.push(target.name);
|
||||||
let initBatchMessage = new BatchInfo();
|
|
||||||
initBatchMessage.name = target.name;
|
|
||||||
this.batchDelectionInfos.push(initBatchMessage);
|
|
||||||
});
|
});
|
||||||
let deletionMessage = new ConfirmationMessage(
|
let deletionMessage = new ConfirmationMessage(
|
||||||
"LABEL.DELETION_TITLE_TARGET",
|
'LABEL.DELETION_TITLE_TARGET',
|
||||||
"LABEL.DELETION_SUMMARY_TARGET",
|
'LABEL.DELETION_SUMMARY_TARGET',
|
||||||
targetNames.join(", ") || "",
|
targetNames.join(', ') || '',
|
||||||
targets,
|
targets,
|
||||||
ConfirmationTargets.TARGET,
|
ConfirmationTargets.TARGET,
|
||||||
ConfirmationButtons.DELETE_CANCEL
|
ConfirmationButtons.DELETE_CANCEL);
|
||||||
);
|
|
||||||
this.confirmationDialogComponent.open(deletionMessage);
|
this.confirmationDialogComponent.open(deletionMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmDeletion(message: ConfirmationAcknowledgement) {
|
confirmDeletion(message: ConfirmationAcknowledgement) {
|
||||||
if (
|
if (message &&
|
||||||
message &&
|
|
||||||
message.source === ConfirmationTargets.TARGET &&
|
message.source === ConfirmationTargets.TARGET &&
|
||||||
message.state === ConfirmationState.CONFIRMED
|
message.state === ConfirmationState.CONFIRMED) {
|
||||||
) {
|
|
||||||
let targetLists: Label[] = message.data;
|
let targetLists: Label[] = message.data;
|
||||||
if (targetLists && targetLists.length) {
|
if (targetLists && targetLists.length) {
|
||||||
let promiseLists: any[] = [];
|
let promiseLists: any[] = [];
|
||||||
targetLists.forEach(target => {
|
targetLists.forEach(target => {
|
||||||
promiseLists.push(this.delOperate(target.id, target.name));
|
promiseLists.push(this.delOperate(target));
|
||||||
});
|
});
|
||||||
Promise.all(promiseLists).then(item => {
|
Promise.all(promiseLists).then((item) => {
|
||||||
this.selectedRow = [];
|
this.selectedRow = [];
|
||||||
this.retrieve(this.scope);
|
this.retrieve(this.scope);
|
||||||
});
|
});
|
||||||
@ -153,17 +144,27 @@ export class LabelComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delOperate(id: number, name: string) {
|
delOperate(target: Label) {
|
||||||
let findedList = this.batchDelectionInfos.find(data => data.name === name);
|
// init operation info
|
||||||
return toPromise<number>(this.labelService.deleteLabel(id))
|
let operMessage = new OperateInfo();
|
||||||
.then(response => {
|
operMessage.name = 'OPERATION.DELETE_LABEL';
|
||||||
this.translateService.get("BATCH.DELETED_SUCCESS").subscribe(res => {
|
operMessage.data.id = target.id;
|
||||||
findedList = BathInfoChanges(findedList, res);
|
operMessage.state = OperationState.progressing;
|
||||||
|
operMessage.data.name = target.name;
|
||||||
|
this.operationService.publishInfo(operMessage);
|
||||||
|
|
||||||
|
return toPromise<number>(this.labelService
|
||||||
|
.deleteLabel(target.id))
|
||||||
|
.then(
|
||||||
|
response => {
|
||||||
|
this.translateService.get('BATCH.DELETED_SUCCESS')
|
||||||
|
.subscribe(res => {
|
||||||
|
operateChanges(operMessage, OperationState.success);
|
||||||
});
|
});
|
||||||
})
|
}).catch(
|
||||||
.catch(error => {
|
error => {
|
||||||
this.translateService.get("BATCH.DELETED_FAILURE").subscribe(res => {
|
this.translateService.get('BATCH.DELETED_FAILURE').subscribe(res => {
|
||||||
findedList = BathInfoChanges(findedList, res, false, true);
|
operateChanges(operMessage, OperationState.failure, res);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -34,5 +34,5 @@
|
|||||||
<clr-dg-pagination #pagination [clrDgPageSize]="5"></clr-dg-pagination>
|
<clr-dg-pagination #pagination [clrDgPageSize]="5"></clr-dg-pagination>
|
||||||
</clr-dg-footer>
|
</clr-dg-footer>
|
||||||
</clr-datagrid>
|
</clr-datagrid>
|
||||||
<confirmation-dialog #deletionConfirmDialog [batchInfors]="batchDelectionInfos" (confirmAction)="deletionConfirm($event)"></confirmation-dialog>
|
<confirmation-dialog #deletionConfirmDialog (confirmAction)="deletionConfirm($event)"></confirmation-dialog>
|
||||||
</div>
|
</div>
|
@ -13,6 +13,7 @@ import { ReplicationRule } from '../service/interface';
|
|||||||
import { ErrorHandler } from '../error-handler/error-handler';
|
import { ErrorHandler } from '../error-handler/error-handler';
|
||||||
import { SERVICE_CONFIG, IServiceConfig } from '../service.config';
|
import { SERVICE_CONFIG, IServiceConfig } from '../service.config';
|
||||||
import { ReplicationService, ReplicationDefaultService } from '../service/replication.service';
|
import { ReplicationService, ReplicationDefaultService } from '../service/replication.service';
|
||||||
|
import { OperationService } from "../operation/operation.service";
|
||||||
|
|
||||||
describe('ListReplicationRuleComponent (inline template)', () => {
|
describe('ListReplicationRuleComponent (inline template)', () => {
|
||||||
|
|
||||||
@ -124,7 +125,8 @@ describe('ListReplicationRuleComponent (inline template)', () => {
|
|||||||
providers: [
|
providers: [
|
||||||
ErrorHandler,
|
ErrorHandler,
|
||||||
{ provide: SERVICE_CONFIG, useValue: config },
|
{ provide: SERVICE_CONFIG, useValue: config },
|
||||||
{ provide: ReplicationService, useClass: ReplicationDefaultService }
|
{ provide: ReplicationService, useClass: ReplicationDefaultService },
|
||||||
|
{ provide: OperationService }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
@ -29,26 +29,25 @@ import "rxjs/add/observable/forkJoin";
|
|||||||
import { Comparator } from "clarity-angular";
|
import { Comparator } from "clarity-angular";
|
||||||
import { TranslateService } from "@ngx-translate/core";
|
import { TranslateService } from "@ngx-translate/core";
|
||||||
|
|
||||||
import { ReplicationService } from "../service/replication.service";
|
import {ReplicationService} from "../service/replication.service";
|
||||||
import {
|
import {
|
||||||
ReplicationJob,
|
ReplicationJob,
|
||||||
ReplicationJobItem,
|
ReplicationJobItem,
|
||||||
ReplicationRule
|
ReplicationRule
|
||||||
} from "../service/interface";
|
} from "../service/interface";
|
||||||
import { ConfirmationDialogComponent } from "../confirmation-dialog/confirmation-dialog.component";
|
import {ConfirmationDialogComponent} from "../confirmation-dialog/confirmation-dialog.component";
|
||||||
import { ConfirmationMessage } from "../confirmation-dialog/confirmation-message";
|
import {ConfirmationMessage} from "../confirmation-dialog/confirmation-message";
|
||||||
import { ConfirmationAcknowledgement } from "../confirmation-dialog/confirmation-state-message";
|
import {ConfirmationAcknowledgement} from "../confirmation-dialog/confirmation-state-message";
|
||||||
import {
|
import {
|
||||||
ConfirmationState,
|
ConfirmationState,
|
||||||
ConfirmationTargets,
|
ConfirmationTargets,
|
||||||
ConfirmationButtons
|
ConfirmationButtons
|
||||||
} from "../shared/shared.const";
|
} from "../shared/shared.const";
|
||||||
import { ErrorHandler } from "../error-handler/error-handler";
|
import {ErrorHandler} from "../error-handler/error-handler";
|
||||||
import { toPromise, CustomComparator } from "../utils";
|
import {toPromise, CustomComparator} from "../utils";
|
||||||
import {
|
import {operateChanges, OperateInfo, OperationState} from "../operation/operate";
|
||||||
BatchInfo,
|
import {OperationService} from "../operation/operation.service";
|
||||||
BathInfoChanges
|
|
||||||
} from "../confirmation-dialog/confirmation-batch-message";
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "hbr-list-replication-rule",
|
selector: "hbr-list-replication-rule",
|
||||||
@ -83,7 +82,6 @@ export class ListReplicationRuleComponent implements OnInit, OnChanges {
|
|||||||
canDeleteRule: boolean;
|
canDeleteRule: boolean;
|
||||||
|
|
||||||
selectedRow: ReplicationRule;
|
selectedRow: ReplicationRule;
|
||||||
batchDelectionInfos: BatchInfo[] = [];
|
|
||||||
|
|
||||||
@ViewChild("toggleConfirmDialog")
|
@ViewChild("toggleConfirmDialog")
|
||||||
toggleConfirmDialog: ConfirmationDialogComponent;
|
toggleConfirmDialog: ConfirmationDialogComponent;
|
||||||
@ -91,19 +89,14 @@ export class ListReplicationRuleComponent implements OnInit, OnChanges {
|
|||||||
@ViewChild("deletionConfirmDialog")
|
@ViewChild("deletionConfirmDialog")
|
||||||
deletionConfirmDialog: ConfirmationDialogComponent;
|
deletionConfirmDialog: ConfirmationDialogComponent;
|
||||||
|
|
||||||
startTimeComparator: Comparator<ReplicationRule> = new CustomComparator<
|
startTimeComparator: Comparator<ReplicationRule> = new CustomComparator<ReplicationRule>("start_time", "date");
|
||||||
ReplicationRule
|
enabledComparator: Comparator<ReplicationRule> = new CustomComparator<ReplicationRule>("enabled", "number");
|
||||||
>("start_time", "date");
|
|
||||||
enabledComparator: Comparator<ReplicationRule> = new CustomComparator<
|
|
||||||
ReplicationRule
|
|
||||||
>("enabled", "number");
|
|
||||||
|
|
||||||
constructor(
|
constructor(private replicationService: ReplicationService,
|
||||||
private replicationService: ReplicationService,
|
|
||||||
private translateService: TranslateService,
|
private translateService: TranslateService,
|
||||||
private errorHandler: ErrorHandler,
|
private errorHandler: ErrorHandler,
|
||||||
private ref: ChangeDetectorRef
|
private operationService: OperationService,
|
||||||
) {
|
private ref: ChangeDetectorRef) {
|
||||||
setInterval(() => ref.markForCheck(), 500);
|
setInterval(() => ref.markForCheck(), 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,10 +204,6 @@ export class ListReplicationRuleComponent implements OnInit, OnChanges {
|
|||||||
|
|
||||||
deleteRule(rule: ReplicationRule) {
|
deleteRule(rule: ReplicationRule) {
|
||||||
if (rule) {
|
if (rule) {
|
||||||
this.batchDelectionInfos = [];
|
|
||||||
let initBatchMessage = new BatchInfo();
|
|
||||||
initBatchMessage.name = rule.name;
|
|
||||||
this.batchDelectionInfos.push(initBatchMessage);
|
|
||||||
let deletionMessage = new ConfirmationMessage(
|
let deletionMessage = new ConfirmationMessage(
|
||||||
"REPLICATION.DELETION_TITLE",
|
"REPLICATION.DELETION_TITLE",
|
||||||
"REPLICATION.DELETION_SUMMARY",
|
"REPLICATION.DELETION_SUMMARY",
|
||||||
@ -226,29 +215,12 @@ export class ListReplicationRuleComponent implements OnInit, OnChanges {
|
|||||||
this.deletionConfirmDialog.open(deletionMessage);
|
this.deletionConfirmDialog.open(deletionMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteOpe(rule: ReplicationRule) {
|
deleteOpe(rule: ReplicationRule) {
|
||||||
if (rule) {
|
if (rule) {
|
||||||
let promiseLists: any[] = [];
|
let promiseLists: any[] = [];
|
||||||
Promise.all([this.jobList(rule.id)]).then(items => {
|
Promise.all([this.jobList(rule.id)]).then(items => {
|
||||||
if (!this.canDeleteRule) {
|
promiseLists.push(this.delOperate(rule));
|
||||||
let findedList = this.batchDelectionInfos.find(
|
|
||||||
data => data.name === rule.name
|
|
||||||
);
|
|
||||||
Observable.forkJoin(
|
|
||||||
this.translateService.get("BATCH.DELETED_FAILURE"),
|
|
||||||
this.translateService.get("REPLICATION.DELETION_SUMMARY_FAILURE")
|
|
||||||
).subscribe(res => {
|
|
||||||
findedList = BathInfoChanges(
|
|
||||||
findedList,
|
|
||||||
res[0],
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
res[1]
|
|
||||||
);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
promiseLists.push(this.delOperate(+rule.id, rule.name));
|
|
||||||
}
|
|
||||||
|
|
||||||
Promise.all(promiseLists).then(item => {
|
Promise.all(promiseLists).then(item => {
|
||||||
this.selectedRow = null;
|
this.selectedRow = null;
|
||||||
@ -260,33 +232,38 @@ export class ListReplicationRuleComponent implements OnInit, OnChanges {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delOperate(ruleId: number, name: string) {
|
delOperate(rule: ReplicationRule) {
|
||||||
let findedList = this.batchDelectionInfos.find(data => data.name === name);
|
// init operation info
|
||||||
return toPromise<any>(this.replicationService.deleteReplicationRule(ruleId))
|
let operMessage = new OperateInfo();
|
||||||
|
operMessage.name = 'OPERATION.DELETE_REPLICATION';
|
||||||
|
operMessage.data.id = +rule.id;
|
||||||
|
operMessage.state = OperationState.progressing;
|
||||||
|
operMessage.data.name = rule.name;
|
||||||
|
this.operationService.publishInfo(operMessage);
|
||||||
|
|
||||||
|
if (!this.canDeleteRule) {
|
||||||
|
Observable.forkJoin(this.translateService.get('BATCH.DELETED_FAILURE'),
|
||||||
|
this.translateService.get('REPLICATION.DELETION_SUMMARY_FAILURE')).subscribe(res => {
|
||||||
|
operateChanges(operMessage, OperationState.failure, res[1]);
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return toPromise<any>(this.replicationService
|
||||||
|
.deleteReplicationRule(+rule.id))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.translateService
|
this.translateService.get('BATCH.DELETED_SUCCESS')
|
||||||
.get("BATCH.DELETED_SUCCESS")
|
.subscribe(res => operateChanges(operMessage, OperationState.success));
|
||||||
.subscribe(res => (findedList = BathInfoChanges(findedList, res)));
|
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
if (error && error.status === 412) {
|
if (error && error.status === 412) {
|
||||||
Observable.forkJoin(
|
Observable.forkJoin(this.translateService.get('BATCH.DELETED_FAILURE'),
|
||||||
this.translateService.get("BATCH.DELETED_FAILURE"),
|
this.translateService.get('REPLICATION.FAILED_TO_DELETE_POLICY_ENABLED')).subscribe(res => {
|
||||||
this.translateService.get(
|
operateChanges(operMessage, OperationState.failure, res[1]);
|
||||||
"REPLICATION.FAILED_TO_DELETE_POLICY_ENABLED"
|
|
||||||
)
|
|
||||||
).subscribe(res => {
|
|
||||||
findedList = BathInfoChanges(
|
|
||||||
findedList,
|
|
||||||
res[0],
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
res[1]
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.translateService.get("BATCH.DELETED_FAILURE").subscribe(res => {
|
this.translateService.get('BATCH.DELETED_FAILURE').subscribe(res => {
|
||||||
findedList = BathInfoChanges(findedList, res, false, true);
|
operateChanges(operMessage, OperationState.failure, res);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
13
src/ui_ng/lib/src/operation/index.ts
Normal file
13
src/ui_ng/lib/src/operation/index.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* Created by pengf on 5/11/2018.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Type} from "@angular/core";
|
||||||
|
import {OperationComponent} from "./operation.component";
|
||||||
|
|
||||||
|
export * from "./operation.component";
|
||||||
|
export * from './operate';
|
||||||
|
export * from './operation.service';
|
||||||
|
export const OPERATION_DIRECTIVES: Type<any>[] = [
|
||||||
|
OperationComponent
|
||||||
|
];
|
30
src/ui_ng/lib/src/operation/operate.ts
Normal file
30
src/ui_ng/lib/src/operation/operate.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
export class OperateInfo {
|
||||||
|
name: string;
|
||||||
|
state: string;
|
||||||
|
data: {[key: string]: string| number};
|
||||||
|
timeStamp: number;
|
||||||
|
timeDiff: string;
|
||||||
|
constructor() {
|
||||||
|
this.name = '';
|
||||||
|
this.state = '';
|
||||||
|
this.data = {id: -1, name: '', errorInf: ''};
|
||||||
|
this.timeStamp = 0;
|
||||||
|
this.timeDiff = 'less 1 minute';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function operateChanges(list: OperateInfo, state?: string, errorInfo?: string, timeStamp?: 0) {
|
||||||
|
list.state = state;
|
||||||
|
list.data.errorInf = errorInfo;
|
||||||
|
list.timeStamp = new Date().getTime();
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const OperationState = {
|
||||||
|
progressing: 'progressing',
|
||||||
|
success : 'success',
|
||||||
|
failure : 'failure',
|
||||||
|
interrupt: 'interrupt'
|
||||||
|
};
|
||||||
|
|
43
src/ui_ng/lib/src/operation/operation.component.css
Normal file
43
src/ui_ng/lib/src/operation/operation.component.css
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/* side form */
|
||||||
|
.side-form {
|
||||||
|
position: absolute;
|
||||||
|
width: 325px;
|
||||||
|
height: 100%;
|
||||||
|
left:28px;
|
||||||
|
padding-top: 20px;
|
||||||
|
background: #fff;
|
||||||
|
border-left: 1px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
.eventInfo {display: flex; justify-content: flex-start; align-content: flex-start;
|
||||||
|
padding: 8px 5px 8px 10px; border-bottom: 1px solid #ccc;}
|
||||||
|
.iconsArea{ flex-shrink: 1;}
|
||||||
|
.infoArea{ margin-left: 10px; width: 270px;}
|
||||||
|
.eventName{display: block; margin-bottom: -5px;font-size: 16px; color: rgb(11, 127, 189); }
|
||||||
|
.eventErrorInf {display:block; font-size: 12px;color:red;line-height: .6rem;}
|
||||||
|
.eventTarget{display: inline-flex; width: 172px; font-size: 12px; flex-shrink:1; overflow: hidden; text-overflow: ellipsis;white-space: nowrap;}
|
||||||
|
.eventTime{ float: right; font-size: 12px;}
|
||||||
|
:host >>> .nav{padding-left: 38px;}
|
||||||
|
.operDiv{position: fixed; top: 60px; right: 0; z-index:100}
|
||||||
|
.toolBar{
|
||||||
|
float: left;border-top: 1px solid #ccc;
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 2px 4px;
|
||||||
|
width: 86px;
|
||||||
|
height: 84px;
|
||||||
|
background-color: white;
|
||||||
|
letter-spacing: 1.2px;
|
||||||
|
font-weight: 500;
|
||||||
|
box-shadow: -2px -1px 3px #bebbbb;
|
||||||
|
cursor: pointer;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.freshIcon{float: right; margin-right: 20px; margin-top: -10px;cursor: pointer;}
|
||||||
|
#contentFailed, #contentAll, #contentRun{
|
||||||
|
position: absolute;
|
||||||
|
top: 95px;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
64
src/ui_ng/lib/src/operation/operation.component.html
Normal file
64
src/ui_ng/lib/src/operation/operation.component.html
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<div class="operDiv" [@SlideInOutAnimation]="animationState">
|
||||||
|
<a class="toolBar" (click)="slideOut()">{{'OPERATION.EVENT_LOG' | translate}}<!--<clr-icon shape="angle-double" style="transform: rotate(90deg)"></clr-icon>--></a>
|
||||||
|
<div class="side-form">
|
||||||
|
<clr-icon shape="refresh" class="freshIcon" (click)="TabEvent()"></clr-icon>
|
||||||
|
<h3 class="custom-h2" style="margin-left: 34px;">{{'OPERATION.LOCAL_EVENT' | translate}}</h3>
|
||||||
|
<div style="margin-top: 10px;">
|
||||||
|
<clr-tabs>
|
||||||
|
<clr-tab>
|
||||||
|
<button clrTabLink id="link1" (click)="TabEvent()">{{'OPERATION.ALL' | translate}}</button>
|
||||||
|
<clr-tab-content id="contentAll" *clrIfActive="true">
|
||||||
|
<div class="eventInfo" *ngFor="let list of resultLists">
|
||||||
|
<div class="iconsArea">
|
||||||
|
<i class="spinner spinner-inline spinner-pos" [hidden]="list.state != 'progressing'"></i>
|
||||||
|
<clr-icon [hidden]="list.state != 'success'" size="18" shape="success-standard" style="color: green"></clr-icon>
|
||||||
|
<clr-icon [hidden]="list.state != 'failure'" size="18" shape="error-standard" style="color: red"></clr-icon>
|
||||||
|
<clr-icon [hidden]="list.state != 'interrupt'" size="18" shape="unlink" style="color: orange"></clr-icon>
|
||||||
|
</div>
|
||||||
|
<div class="infoArea">
|
||||||
|
<label class="eventName" (click)="toggleTitle(spanErrorInfo)">{{list.name | translate}}</label>
|
||||||
|
<span class="eventTarget">{{list.data.name}}</span><span class="eventTime">{{list.timeDiff | translate}}</span>
|
||||||
|
<span #spanErrorInfo class="eventErrorInf" style="display: none;">{{list.data.errorInf}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</clr-tab-content>
|
||||||
|
</clr-tab>
|
||||||
|
<clr-tab>
|
||||||
|
<button clrTabLink (click)="TabEvent()">{{'OPERATION.RUNNING' | translate}}</button>
|
||||||
|
<clr-tab-content id="contentRun" *clrIfActive>
|
||||||
|
<div class="eventInfo" *ngFor="let list of runningLists">
|
||||||
|
<div class="iconsArea">
|
||||||
|
<i class="spinner spinner-inline spinner-pos" [hidden]="list.state != 'progressing'"></i>
|
||||||
|
<clr-icon [hidden]="list.state != 'success'" size="18" shape="success-standard" style="color: green"></clr-icon>
|
||||||
|
<clr-icon [hidden]="list.state != 'failure'" size="18" shape="error-standard" style="color: red"></clr-icon>
|
||||||
|
</div>
|
||||||
|
<div class="infoArea">
|
||||||
|
<label class="eventName" (click)="toggleTitle(spanErrorInfo)">{{list.name | translate}}</label>
|
||||||
|
<span class="eventTarget">{{list.data.name}}</span><span class="eventTime">{{list.timeDiff | translate}}</span>
|
||||||
|
<span #spanErrorInfo class="eventErrorInf" style="display: none;">{{list.data.errorInf}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</clr-tab-content>
|
||||||
|
</clr-tab>
|
||||||
|
<clr-tab>
|
||||||
|
<button clrTabLink (click)="TabEvent()">{{'OPERATION.FAILED' | translate}}</button>
|
||||||
|
<clr-tab-content id="contentFailed" *clrIfActive>
|
||||||
|
<div class="eventInfo" *ngFor="let list of failLists">
|
||||||
|
<div class="iconsArea">
|
||||||
|
<i class="spinner spinner-inline spinner-pos" [hidden]="list.state != 'progressing'"></i>
|
||||||
|
<clr-icon [hidden]="list.state != 'success'" size="18" shape="success-standard" style="color: green"></clr-icon>
|
||||||
|
<clr-icon [hidden]="list.state != 'failure'" size="18" shape="error-standard" style="color: red"></clr-icon>
|
||||||
|
</div>
|
||||||
|
<div class="infoArea">
|
||||||
|
<label class="eventName" (click)="toggleTitle(spanErrorInfo)">{{list.name | translate}}</label>
|
||||||
|
<span class="eventTarget">{{list.data.name}}</span><span class="eventTime">{{list.timeDiff | translate}}</span>
|
||||||
|
<span #spanErrorInfo class="eventErrorInf" style="display: none;">{{list.data.errorInf}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</clr-tab-content>
|
||||||
|
</clr-tab>
|
||||||
|
</clr-tabs>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
144
src/ui_ng/lib/src/operation/operation.component.ts
Normal file
144
src/ui_ng/lib/src/operation/operation.component.ts
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
import {Component, OnInit, OnDestroy, HostListener} from '@angular/core';
|
||||||
|
import {OperationService} from "./operation.service";
|
||||||
|
import {Subscription} from "rxjs/Subscription";
|
||||||
|
import {OperateInfo, OperationState} from "./operate";
|
||||||
|
import {SlideInOutAnimation} from "../_animations/slide-in-out.animation";
|
||||||
|
import {TranslateService} from "@ngx-translate/core";
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'hbr-operation-model',
|
||||||
|
templateUrl: './operation.component.html',
|
||||||
|
styleUrls: ['./operation.component.css'],
|
||||||
|
animations: [SlideInOutAnimation],
|
||||||
|
})
|
||||||
|
export class OperationComponent implements OnInit, OnDestroy {
|
||||||
|
batchInfoSubscription: Subscription;
|
||||||
|
resultLists: OperateInfo[] = [];
|
||||||
|
animationState = "out";
|
||||||
|
|
||||||
|
@HostListener('window:beforeunload', ['$event'])
|
||||||
|
beforeUnloadHander(event) {
|
||||||
|
// storage to localStorage
|
||||||
|
let timp = new Date().getTime();
|
||||||
|
localStorage.setItem('operaion', JSON.stringify({timp: timp, data: this.resultLists}));
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private operationService: OperationService,
|
||||||
|
private translate: TranslateService) {
|
||||||
|
|
||||||
|
this.batchInfoSubscription = operationService.operationInfo$.subscribe(data => {
|
||||||
|
// this.resultLists = data;
|
||||||
|
this.openSlide();
|
||||||
|
if (data) {
|
||||||
|
if (this.resultLists.length >= 50) {
|
||||||
|
this.resultLists.splice(49, this.resultLists.length - 49);
|
||||||
|
}
|
||||||
|
this.resultLists.unshift(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public get runningLists(): OperateInfo[] {
|
||||||
|
let runningList: OperateInfo[] = [];
|
||||||
|
this.resultLists.forEach(data => {
|
||||||
|
if (data.state === 'progressing') {
|
||||||
|
runningList.push(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return runningList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get failLists(): OperateInfo[] {
|
||||||
|
let failedList: OperateInfo[] = [];
|
||||||
|
this.resultLists.forEach(data => {
|
||||||
|
if (data.state === 'failure') {
|
||||||
|
failedList.push(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return failedList;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
let requestCookie = localStorage.getItem('operaion');
|
||||||
|
if (requestCookie) {
|
||||||
|
let operInfors: any = JSON.parse(requestCookie);
|
||||||
|
if (operInfors) {
|
||||||
|
if ((new Date().getTime() - operInfors.timp) > 1000 * 60 * 60 * 24) {
|
||||||
|
localStorage.removeItem('operaion');
|
||||||
|
}else {
|
||||||
|
if (operInfors.data) {
|
||||||
|
operInfors.data.forEach(operInfo => {
|
||||||
|
if (operInfo.state === OperationState.progressing) {
|
||||||
|
operInfo.state = OperationState.interrupt;
|
||||||
|
operInfo.data.errorInf = 'operation been interrupted';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.resultLists = operInfors.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
if (this.batchInfoSubscription) {
|
||||||
|
this.batchInfoSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleTitle(errorSpan: any) {
|
||||||
|
errorSpan.style.display = (errorSpan.style.display === 'none') ? 'block' : 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
slideOut(): void {
|
||||||
|
this.animationState = this.animationState === 'out' ? 'in' : 'out';
|
||||||
|
}
|
||||||
|
|
||||||
|
openSlide(): void {
|
||||||
|
this.animationState = 'in';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TabEvent(): void {
|
||||||
|
let timp: any;
|
||||||
|
this.resultLists.forEach(data => {
|
||||||
|
timp = new Date().getTime() - +data.timeStamp;
|
||||||
|
data.timeDiff = this.calculateTime(timp);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateTime(timp: number) {
|
||||||
|
let dist = Math.floor(timp / 1000 / 60); // change to minute;
|
||||||
|
if (dist > 0 && dist < 60) {
|
||||||
|
return Math.floor(dist) + ' minute(s) ago';
|
||||||
|
}else if (dist >= 60 && Math.floor(dist / 60) < 24) {
|
||||||
|
return Math.floor(dist / 60) + ' hour(s) ago';
|
||||||
|
} else if (Math.floor(dist / 60) >= 24) {
|
||||||
|
return Math.floor(dist / 60 / 24) + ' day ago';
|
||||||
|
} else {
|
||||||
|
return 'less 1 minute';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*calculateTime(timp: number) {
|
||||||
|
let dist = Math.floor(timp / 1000 / 60); // change to minute;
|
||||||
|
if (dist > 0 && dist < 60) {
|
||||||
|
return this.translateTime('OPERATION.MINUTE_AGO', Math.floor(dist));
|
||||||
|
}else if (dist > 60 && Math.floor(dist / 60) < 24) {
|
||||||
|
return this.translateTime('OPERATION.HOUR_AGO', Math.floor(dist / 60));
|
||||||
|
} else if (Math.floor(dist / 60) >= 24 && Math.floor(dist / 60) <= 48) {
|
||||||
|
return this.translateTime('OPERATION.DAY_AGO', Math.floor(dist / 60 / 24));
|
||||||
|
} else {
|
||||||
|
return this.translateTime('OPERATION.SECOND_AGO');
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
translateTime(tim: string, param?: number) {
|
||||||
|
this.translate.get(tim, { 'param': param }).subscribe((res: string) => {
|
||||||
|
return res;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
15
src/ui_ng/lib/src/operation/operation.service.ts
Normal file
15
src/ui_ng/lib/src/operation/operation.service.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Subject } from 'rxjs/Subject';
|
||||||
|
import {OperateInfo} from "./operate";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class OperationService {
|
||||||
|
subjects: Subject<any> = null;
|
||||||
|
|
||||||
|
operationInfoSource = new Subject<OperateInfo>();
|
||||||
|
operationInfo$ = this.operationInfoSource.asObservable();
|
||||||
|
|
||||||
|
publishInfo(data: OperateInfo): void {
|
||||||
|
this.operationInfoSource.next(data);
|
||||||
|
}
|
||||||
|
}
|
@ -73,5 +73,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<job-log-viewer #replicationLogViewer></job-log-viewer>
|
<job-log-viewer #replicationLogViewer></job-log-viewer>
|
||||||
<hbr-create-edit-rule *ngIf="isSystemAdmin" [projectId]="projectId" [projectName]="projectName" (goToRegistry)="goRegistry()" (reload)="reloadRules($event)"></hbr-create-edit-rule>
|
<hbr-create-edit-rule *ngIf="isSystemAdmin" [projectId]="projectId" [projectName]="projectName" (goToRegistry)="goRegistry()" (reload)="reloadRules($event)"></hbr-create-edit-rule>
|
||||||
<confirmation-dialog #replicationConfirmDialog [batchInfors]="batchDelectionInfos" (confirmAction)="confirmReplication($event)"></confirmation-dialog>
|
<confirmation-dialog #replicationConfirmDialog (confirmAction)="confirmReplication($event)"></confirmation-dialog>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ import { EndpointService, EndpointDefaultService } from '../service/endpoint.ser
|
|||||||
import { JobLogViewerComponent } from '../job-log-viewer/job-log-viewer.component';
|
import { JobLogViewerComponent } from '../job-log-viewer/job-log-viewer.component';
|
||||||
import { JobLogService, JobLogDefaultService, ReplicationJobItem } from '../service/index';
|
import { JobLogService, JobLogDefaultService, ReplicationJobItem } from '../service/index';
|
||||||
import {ProjectDefaultService, ProjectService} from "../service/project.service";
|
import {ProjectDefaultService, ProjectService} from "../service/project.service";
|
||||||
|
import {OperationService} from "../operation/operation.service";
|
||||||
|
|
||||||
describe('Replication Component (inline template)', () => {
|
describe('Replication Component (inline template)', () => {
|
||||||
|
|
||||||
@ -231,7 +232,8 @@ describe('Replication Component (inline template)', () => {
|
|||||||
{ provide: ReplicationService, useClass: ReplicationDefaultService },
|
{ provide: ReplicationService, useClass: ReplicationDefaultService },
|
||||||
{ provide: EndpointService, useClass: EndpointDefaultService },
|
{ provide: EndpointService, useClass: EndpointDefaultService },
|
||||||
{ provide: ProjectService, useClass: ProjectDefaultService },
|
{ provide: ProjectService, useClass: ProjectDefaultService },
|
||||||
{ provide: JobLogService, useClass: JobLogDefaultService }
|
{ provide: JobLogService, useClass: JobLogDefaultService },
|
||||||
|
{ provide: OperationService }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
@ -56,12 +56,10 @@ import {
|
|||||||
ConfirmationState
|
ConfirmationState
|
||||||
} from "../shared/shared.const";
|
} from "../shared/shared.const";
|
||||||
import { ConfirmationMessage } from "../confirmation-dialog/confirmation-message";
|
import { ConfirmationMessage } from "../confirmation-dialog/confirmation-message";
|
||||||
import {
|
|
||||||
BatchInfo,
|
|
||||||
BathInfoChanges
|
|
||||||
} from "../confirmation-dialog/confirmation-batch-message";
|
|
||||||
import { ConfirmationDialogComponent } from "../confirmation-dialog/confirmation-dialog.component";
|
import { ConfirmationDialogComponent } from "../confirmation-dialog/confirmation-dialog.component";
|
||||||
import { ConfirmationAcknowledgement } from "../confirmation-dialog/confirmation-state-message";
|
import { ConfirmationAcknowledgement } from "../confirmation-dialog/confirmation-state-message";
|
||||||
|
import {operateChanges, OperationState, OperateInfo} from "../operation/operate";
|
||||||
|
import {OperationService} from "../operation/operation.service";
|
||||||
|
|
||||||
const ruleStatus: { [key: string]: any } = [
|
const ruleStatus: { [key: string]: any } = [
|
||||||
{ key: "all", description: "REPLICATION.ALL_STATUS" },
|
{ key: "all", description: "REPLICATION.ALL_STATUS" },
|
||||||
@ -130,7 +128,6 @@ export class ReplicationComponent implements OnInit, OnDestroy {
|
|||||||
hiddenJobList = true;
|
hiddenJobList = true;
|
||||||
|
|
||||||
jobs: ReplicationJobItem[];
|
jobs: ReplicationJobItem[];
|
||||||
batchDelectionInfos: BatchInfo[] = [];
|
|
||||||
|
|
||||||
toggleJobSearchOption = optionalSearch;
|
toggleJobSearchOption = optionalSearch;
|
||||||
currentJobSearchOption: number;
|
currentJobSearchOption: number;
|
||||||
@ -165,8 +162,8 @@ export class ReplicationComponent implements OnInit, OnDestroy {
|
|||||||
constructor(
|
constructor(
|
||||||
private errorHandler: ErrorHandler,
|
private errorHandler: ErrorHandler,
|
||||||
private replicationService: ReplicationService,
|
private replicationService: ReplicationService,
|
||||||
private translateService: TranslateService
|
private operationService: OperationService,
|
||||||
) {}
|
private translateService: TranslateService) {}
|
||||||
|
|
||||||
public get showPaginationIndex(): boolean {
|
public get showPaginationIndex(): boolean {
|
||||||
return this.totalCount > 0;
|
return this.totalCount > 0;
|
||||||
@ -307,10 +304,6 @@ export class ReplicationComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
replicateManualRule(rule: ReplicationRule) {
|
replicateManualRule(rule: ReplicationRule) {
|
||||||
if (rule) {
|
if (rule) {
|
||||||
this.batchDelectionInfos = [];
|
|
||||||
let initBatchMessage = new BatchInfo();
|
|
||||||
initBatchMessage.name = rule.name;
|
|
||||||
this.batchDelectionInfos.push(initBatchMessage);
|
|
||||||
let replicationMessage = new ConfirmationMessage(
|
let replicationMessage = new ConfirmationMessage(
|
||||||
"REPLICATION.REPLICATION_TITLE",
|
"REPLICATION.REPLICATION_TITLE",
|
||||||
"REPLICATION.REPLICATION_SUMMARY",
|
"REPLICATION.REPLICATION_SUMMARY",
|
||||||
@ -332,43 +325,37 @@ export class ReplicationComponent implements OnInit, OnDestroy {
|
|||||||
let rule: ReplicationRule = message.data;
|
let rule: ReplicationRule = message.data;
|
||||||
|
|
||||||
if (rule) {
|
if (rule) {
|
||||||
Promise.all([this.replicationOperate(+rule.id, rule.name)]).then(
|
Promise.all([this.replicationOperate(rule)]).then((item) => {
|
||||||
item => {
|
|
||||||
this.selectOneRule(rule);
|
this.selectOneRule(rule);
|
||||||
}
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
replicationOperate(ruleId: number, name: string) {
|
replicationOperate(rule: ReplicationRule) {
|
||||||
let findedList = this.batchDelectionInfos.find(data => data.name === name);
|
// init operation info
|
||||||
|
let operMessage = new OperateInfo();
|
||||||
|
operMessage.name = 'OPERATION.REPLICATION';
|
||||||
|
operMessage.data.id = rule.id;
|
||||||
|
operMessage.state = OperationState.progressing;
|
||||||
|
operMessage.data.name = rule.name;
|
||||||
|
this.operationService.publishInfo(operMessage);
|
||||||
|
|
||||||
return toPromise<any>(this.replicationService.replicateRule(ruleId))
|
return toPromise<any>(this.replicationService.replicateRule(+rule.id))
|
||||||
.then(response => {
|
.then(response => {
|
||||||
this.translateService
|
this.translateService.get('BATCH.REPLICATE_SUCCESS')
|
||||||
.get("BATCH.REPLICATE_SUCCESS")
|
.subscribe(res => operateChanges(operMessage, OperationState.success));
|
||||||
.subscribe(res => (findedList = BathInfoChanges(findedList, res)));
|
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
if (error && error.status === 412) {
|
if (error && error.status === 412) {
|
||||||
Observable.forkJoin(
|
Observable.forkJoin(this.translateService.get('BATCH.REPLICATE_FAILURE'),
|
||||||
this.translateService.get("BATCH.REPLICATE_FAILURE"),
|
this.translateService.get('REPLICATION.REPLICATE_SUMMARY_FAILURE'))
|
||||||
this.translateService.get("REPLICATION.REPLICATE_SUMMARY_FAILURE")
|
.subscribe(function (res) {
|
||||||
).subscribe(function(res) {
|
operateChanges(operMessage, OperationState.failure, res[1]);
|
||||||
findedList = BathInfoChanges(
|
|
||||||
findedList,
|
|
||||||
res[0],
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
res[1]
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.translateService
|
this.translateService.get('BATCH.REPLICATE_FAILURE').subscribe(res => {
|
||||||
.get("BATCH.REPLICATE_FAILURE")
|
operateChanges(operMessage, OperationState.failure, res);
|
||||||
.subscribe(res => {
|
|
||||||
findedList = BathInfoChanges(findedList, res, false, true);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
<div *ngIf="!isCardView" class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
<div *ngIf="!isCardView" class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||||
<clr-datagrid (clrDgRefresh)="clrLoad($event)" [clrDgLoading]="loading" [(clrDgSelected)]="selectedRow" (clrDgSelectedChange)="selectedChange()">
|
<clr-datagrid (clrDgRefresh)="clrLoad($event)" [clrDgLoading]="loading" [(clrDgSelected)]="selectedRow" (clrDgSelectedChange)="selectedChange()">
|
||||||
<clr-dg-action-bar>
|
<clr-dg-action-bar>
|
||||||
@ -44,6 +45,8 @@
|
|||||||
</clr-dg-footer>
|
</clr-dg-footer>
|
||||||
</clr-datagrid>
|
</clr-datagrid>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<hbr-gridview *ngIf="isCardView" #gridView style="position:relative;" [items]="repositories" [loading]="loading" [pageSize]="pageSize"
|
<hbr-gridview *ngIf="isCardView" #gridView style="position:relative;" [items]="repositories" [loading]="loading" [pageSize]="pageSize"
|
||||||
[currentPage]="currentPage" [totalCount]="totalCount" [expectScrollPercent]="90" [withAdmiral]="withAdmiral" (loadNextPageEvent)="loadNextPage()">
|
[currentPage]="currentPage" [totalCount]="totalCount" [expectScrollPercent]="90" [withAdmiral]="withAdmiral" (loadNextPageEvent)="loadNextPage()">
|
||||||
<ng-template let-item="item">
|
<ng-template let-item="item">
|
||||||
@ -90,5 +93,5 @@
|
|||||||
</a>
|
</a>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</hbr-gridview>
|
</hbr-gridview>
|
||||||
<confirmation-dialog #confirmationDialog [batchInfors]="batchDelectionInfos" (confirmAction)="confirmDeletion($event)"></confirmation-dialog>
|
<confirmation-dialog #confirmationDialog (confirmAction)="confirmDeletion($event)"></confirmation-dialog>
|
||||||
</div>
|
</div>
|
@ -22,6 +22,7 @@ import { PUSH_IMAGE_BUTTON_DIRECTIVES } from '../push-image/index';
|
|||||||
import { INLINE_ALERT_DIRECTIVES } from '../inline-alert/index';
|
import { INLINE_ALERT_DIRECTIVES } from '../inline-alert/index';
|
||||||
import { JobLogViewerComponent } from '../job-log-viewer/index';
|
import { JobLogViewerComponent } from '../job-log-viewer/index';
|
||||||
import {LabelPieceComponent} from "../label-piece/label-piece.component";
|
import {LabelPieceComponent} from "../label-piece/label-piece.component";
|
||||||
|
import {OperationService} from "../operation/operation.service";
|
||||||
|
|
||||||
describe('RepositoryComponentGridview (inline template)', () => {
|
describe('RepositoryComponentGridview (inline template)', () => {
|
||||||
|
|
||||||
@ -115,7 +116,8 @@ describe('RepositoryComponentGridview (inline template)', () => {
|
|||||||
{ provide: SERVICE_CONFIG, useValue: config },
|
{ provide: SERVICE_CONFIG, useValue: config },
|
||||||
{ provide: RepositoryService, useClass: RepositoryDefaultService },
|
{ provide: RepositoryService, useClass: RepositoryDefaultService },
|
||||||
{ provide: TagService, useClass: TagDefaultService },
|
{ provide: TagService, useClass: TagDefaultService },
|
||||||
{ provide: SystemInfoService, useClass: SystemInfoDefaultService }
|
{ provide: SystemInfoService, useClass: SystemInfoDefaultService },
|
||||||
|
{ provide: OperationService }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
@ -10,11 +10,11 @@ import {
|
|||||||
OnChanges,
|
OnChanges,
|
||||||
SimpleChanges
|
SimpleChanges
|
||||||
} from "@angular/core";
|
} from "@angular/core";
|
||||||
import { Router } from "@angular/router";
|
import {Router} from "@angular/router";
|
||||||
import { Observable } from "rxjs/Observable";
|
import {Observable} from "rxjs/Observable";
|
||||||
import "rxjs/add/observable/forkJoin";
|
import "rxjs/add/observable/forkJoin";
|
||||||
import { TranslateService } from "@ngx-translate/core";
|
import {TranslateService} from "@ngx-translate/core";
|
||||||
import { Comparator, State } from "clarity-angular";
|
import {Comparator, State} from "clarity-angular";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Repository,
|
Repository,
|
||||||
@ -24,31 +24,17 @@ import {
|
|||||||
RequestQueryParams,
|
RequestQueryParams,
|
||||||
RepositoryItem,
|
RepositoryItem,
|
||||||
TagService
|
TagService
|
||||||
} from "../service/index";
|
} from '../service/index';
|
||||||
import { ErrorHandler } from "../error-handler/error-handler";
|
import {ErrorHandler} from '../error-handler/error-handler';
|
||||||
import {
|
import {toPromise, CustomComparator, DEFAULT_PAGE_SIZE, calculatePage, doFiltering, doSorting, clone} from '../utils';
|
||||||
toPromise,
|
import {ConfirmationState, ConfirmationTargets, ConfirmationButtons} from '../shared/shared.const';
|
||||||
CustomComparator,
|
import {ConfirmationDialogComponent} from '../confirmation-dialog/confirmation-dialog.component';
|
||||||
DEFAULT_PAGE_SIZE,
|
import {ConfirmationMessage} from '../confirmation-dialog/confirmation-message';
|
||||||
calculatePage,
|
import {ConfirmationAcknowledgement} from '../confirmation-dialog/confirmation-state-message';
|
||||||
doFiltering,
|
import {Tag} from '../service/interface';
|
||||||
doSorting,
|
import {GridViewComponent} from '../gridview/grid-view.component';
|
||||||
clone
|
import {OperationService} from "../operation/operation.service";
|
||||||
} from "../utils";
|
import {OperateInfo, OperationState, operateChanges} from "../operation/operate";
|
||||||
import {
|
|
||||||
ConfirmationState,
|
|
||||||
ConfirmationTargets,
|
|
||||||
ConfirmationButtons
|
|
||||||
} 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 { Tag } from "../service/interface";
|
|
||||||
import {
|
|
||||||
BatchInfo,
|
|
||||||
BathInfoChanges
|
|
||||||
} from "../confirmation-dialog/confirmation-batch-message";
|
|
||||||
import { GridViewComponent } from "../gridview/grid-view.component";
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "hbr-repository-gridview",
|
selector: "hbr-repository-gridview",
|
||||||
@ -79,13 +65,8 @@ export class RepositoryGridviewComponent implements OnChanges, OnInit {
|
|||||||
cardHover = false;
|
cardHover = false;
|
||||||
listHover = false;
|
listHover = false;
|
||||||
|
|
||||||
batchDelectionInfos: BatchInfo[] = [];
|
pullCountComparator: Comparator<RepositoryItem> = new CustomComparator<RepositoryItem>('pull_count', 'number');
|
||||||
pullCountComparator: Comparator<RepositoryItem> = new CustomComparator<
|
tagsCountComparator: Comparator<RepositoryItem> = new CustomComparator<RepositoryItem>('tags_count', 'number');
|
||||||
RepositoryItem
|
|
||||||
>("pull_count", "number");
|
|
||||||
tagsCountComparator: Comparator<RepositoryItem> = new CustomComparator<
|
|
||||||
RepositoryItem
|
|
||||||
>("tags_count", "number");
|
|
||||||
|
|
||||||
pageSize: number = DEFAULT_PAGE_SIZE;
|
pageSize: number = DEFAULT_PAGE_SIZE;
|
||||||
currentPage = 1;
|
currentPage = 1;
|
||||||
@ -97,15 +78,15 @@ export class RepositoryGridviewComponent implements OnChanges, OnInit {
|
|||||||
|
|
||||||
@ViewChild("gridView") gridView: GridViewComponent;
|
@ViewChild("gridView") gridView: GridViewComponent;
|
||||||
|
|
||||||
constructor(
|
constructor(private errorHandler: ErrorHandler,
|
||||||
private errorHandler: ErrorHandler,
|
|
||||||
private translateService: TranslateService,
|
private translateService: TranslateService,
|
||||||
private repositoryService: RepositoryService,
|
private repositoryService: RepositoryService,
|
||||||
private systemInfoService: SystemInfoService,
|
private systemInfoService: SystemInfoService,
|
||||||
private tagService: TagService,
|
private tagService: TagService,
|
||||||
|
private operationService: OperationService,
|
||||||
private ref: ChangeDetectorRef,
|
private ref: ChangeDetectorRef,
|
||||||
private router: Router
|
private router: Router) {
|
||||||
) {}
|
}
|
||||||
|
|
||||||
public get registryUrl(): string {
|
public get registryUrl(): string {
|
||||||
return this.systemInfo ? this.systemInfo.registry_url : "";
|
return this.systemInfo ? this.systemInfo.registry_url : "";
|
||||||
@ -153,19 +134,18 @@ export class RepositoryGridviewComponent implements OnChanges, OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
confirmDeletion(message: ConfirmationAcknowledgement) {
|
confirmDeletion(message: ConfirmationAcknowledgement) {
|
||||||
if (
|
if (message &&
|
||||||
message &&
|
|
||||||
message.source === ConfirmationTargets.REPOSITORY &&
|
message.source === ConfirmationTargets.REPOSITORY &&
|
||||||
message.state === ConfirmationState.CONFIRMED
|
message.state === ConfirmationState.CONFIRMED) {
|
||||||
) {
|
|
||||||
let promiseLists: any[] = [];
|
|
||||||
let repoNames: string[] = message.data.split(",");
|
|
||||||
|
|
||||||
repoNames.forEach(repoName => {
|
let repoLists = message.data;
|
||||||
promiseLists.push(this.delOperate(repoName));
|
if (repoLists && repoLists.length) {
|
||||||
|
let promiseLists: any[] = [];
|
||||||
|
repoLists.forEach(repo => {
|
||||||
|
promiseLists.push(this.delOperate(repo));
|
||||||
});
|
});
|
||||||
|
|
||||||
Promise.all(promiseLists).then(item => {
|
Promise.all(promiseLists).then((item) => {
|
||||||
this.selectedRow = [];
|
this.selectedRow = [];
|
||||||
this.refresh();
|
this.refresh();
|
||||||
let st: State = this.getStateAfterDeletion();
|
let st: State = this.getStateAfterDeletion();
|
||||||
@ -177,60 +157,47 @@ export class RepositoryGridviewComponent implements OnChanges, OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
delOperate(repoName: string) {
|
delOperate(repo: RepositoryItem) {
|
||||||
let findedList = this.batchDelectionInfos.find(
|
// init operation info
|
||||||
data => data.name === repoName
|
let operMessage = new OperateInfo();
|
||||||
);
|
operMessage.name = 'OPERATION.DELETE_REPO';
|
||||||
if (this.signedCon[repoName].length !== 0) {
|
operMessage.data.id = repo.id;
|
||||||
Observable.forkJoin(
|
operMessage.state = OperationState.progressing;
|
||||||
this.translateService.get("BATCH.DELETED_FAILURE"),
|
operMessage.data.name = repo.name;
|
||||||
this.translateService.get("REPOSITORY.DELETION_TITLE_REPO_SIGNED")
|
this.operationService.publishInfo(operMessage);
|
||||||
).subscribe(res => {
|
|
||||||
findedList = BathInfoChanges(findedList, res[0], false, true, res[1]);
|
if (this.signedCon[repo.name].length !== 0) {
|
||||||
|
Observable.forkJoin(this.translateService.get('BATCH.DELETED_FAILURE'),
|
||||||
|
this.translateService.get('REPOSITORY.DELETION_TITLE_REPO_SIGNED')).subscribe(res => {
|
||||||
|
operateChanges(operMessage, OperationState.failure, res[1]);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return toPromise<number>(
|
return toPromise<number>(this.repositoryService
|
||||||
this.repositoryService.deleteRepository(repoName)
|
.deleteRepository(repo.name))
|
||||||
)
|
.then(
|
||||||
.then(response => {
|
response => {
|
||||||
this.translateService.get("BATCH.DELETED_SUCCESS").subscribe(res => {
|
this.translateService.get('BATCH.DELETED_SUCCESS').subscribe(res => {
|
||||||
findedList = BathInfoChanges(findedList, res);
|
operateChanges(operMessage, OperationState.success);
|
||||||
});
|
});
|
||||||
})
|
}).catch(error => {
|
||||||
.catch(error => {
|
|
||||||
if (error.status === "412") {
|
if (error.status === "412") {
|
||||||
Observable.forkJoin(
|
Observable.forkJoin(this.translateService.get('BATCH.DELETED_FAILURE'),
|
||||||
this.translateService.get("BATCH.DELETED_FAILURE"),
|
this.translateService.get('REPOSITORY.TAGS_SIGNED')).subscribe(res => {
|
||||||
this.translateService.get("REPOSITORY.TAGS_SIGNED")
|
operateChanges(operMessage, OperationState.failure, res[1]);
|
||||||
).subscribe(res => {
|
|
||||||
findedList = BathInfoChanges(
|
|
||||||
findedList,
|
|
||||||
res[0],
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
res[1]
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (error.status === 503) {
|
if (error.status === 503) {
|
||||||
Observable.forkJoin(
|
Observable.forkJoin(this.translateService.get('BATCH.DELETED_FAILURE'),
|
||||||
this.translateService.get("BATCH.DELETED_FAILURE"),
|
this.translateService.get('REPOSITORY.TAGS_NO_DELETE')).subscribe(res => {
|
||||||
this.translateService.get("REPOSITORY.TAGS_NO_DELETE")
|
operateChanges(operMessage, OperationState.failure, res[1]);
|
||||||
).subscribe(res => {
|
|
||||||
findedList = BathInfoChanges(
|
|
||||||
findedList,
|
|
||||||
res[0],
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
res[1]
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.translateService.get("BATCH.DELETED_FAILURE").subscribe(res => {
|
this.translateService.get('BATCH.DELETED_FAILURE').subscribe(res => {
|
||||||
findedList = BathInfoChanges(findedList, res, false, true);
|
operateChanges(operMessage, OperationState.failure, res);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -241,7 +208,7 @@ export class RepositoryGridviewComponent implements OnChanges, OnInit {
|
|||||||
this.currentPage = 1;
|
this.currentPage = 1;
|
||||||
let st: State = this.currentState;
|
let st: State = this.currentState;
|
||||||
if (!st) {
|
if (!st) {
|
||||||
st = { page: {} };
|
st = {page: {}};
|
||||||
}
|
}
|
||||||
st.page.size = this.pageSize;
|
st.page.size = this.pageSize;
|
||||||
st.page.from = 0;
|
st.page.from = 0;
|
||||||
@ -256,14 +223,10 @@ export class RepositoryGridviewComponent implements OnChanges, OnInit {
|
|||||||
deleteRepos(repoLists: RepositoryItem[]) {
|
deleteRepos(repoLists: RepositoryItem[]) {
|
||||||
if (repoLists && repoLists.length) {
|
if (repoLists && repoLists.length) {
|
||||||
let repoNames: string[] = [];
|
let repoNames: string[] = [];
|
||||||
this.batchDelectionInfos = [];
|
|
||||||
let repArr: any[] = [];
|
let repArr: any[] = [];
|
||||||
|
|
||||||
repoLists.forEach(repo => {
|
repoLists.forEach(repo => {
|
||||||
repoNames.push(repo.name);
|
repoNames.push(repo.name);
|
||||||
let initBatchMessage = new BatchInfo();
|
|
||||||
initBatchMessage.name = repo.name;
|
|
||||||
this.batchDelectionInfos.push(initBatchMessage);
|
|
||||||
|
|
||||||
if (!this.signedCon[repo.name]) {
|
if (!this.signedCon[repo.name]) {
|
||||||
repArr.push(this.getTagInfo(repo.name));
|
repArr.push(this.getTagInfo(repo.name));
|
||||||
@ -272,12 +235,12 @@ export class RepositoryGridviewComponent implements OnChanges, OnInit {
|
|||||||
|
|
||||||
Promise.all(repArr).then(() => {
|
Promise.all(repArr).then(() => {
|
||||||
this.confirmationDialogSet(
|
this.confirmationDialogSet(
|
||||||
"REPOSITORY.DELETION_TITLE_REPO",
|
'REPOSITORY.DELETION_TITLE_REPO',
|
||||||
"",
|
'',
|
||||||
repoNames.join(","),
|
repoNames.join(','),
|
||||||
"REPOSITORY.DELETION_SUMMARY_REPO",
|
repoLists,
|
||||||
ConfirmationButtons.DELETE_CANCEL
|
'REPOSITORY.DELETION_SUMMARY_REPO',
|
||||||
);
|
ConfirmationButtons.DELETE_CANCEL);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -295,39 +258,13 @@ export class RepositoryGridviewComponent implements OnChanges, OnInit {
|
|||||||
.catch(error => this.errorHandler.error(error));
|
.catch(error => this.errorHandler.error(error));
|
||||||
}
|
}
|
||||||
|
|
||||||
signedDataSet(repoName: string): void {
|
confirmationDialogSet(summaryTitle: string, signature: string,
|
||||||
let signature = "";
|
repoName: string, repoLists: RepositoryItem[],
|
||||||
if (this.signedCon[repoName].length === 0) {
|
summaryKey: string, button: ConfirmationButtons): void {
|
||||||
this.confirmationDialogSet(
|
this.translateService.get(summaryKey,
|
||||||
"REPOSITORY.DELETION_TITLE_REPO",
|
{
|
||||||
signature,
|
|
||||||
repoName,
|
|
||||||
"REPOSITORY.DELETION_SUMMARY_REPO",
|
|
||||||
ConfirmationButtons.DELETE_CANCEL
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
signature = this.signedCon[repoName].join(",");
|
|
||||||
this.confirmationDialogSet(
|
|
||||||
"REPOSITORY.DELETION_TITLE_REPO_SIGNED",
|
|
||||||
signature,
|
|
||||||
repoName,
|
|
||||||
"REPOSITORY.DELETION_SUMMARY_REPO_SIGNED",
|
|
||||||
ConfirmationButtons.CLOSE
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
confirmationDialogSet(
|
|
||||||
summaryTitle: string,
|
|
||||||
signature: string,
|
|
||||||
repoName: string,
|
|
||||||
summaryKey: string,
|
|
||||||
button: ConfirmationButtons
|
|
||||||
): void {
|
|
||||||
this.translateService
|
|
||||||
.get(summaryKey, {
|
|
||||||
repoName: repoName,
|
repoName: repoName,
|
||||||
signedImages: signature
|
signedImages: signature,
|
||||||
})
|
})
|
||||||
.subscribe((res: string) => {
|
.subscribe((res: string) => {
|
||||||
summaryKey = res;
|
summaryKey = res;
|
||||||
@ -335,25 +272,29 @@ export class RepositoryGridviewComponent implements OnChanges, OnInit {
|
|||||||
summaryTitle,
|
summaryTitle,
|
||||||
summaryKey,
|
summaryKey,
|
||||||
repoName,
|
repoName,
|
||||||
repoName,
|
repoLists,
|
||||||
ConfirmationTargets.REPOSITORY,
|
ConfirmationTargets.REPOSITORY,
|
||||||
button
|
button);
|
||||||
);
|
|
||||||
this.confirmationDialog.open(message);
|
this.confirmationDialog.open(message);
|
||||||
|
|
||||||
let hnd = setInterval(() => this.ref.markForCheck(), 100);
|
let hnd = setInterval(() => this.ref.markForCheck(), 100);
|
||||||
setTimeout(() => clearInterval(hnd), 5000);
|
setTimeout(() => clearInterval(hnd), 5000);
|
||||||
});
|
});
|
||||||
|
let hnd = setInterval(() => this.ref.markForCheck(), 100);
|
||||||
|
setTimeout(() => clearInterval(hnd), 5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
containsLatestTag(repo: RepositoryItem): Promise<boolean> {
|
containsLatestTag(repo: RepositoryItem): Promise<boolean> {
|
||||||
return toPromise<Tag[]>(this.tagService.getTags(repo.name))
|
return toPromise<Tag[]>(this.tagService.getTags(repo.name))
|
||||||
.then(items => {
|
.then(items => {
|
||||||
if (items.some((t: Tag) => { return t.name === 'latest'; })) {
|
if (items.some((t: Tag) => {
|
||||||
|
return t.name === 'latest';
|
||||||
|
})) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
};
|
}
|
||||||
|
;
|
||||||
})
|
})
|
||||||
.catch(error => Promise.reject(false));
|
.catch(error => Promise.reject(false));
|
||||||
}
|
}
|
||||||
@ -370,7 +311,7 @@ export class RepositoryGridviewComponent implements OnChanges, OnInit {
|
|||||||
this.addInfoEvent.emit(repoCopy);
|
this.addInfoEvent.emit(repoCopy);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch( error => this.errorHandler.error(error));
|
.catch(error => this.errorHandler.error(error));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,18 +337,13 @@ export class RepositoryGridviewComponent implements OnChanges, OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadNextPage() {
|
loadNextPage() {
|
||||||
if (this.currentPage * this.pageSize >= this.totalCount) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.currentPage = this.currentPage + 1;
|
this.currentPage = this.currentPage + 1;
|
||||||
|
|
||||||
// Pagination
|
// Pagination
|
||||||
let params: RequestQueryParams = new RequestQueryParams();
|
let params: RequestQueryParams = new RequestQueryParams();
|
||||||
params.set("page", "" + this.currentPage);
|
params.set("page", "" + this.currentPage);
|
||||||
params.set("page_size", "" + this.pageSize);
|
params.set("page_size", "" + this.pageSize);
|
||||||
|
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
|
||||||
toPromise<Repository>(
|
toPromise<Repository>(
|
||||||
this.repositoryService.getRepositories(
|
this.repositoryService.getRepositories(
|
||||||
this.projectId,
|
this.projectId,
|
||||||
@ -502,7 +438,7 @@ export class RepositoryGridviewComponent implements OnChanges, OnInit {
|
|||||||
|
|
||||||
let st: State = this.currentState;
|
let st: State = this.currentState;
|
||||||
if (!st) {
|
if (!st) {
|
||||||
st = { page: {} };
|
st = {page: {}};
|
||||||
}
|
}
|
||||||
st.page.size = this.pageSize;
|
st.page.size = this.pageSize;
|
||||||
st.page.from = (targetPageNumber - 1) * this.pageSize;
|
st.page.from = (targetPageNumber - 1) * this.pageSize;
|
||||||
@ -525,6 +461,7 @@ export class RepositoryGridviewComponent implements OnChanges, OnInit {
|
|||||||
}
|
}
|
||||||
return "No description for this repo. You can add it to this repository.";
|
return "No description for this repo. You can add it to this repository.";
|
||||||
}
|
}
|
||||||
|
|
||||||
showCard(cardView: boolean) {
|
showCard(cardView: boolean) {
|
||||||
if (this.isCardView === cardView) {
|
if (this.isCardView === cardView) {
|
||||||
return;
|
return;
|
||||||
|
@ -25,6 +25,7 @@ import { TagService, TagDefaultService } from '../service/tag.service';
|
|||||||
import { ChannelService } from '../channel/index';
|
import { ChannelService } from '../channel/index';
|
||||||
import {LabelPieceComponent} from "../label-piece/label-piece.component";
|
import {LabelPieceComponent} from "../label-piece/label-piece.component";
|
||||||
import {LabelDefaultService, LabelService} from "../service/label.service";
|
import {LabelDefaultService, LabelService} from "../service/label.service";
|
||||||
|
import {OperationService} from "../operation/operation.service";
|
||||||
|
|
||||||
|
|
||||||
class RouterStub {
|
class RouterStub {
|
||||||
@ -174,6 +175,7 @@ describe('RepositoryComponent (inline template)', () => {
|
|||||||
{ provide: TagService, useClass: TagDefaultService },
|
{ provide: TagService, useClass: TagDefaultService },
|
||||||
{ provide: LabelService, useClass: LabelDefaultService},
|
{ provide: LabelService, useClass: LabelDefaultService},
|
||||||
{ provide: ChannelService},
|
{ provide: ChannelService},
|
||||||
|
{ provide: OperationService }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<confirmation-dialog class="hidden-tag" #confirmationDialog [batchInfors]="batchDelectionInfos" (confirmAction)="confirmDeletion($event)"></confirmation-dialog>
|
<confirmation-dialog class="hidden-tag" #confirmationDialog (confirmAction)="confirmDeletion($event)"></confirmation-dialog>
|
||||||
<clr-modal class="hidden-tag" [(clrModalOpen)]="showTagManifestOpened" [clrModalStaticBackdrop]="staticBackdrop" [clrModalClosable]="closable">
|
<clr-modal class="hidden-tag" [(clrModalOpen)]="showTagManifestOpened" [clrModalStaticBackdrop]="staticBackdrop" [clrModalClosable]="closable">
|
||||||
<h3 class="modal-title">{{ manifestInfoTitle | translate }}</h3>
|
<h3 class="modal-title">{{ manifestInfoTitle | translate }}</h3>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
|
@ -18,6 +18,7 @@ import { JobLogViewerComponent } from '../job-log-viewer/index';
|
|||||||
import {CopyInputComponent} from "../push-image/copy-input.component";
|
import {CopyInputComponent} from "../push-image/copy-input.component";
|
||||||
import {LabelPieceComponent} from "../label-piece/label-piece.component";
|
import {LabelPieceComponent} from "../label-piece/label-piece.component";
|
||||||
import {LabelDefaultService, LabelService} from "../service/label.service";
|
import {LabelDefaultService, LabelService} from "../service/label.service";
|
||||||
|
import {OperationService} from "../operation/operation.service";
|
||||||
|
|
||||||
describe('TagComponent (inline template)', () => {
|
describe('TagComponent (inline template)', () => {
|
||||||
|
|
||||||
@ -112,7 +113,8 @@ describe('TagComponent (inline template)', () => {
|
|||||||
{ provide: SERVICE_CONFIG, useValue: config },
|
{ provide: SERVICE_CONFIG, useValue: config },
|
||||||
{ provide: TagService, useClass: TagDefaultService },
|
{ provide: TagService, useClass: TagDefaultService },
|
||||||
{ provide: ScanningResultService, useClass: ScanningResultDefaultService },
|
{ provide: ScanningResultService, useClass: ScanningResultDefaultService },
|
||||||
{provide: LabelService, useClass: LabelDefaultService}
|
{provide: LabelService, useClass: LabelDefaultService},
|
||||||
|
{ provide: OperationService }
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
@ -53,11 +53,10 @@ import {
|
|||||||
clone,
|
clone,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
|
|
||||||
import {CopyInputComponent} from "../push-image/copy-input.component";
|
import {CopyInputComponent} from "../push-image/copy-input.component";
|
||||||
import {BatchInfo, BathInfoChanges} from "../confirmation-dialog/confirmation-batch-message";
|
|
||||||
|
|
||||||
import {LabelService} from "../service/label.service";
|
import {LabelService} from "../service/label.service";
|
||||||
|
import {operateChanges, OperateInfo, OperationState} from "../operation/operate";
|
||||||
|
import {OperationService} from "../operation/operation.service";
|
||||||
|
|
||||||
export interface LabelState {
|
export interface LabelState {
|
||||||
iconsShow: boolean;
|
iconsShow: boolean;
|
||||||
@ -97,7 +96,6 @@ export class TagComponent implements OnInit, AfterViewInit {
|
|||||||
staticBackdrop = true;
|
staticBackdrop = true;
|
||||||
closable = false;
|
closable = false;
|
||||||
lastFilteredTagName: string;
|
lastFilteredTagName: string;
|
||||||
batchDelectionInfos: BatchInfo[] = [];
|
|
||||||
inprogress: boolean;
|
inprogress: boolean;
|
||||||
openLabelFilterPanel: boolean;
|
openLabelFilterPanel: boolean;
|
||||||
openLabelFilterPiece: boolean;
|
openLabelFilterPiece: boolean;
|
||||||
@ -146,6 +144,7 @@ export class TagComponent implements OnInit, AfterViewInit {
|
|||||||
private labelService: LabelService,
|
private labelService: LabelService,
|
||||||
private translateService: TranslateService,
|
private translateService: TranslateService,
|
||||||
private ref: ChangeDetectorRef,
|
private ref: ChangeDetectorRef,
|
||||||
|
private operationService: OperationService,
|
||||||
private channel: ChannelService
|
private channel: ChannelService
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
@ -566,12 +565,8 @@ export class TagComponent implements OnInit, AfterViewInit {
|
|||||||
deleteTags(tags: Tag[]) {
|
deleteTags(tags: Tag[]) {
|
||||||
if (tags && tags.length) {
|
if (tags && tags.length) {
|
||||||
let tagNames: string[] = [];
|
let tagNames: string[] = [];
|
||||||
this.batchDelectionInfos = [];
|
|
||||||
tags.forEach(tag => {
|
tags.forEach(tag => {
|
||||||
tagNames.push(tag.name);
|
tagNames.push(tag.name);
|
||||||
let initBatchMessage = new BatchInfo ();
|
|
||||||
initBatchMessage.name = tag.name;
|
|
||||||
this.batchDelectionInfos.push(initBatchMessage);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let titleKey: string, summaryKey: string, content: string, buttons: ConfirmationButtons;
|
let titleKey: string, summaryKey: string, content: string, buttons: ConfirmationButtons;
|
||||||
@ -598,7 +593,7 @@ export class TagComponent implements OnInit, AfterViewInit {
|
|||||||
if (tags && tags.length) {
|
if (tags && tags.length) {
|
||||||
let promiseLists: any[] = [];
|
let promiseLists: any[] = [];
|
||||||
tags.forEach(tag => {
|
tags.forEach(tag => {
|
||||||
promiseLists.push(this.delOperate(tag.signature, tag.name));
|
promiseLists.push(this.delOperate(tag));
|
||||||
});
|
});
|
||||||
|
|
||||||
Promise.all(promiseLists).then((item) => {
|
Promise.all(promiseLists).then((item) => {
|
||||||
@ -609,34 +604,43 @@ export class TagComponent implements OnInit, AfterViewInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delOperate(signature: any, name: string) {
|
delOperate(tag: Tag) {
|
||||||
let findedList = this.batchDelectionInfos.find(data => data.name === name);
|
// init operation info
|
||||||
if (signature) {
|
let operMessage = new OperateInfo();
|
||||||
|
operMessage.name = 'OPERATION.DELETE_TAG';
|
||||||
|
operMessage.data.id = tag.id;
|
||||||
|
operMessage.state = OperationState.progressing;
|
||||||
|
operMessage.data.name = tag.name;
|
||||||
|
this.operationService.publishInfo(operMessage);
|
||||||
|
|
||||||
|
if (tag.signature) {
|
||||||
Observable.forkJoin(this.translateService.get("BATCH.DELETED_FAILURE"),
|
Observable.forkJoin(this.translateService.get("BATCH.DELETED_FAILURE"),
|
||||||
this.translateService.get("REPOSITORY.DELETION_SUMMARY_TAG_DENIED")).subscribe(res => {
|
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 " +
|
let wrongInfo: string = res[1] + "notary -s https://" + this.registryUrl +
|
||||||
this.registryUrl + "/" + this.repoName + " " + name;
|
":4443 -d ~/.docker/trust remove -p " +
|
||||||
findedList = BathInfoChanges(findedList, res[0], false, true, wrongInfo);
|
this.registryUrl + "/" + this.repoName +
|
||||||
|
" " + name;
|
||||||
|
operateChanges(operMessage, OperationState.failure, wrongInfo);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return toPromise<number>(this.tagService
|
return toPromise<number>(this.tagService
|
||||||
.deleteTag(this.repoName, name))
|
.deleteTag(this.repoName, tag.name))
|
||||||
.then(
|
.then(
|
||||||
response => {
|
response => {
|
||||||
this.translateService.get("BATCH.DELETED_SUCCESS")
|
this.translateService.get("BATCH.DELETED_SUCCESS")
|
||||||
.subscribe(res => {
|
.subscribe(res => {
|
||||||
findedList = BathInfoChanges(findedList, res);
|
operateChanges(operMessage, OperationState.success);
|
||||||
});
|
});
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
if (error.status === 503) {
|
if (error.status === 503) {
|
||||||
Observable.forkJoin(this.translateService.get('BATCH.DELETED_FAILURE'),
|
Observable.forkJoin(this.translateService.get('BATCH.DELETED_FAILURE'),
|
||||||
this.translateService.get('REPOSITORY.TAGS_NO_DELETE')).subscribe(res => {
|
this.translateService.get('REPOSITORY.TAGS_NO_DELETE')).subscribe(res => {
|
||||||
findedList = BathInfoChanges(findedList, res[0], false, true, res[1]);
|
operateChanges(operMessage, OperationState.failure, res[1]);
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.translateService.get("BATCH.DELETED_FAILURE").subscribe(res => {
|
this.translateService.get("BATCH.DELETED_FAILURE").subscribe(res => {
|
||||||
findedList = BathInfoChanges(findedList, res, false, true);
|
operateChanges(operMessage, OperationState.failure, res);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,6 @@
|
|||||||
"clarity-icons": "^0.10.27",
|
"clarity-icons": "^0.10.27",
|
||||||
"clarity-ui": "^0.10.27",
|
"clarity-ui": "^0.10.27",
|
||||||
"core-js": "^2.4.1",
|
"core-js": "^2.4.1",
|
||||||
"harbor-ui": "0.7.19-dev.8",
|
|
||||||
"intl": "^1.2.5",
|
"intl": "^1.2.5",
|
||||||
"mutationobserver-shim": "^0.3.2",
|
"mutationobserver-shim": "^0.3.2",
|
||||||
"ngx-cookie": "^1.0.0",
|
"ngx-cookie": "^1.0.0",
|
||||||
@ -50,6 +49,7 @@
|
|||||||
"bootstrap": "4.0.0-alpha.5",
|
"bootstrap": "4.0.0-alpha.5",
|
||||||
"codelyzer": "~2.0.0-beta.4",
|
"codelyzer": "~2.0.0-beta.4",
|
||||||
"enhanced-resolve": "^3.0.0",
|
"enhanced-resolve": "^3.0.0",
|
||||||
|
"harbor-ui": "0.7.19-test-3",
|
||||||
"jasmine-core": "2.4.1",
|
"jasmine-core": "2.4.1",
|
||||||
"jasmine-spec-reporter": "2.5.0",
|
"jasmine-spec-reporter": "2.5.0",
|
||||||
"karma": "~1.7.0",
|
"karma": "~1.7.0",
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
</clr-vertical-nav-group-children>
|
</clr-vertical-nav-group-children>
|
||||||
</clr-vertical-nav-group>
|
</clr-vertical-nav-group>
|
||||||
</clr-vertical-nav>
|
</clr-vertical-nav>
|
||||||
|
<hbr-operation-model *ngIf="isUserExisting"></hbr-operation-model>
|
||||||
</div>
|
</div>
|
||||||
</clr-main-container>
|
</clr-main-container>
|
||||||
<account-settings-modal></account-settings-modal>
|
<account-settings-modal></account-settings-modal>
|
||||||
|
@ -34,9 +34,9 @@ import { StatisticHandler } from "../../shared/statictics/statistic-handler.serv
|
|||||||
import { ConfirmationDialogService } from "../../shared/confirmation-dialog/confirmation-dialog.service";
|
import { ConfirmationDialogService } from "../../shared/confirmation-dialog/confirmation-dialog.service";
|
||||||
import { MessageHandlerService } from "../../shared/message-handler/message-handler.service";
|
import { MessageHandlerService } from "../../shared/message-handler/message-handler.service";
|
||||||
import { ConfirmationMessage } from "../../shared/confirmation-dialog/confirmation-message";
|
import { ConfirmationMessage } from "../../shared/confirmation-dialog/confirmation-message";
|
||||||
import {BatchInfo, BathInfoChanges} from "../../shared/confirmation-dialog/confirmation-batch-message";
|
|
||||||
import { SearchTriggerService } from "../../base/global-search/search-trigger.service";
|
import { SearchTriggerService } from "../../base/global-search/search-trigger.service";
|
||||||
import {AppConfigService} from "../../app-config.service";
|
import {AppConfigService} from "../../app-config.service";
|
||||||
|
import {operateChanges, OperateInfo, OperationService, OperationState} from "harbor-ui";
|
||||||
|
|
||||||
import { Project } from "../project";
|
import { Project } from "../project";
|
||||||
import { ProjectService } from "../project.service";
|
import { ProjectService } from "../project.service";
|
||||||
@ -52,7 +52,6 @@ export class ListProjectComponent implements OnDestroy {
|
|||||||
filteredType = 0; // All projects
|
filteredType = 0; // All projects
|
||||||
searchKeyword = "";
|
searchKeyword = "";
|
||||||
selectedRow: Project[] = [];
|
selectedRow: Project[] = [];
|
||||||
batchDelectionInfos: BatchInfo[] = [];
|
|
||||||
|
|
||||||
@Output() addProject = new EventEmitter<void>();
|
@Output() addProject = new EventEmitter<void>();
|
||||||
|
|
||||||
@ -77,6 +76,7 @@ export class ListProjectComponent implements OnDestroy {
|
|||||||
private statisticHandler: StatisticHandler,
|
private statisticHandler: StatisticHandler,
|
||||||
private translate: TranslateService,
|
private translate: TranslateService,
|
||||||
private deletionDialogService: ConfirmationDialogService,
|
private deletionDialogService: ConfirmationDialogService,
|
||||||
|
private operationService: OperationService,
|
||||||
private ref: ChangeDetectorRef) {
|
private ref: ChangeDetectorRef) {
|
||||||
this.subscription = deletionDialogService.confirmationConfirm$.subscribe(message => {
|
this.subscription = deletionDialogService.confirmationConfirm$.subscribe(message => {
|
||||||
if (message &&
|
if (message &&
|
||||||
@ -214,15 +214,10 @@ export class ListProjectComponent implements OnDestroy {
|
|||||||
|
|
||||||
deleteProjects(p: Project[]) {
|
deleteProjects(p: Project[]) {
|
||||||
let nameArr: string[] = [];
|
let nameArr: string[] = [];
|
||||||
this.batchDelectionInfos = [];
|
|
||||||
if (p && p.length) {
|
if (p && p.length) {
|
||||||
p.forEach(data => {
|
p.forEach(data => {
|
||||||
nameArr.push(data.name);
|
nameArr.push(data.name);
|
||||||
let initBatchMessage = new BatchInfo ();
|
|
||||||
initBatchMessage.name = data.name;
|
|
||||||
this.batchDelectionInfos.push(initBatchMessage);
|
|
||||||
});
|
});
|
||||||
this.deletionDialogService.addBatchInfoList(this.batchDelectionInfos);
|
|
||||||
let deletionMessage = new ConfirmationMessage(
|
let deletionMessage = new ConfirmationMessage(
|
||||||
"PROJECT.DELETION_TITLE",
|
"PROJECT.DELETION_TITLE",
|
||||||
"PROJECT.DELETION_SUMMARY",
|
"PROJECT.DELETION_SUMMARY",
|
||||||
@ -238,7 +233,7 @@ export class ListProjectComponent implements OnDestroy {
|
|||||||
let observableLists: any[] = [];
|
let observableLists: any[] = [];
|
||||||
if (projects && projects.length) {
|
if (projects && projects.length) {
|
||||||
projects.forEach(data => {
|
projects.forEach(data => {
|
||||||
observableLists.push(this.delOperate(data.project_id, data.name));
|
observableLists.push(this.delOperate(data));
|
||||||
});
|
});
|
||||||
Promise.all(observableLists).then(item => {
|
Promise.all(observableLists).then(item => {
|
||||||
let st: State = this.getStateAfterDeletion();
|
let st: State = this.getStateAfterDeletion();
|
||||||
@ -253,24 +248,31 @@ export class ListProjectComponent implements OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delOperate(id: number, name: string) {
|
delOperate(project: Project) {
|
||||||
let findedList = this.batchDelectionInfos.find(list => list.name === name);
|
// init operation info
|
||||||
return this.proService.deleteProject(id)
|
let operMessage = new OperateInfo();
|
||||||
|
operMessage.name = 'OPERATION.DELETE_PROJECT';
|
||||||
|
operMessage.data.id = project.project_id;
|
||||||
|
operMessage.state = OperationState.progressing;
|
||||||
|
operMessage.data.name = project.name;
|
||||||
|
this.operationService.publishInfo(operMessage);
|
||||||
|
|
||||||
|
return this.proService.deleteProject(project.project_id)
|
||||||
.then(
|
.then(
|
||||||
() => {
|
() => {
|
||||||
this.translate.get("BATCH.DELETED_SUCCESS").subscribe(res => {
|
this.translate.get("BATCH.DELETED_SUCCESS").subscribe(res => {
|
||||||
findedList = BathInfoChanges(findedList, res);
|
operateChanges(operMessage, OperationState.success);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
if (error && error.status === 412) {
|
if (error && error.status === 412) {
|
||||||
Observable.forkJoin(this.translate.get("BATCH.DELETED_FAILURE"),
|
Observable.forkJoin(this.translate.get("BATCH.DELETED_FAILURE"),
|
||||||
this.translate.get("PROJECT.FAILED_TO_DELETE_PROJECT")).subscribe(res => {
|
this.translate.get("PROJECT.FAILED_TO_DELETE_PROJECT")).subscribe(res => {
|
||||||
findedList = BathInfoChanges(findedList, res[0], false, true, res[1]);
|
operateChanges(operMessage, OperationState.failure, res[1]);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.translate.get("BATCH.DELETED_FAILURE").subscribe(res => {
|
this.translate.get("BATCH.DELETED_FAILURE").subscribe(res => {
|
||||||
findedList = BathInfoChanges(findedList, res, false, true);
|
operateChanges(operMessage, OperationState.failure, res);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -34,8 +34,7 @@
|
|||||||
<clr-dg-row *clrDgItems="let m of members" [clrDgItem]="m">
|
<clr-dg-row *clrDgItems="let m of members" [clrDgItem]="m">
|
||||||
<clr-dg-cell>{{m.entity_name}}</clr-dg-cell>
|
<clr-dg-cell>{{m.entity_name}}</clr-dg-cell>
|
||||||
<clr-dg-cell>
|
<clr-dg-cell>
|
||||||
<span *ngIf="ChangeRoleOngoing(m.entity_name)" class="spinner spinner-inline"> Loading... </span>
|
<span>{{roleInfo[m.role_id] | translate}}</span>
|
||||||
<span *ngIf="!ChangeRoleOngoing(m.entity_name)">{{roleInfo[m.role_id] | translate}}</span>
|
|
||||||
</clr-dg-cell>
|
</clr-dg-cell>
|
||||||
</clr-dg-row>
|
</clr-dg-row>
|
||||||
<clr-dg-footer>
|
<clr-dg-footer>
|
||||||
|
@ -37,7 +37,7 @@ import { Subscription } from "rxjs/Subscription";
|
|||||||
|
|
||||||
import { Project } from "../../project/project";
|
import { Project } from "../../project/project";
|
||||||
import {TranslateService} from "@ngx-translate/core";
|
import {TranslateService} from "@ngx-translate/core";
|
||||||
import {BatchInfo, BathInfoChanges} from "../../shared/confirmation-dialog/confirmation-batch-message";
|
import {operateChanges, OperateInfo, OperationService, OperationState} from "harbor-ui";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: "member.component.html",
|
templateUrl: "member.component.html",
|
||||||
@ -62,8 +62,6 @@ export class MemberComponent implements OnInit, OnDestroy {
|
|||||||
roleNum: number;
|
roleNum: number;
|
||||||
isDelete = false;
|
isDelete = false;
|
||||||
isChangeRole = false;
|
isChangeRole = false;
|
||||||
batchActionInfos: BatchInfo[] = [];
|
|
||||||
batchDeletionInfos: BatchInfo[] = [];
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
@ -73,6 +71,7 @@ export class MemberComponent implements OnInit, OnDestroy {
|
|||||||
private messageHandlerService: MessageHandlerService,
|
private messageHandlerService: MessageHandlerService,
|
||||||
private OperateDialogService: ConfirmationDialogService,
|
private OperateDialogService: ConfirmationDialogService,
|
||||||
private session: SessionService,
|
private session: SessionService,
|
||||||
|
private operationService: OperationService,
|
||||||
private ref: ChangeDetectorRef) {
|
private ref: ChangeDetectorRef) {
|
||||||
|
|
||||||
this.delSub = OperateDialogService.confirmationConfirm$.subscribe(message => {
|
this.delSub = OperateDialogService.confirmationConfirm$.subscribe(message => {
|
||||||
@ -146,15 +145,6 @@ export class MemberComponent implements OnInit, OnDestroy {
|
|||||||
this.isDelete = false;
|
this.isDelete = false;
|
||||||
this.isChangeRole = true;
|
this.isChangeRole = true;
|
||||||
this.roleNum = roleId;
|
this.roleNum = roleId;
|
||||||
let nameArr: string[] = [];
|
|
||||||
this.batchActionInfos = [];
|
|
||||||
m.forEach(data => {
|
|
||||||
nameArr.push(data.entity_name);
|
|
||||||
let initBatchMessage = new BatchInfo();
|
|
||||||
initBatchMessage.name = data.entity_name;
|
|
||||||
this.batchActionInfos.push(initBatchMessage);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.changeOpe(m);
|
this.changeOpe(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -163,15 +153,7 @@ export class MemberComponent implements OnInit, OnDestroy {
|
|||||||
if (members && members.length) {
|
if (members && members.length) {
|
||||||
let promiseList: any[] = [];
|
let promiseList: any[] = [];
|
||||||
members.forEach(member => {
|
members.forEach(member => {
|
||||||
if (member.entity_id === this.currentUser.user_id) {
|
promiseList.push(this.changeOperate(this.projectId, this.roleNum, member));
|
||||||
let foundMember = this.batchActionInfos.find(batchInfo => batchInfo.name === member.entity_name);
|
|
||||||
this.translate.get("BATCH.SWITCH_FAILURE").subscribe(res => {
|
|
||||||
this.messageHandlerService.handleError(res + ": " + foundMember.name);
|
|
||||||
foundMember = BathInfoChanges(foundMember, res, false, true);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
promiseList.push(this.changeOperate(this.projectId, member.id, this.roleNum, member.entity_name));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Promise.all(promiseList).then(num => {
|
Promise.all(promiseList).then(num => {
|
||||||
@ -181,47 +163,45 @@ export class MemberComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
changeOperate(projectId: number, memberId: number, roleId: number, username: string) {
|
changeOperate(projectId: number, roleId: number, member: Member) {
|
||||||
let foundMember = this.batchActionInfos.find(batchInfo => batchInfo.name === username);
|
// init operation info
|
||||||
|
let operMessage = new OperateInfo();
|
||||||
|
operMessage.name = 'OPERATION.SWITCH_ROLE';
|
||||||
|
operMessage.data.id = member.id;
|
||||||
|
operMessage.state = OperationState.progressing;
|
||||||
|
operMessage.data.name = member.entity_name;
|
||||||
|
this.operationService.publishInfo(operMessage);
|
||||||
|
|
||||||
|
if (member.entity_id === this.currentUser.user_id) {
|
||||||
|
this.translate.get("BATCH.SWITCH_FAILURE").subscribe(res => {
|
||||||
|
operateChanges(operMessage, OperationState.failure, res);
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return this.memberService
|
return this.memberService
|
||||||
.changeMemberRole(projectId, memberId, roleId)
|
.changeMemberRole(projectId, member.id, roleId)
|
||||||
.then(
|
.then(
|
||||||
response => {
|
response => {
|
||||||
this.translate.get("BATCH.SWITCH_SUCCESS").subscribe(res => {
|
this.translate.get("BATCH.SWITCH_SUCCESS").subscribe(res => {
|
||||||
foundMember = BathInfoChanges(foundMember, res);
|
operateChanges(operMessage, OperationState.success);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
this.translate.get("BATCH.SWITCH_FAILURE").subscribe(res => {
|
this.translate.get("BATCH.SWITCH_FAILURE").subscribe(res => {
|
||||||
this.messageHandlerService.handleError(res + ": " + username);
|
operateChanges(operMessage, OperationState.failure, res);
|
||||||
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[]) {
|
deleteMembers(m: Member[]) {
|
||||||
this.isDelete = true;
|
this.isDelete = true;
|
||||||
this.isChangeRole = false;
|
this.isChangeRole = false;
|
||||||
let nameArr: string[] = [];
|
let nameArr: string[] = [];
|
||||||
this.batchDeletionInfos = [];
|
|
||||||
if (m && m.length) {
|
if (m && m.length) {
|
||||||
m.forEach(data => {
|
m.forEach(data => {
|
||||||
nameArr.push(data.entity_name);
|
nameArr.push(data.entity_name);
|
||||||
let initBatchMessage = new BatchInfo ();
|
|
||||||
initBatchMessage.name = data.entity_name;
|
|
||||||
this.batchDeletionInfos.push(initBatchMessage);
|
|
||||||
});
|
});
|
||||||
this.OperateDialogService.addBatchInfoList(this.batchDeletionInfos);
|
|
||||||
|
|
||||||
let deletionMessage = new ConfirmationMessage(
|
let deletionMessage = new ConfirmationMessage(
|
||||||
"MEMBER.DELETION_TITLE",
|
"MEMBER.DELETION_TITLE",
|
||||||
@ -239,15 +219,7 @@ export class MemberComponent implements OnInit, OnDestroy {
|
|||||||
if (members && members.length) {
|
if (members && members.length) {
|
||||||
let promiseLists: any[] = [];
|
let promiseLists: any[] = [];
|
||||||
members.forEach(member => {
|
members.forEach(member => {
|
||||||
if (member.entity_id === this.currentUser.user_id) {
|
promiseLists.push(this.delOperate(this.projectId, member));
|
||||||
let findedList = this.batchDeletionInfos.find(data => data.name === member.entity_name);
|
|
||||||
this.translate.get("BATCH.DELETED_FAILURE").subscribe(res => {
|
|
||||||
findedList = BathInfoChanges(findedList, res, false, true);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
promiseLists.push(this.delOperate(this.projectId, member.id, member.entity_name));
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Promise.all(promiseLists).then(item => {
|
Promise.all(promiseLists).then(item => {
|
||||||
@ -257,19 +229,33 @@ export class MemberComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delOperate(projectId: number, memberId: number, username: string) {
|
delOperate(projectId: number, member: Member) {
|
||||||
let findedList = this.batchDeletionInfos.find(data => data.name === username);
|
// init operation info
|
||||||
|
let operMessage = new OperateInfo();
|
||||||
|
operMessage.name = 'OPERATION.DELETE_MEMBER';
|
||||||
|
operMessage.data.id = member.id;
|
||||||
|
operMessage.state = OperationState.progressing;
|
||||||
|
operMessage.data.name = member.entity_name;
|
||||||
|
this.operationService.publishInfo(operMessage);
|
||||||
|
|
||||||
|
if (member.entity_id === this.currentUser.user_id) {
|
||||||
|
this.translate.get("BATCH.DELETED_FAILURE").subscribe(res => {
|
||||||
|
operateChanges(operMessage, OperationState.failure, res);
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return this.memberService
|
return this.memberService
|
||||||
.deleteMember(projectId, memberId)
|
.deleteMember(projectId, member.id)
|
||||||
.then(
|
.then(
|
||||||
response => {
|
response => {
|
||||||
this.translate.get("BATCH.DELETED_SUCCESS").subscribe(res => {
|
this.translate.get("BATCH.DELETED_SUCCESS").subscribe(res => {
|
||||||
findedList = BathInfoChanges(findedList, res);
|
operateChanges(operMessage, OperationState.success);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
this.translate.get("BATCH.DELETED_FAILURE").subscribe(res => {
|
this.translate.get("BATCH.DELETED_FAILURE").subscribe(res => {
|
||||||
findedList = BathInfoChanges(findedList, res, false, true);
|
operateChanges(operMessage, OperationState.failure, res);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
|
|
||||||
/**
|
|
||||||
* Created by pengf on 11/22/2017.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export class BatchInfo {
|
|
||||||
name: string;
|
|
||||||
status: string;
|
|
||||||
loading: boolean;
|
|
||||||
errorState: boolean;
|
|
||||||
errorInfo: string;
|
|
||||||
constructor() {
|
|
||||||
this.status = "pending";
|
|
||||||
this.loading = false;
|
|
||||||
this.errorState = false;
|
|
||||||
this.errorInfo = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function BathInfoChanges(list: BatchInfo, status: string, loading = false, errStatus = false, errorInfo = '') {
|
|
||||||
list.status = status;
|
|
||||||
list.loading = loading;
|
|
||||||
list.errorState = errStatus;
|
|
||||||
list.errorInfo = errorInfo;
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
@ -5,18 +5,6 @@
|
|||||||
<clr-icon shape="warning" class="is-warning" size="64"></clr-icon>
|
<clr-icon shape="warning" class="is-warning" size="64"></clr-icon>
|
||||||
</div>
|
</div>
|
||||||
<div class="confirmation-content">{{dialogContent}}</div>
|
<div class="confirmation-content">{{dialogContent}}</div>
|
||||||
<div>
|
|
||||||
<ul class="batchInfoUl">
|
|
||||||
<li *ngFor="let info of resultLists">
|
|
||||||
<span> <i class="spinner spinner-inline spinner-pos" [hidden]='!info.loading'></i> {{info.name}}</span>
|
|
||||||
<span *ngIf="!info.errorInfo.length" [style.color]="colorChange(info)">{{info.status}}</span>
|
|
||||||
<span *ngIf="info.errorInfo.length" [style.color]="colorChange(info)">
|
|
||||||
<a (click)="toggleErrorTitle(errorInfo)" >{{info.status}}</a><br>
|
|
||||||
<i #errorInfo style="display: none;">{{info.errorInfo}}</i>
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer" [ngSwitch]="buttons">
|
<div class="modal-footer" [ngSwitch]="buttons">
|
||||||
<ng-template [ngSwitchCase]="0">
|
<ng-template [ngSwitchCase]="0">
|
||||||
@ -29,8 +17,7 @@
|
|||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template [ngSwitchCase]="2">
|
<ng-template [ngSwitchCase]="2">
|
||||||
<button type="button" class="btn btn-outline" (click)="cancel()" [hidden]="isDelete">{{'BUTTON.CANCEL' | translate}}</button>
|
<button type="button" class="btn btn-outline" (click)="cancel()" [hidden]="isDelete">{{'BUTTON.CANCEL' | translate}}</button>
|
||||||
<button type="button" class="btn btn-danger" (click)="operate()" [hidden]="isDelete">{{'BUTTON.DELETE' | translate}}</button>
|
<button type="button" class="btn btn-danger" (click)="confirm()" [hidden]="isDelete">{{'BUTTON.DELETE' | translate}}</button>
|
||||||
<button type="button" class="btn btn-primary" (click)="cancel()" [disabled]="!batchOverStatus" [hidden]="!isDelete">{{'BUTTON.CLOSE' | translate}}</button>
|
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template [ngSwitchCase]="3">
|
<ng-template [ngSwitchCase]="3">
|
||||||
<button type="button" class="btn btn-primary" (click)="cancel()">{{'BUTTON.CLOSE' | translate}}</button>
|
<button type="button" class="btn btn-primary" (click)="cancel()">{{'BUTTON.CLOSE' | translate}}</button>
|
||||||
|
@ -19,7 +19,6 @@ import { ConfirmationDialogService } from './confirmation-dialog.service';
|
|||||||
import { ConfirmationMessage } from './confirmation-message';
|
import { ConfirmationMessage } from './confirmation-message';
|
||||||
import { ConfirmationAcknowledgement } from './confirmation-state-message';
|
import { ConfirmationAcknowledgement } from './confirmation-state-message';
|
||||||
import { ConfirmationState, ConfirmationTargets, ConfirmationButtons } from '../shared.const';
|
import { ConfirmationState, ConfirmationTargets, ConfirmationButtons } from '../shared.const';
|
||||||
import {BatchInfo} from "./confirmation-batch-message";
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'confiramtion-dialog',
|
selector: 'confiramtion-dialog',
|
||||||
@ -32,32 +31,9 @@ export class ConfirmationDialogComponent implements OnDestroy {
|
|||||||
dialogTitle: string = "";
|
dialogTitle: string = "";
|
||||||
dialogContent: string = "";
|
dialogContent: string = "";
|
||||||
message: ConfirmationMessage;
|
message: ConfirmationMessage;
|
||||||
resultLists: BatchInfo[] = [];
|
|
||||||
annouceSubscription: Subscription;
|
annouceSubscription: Subscription;
|
||||||
batchInfoSubscription: Subscription;
|
|
||||||
buttons: ConfirmationButtons;
|
buttons: ConfirmationButtons;
|
||||||
isDelete: boolean = false;
|
isDelete: boolean = false;
|
||||||
|
|
||||||
get batchOverStatus(): boolean {
|
|
||||||
if (this.resultLists.length) {
|
|
||||||
return this.resultLists.every(item => item.loading === false);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
colorChange(list: BatchInfo) {
|
|
||||||
if (!list.loading && !list.errorState) {
|
|
||||||
return 'green';
|
|
||||||
} else if (!list.loading && list.errorState) {
|
|
||||||
return 'red';
|
|
||||||
} else {
|
|
||||||
return '#666';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
toggleErrorTitle(errorSpan: any) {
|
|
||||||
errorSpan.style.display = (errorSpan.style.display === 'none') ? 'block' : 'none';
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private confirmationService: ConfirmationDialogService,
|
private confirmationService: ConfirmationDialogService,
|
||||||
private translate: TranslateService) {
|
private translate: TranslateService) {
|
||||||
@ -71,19 +47,12 @@ export class ConfirmationDialogComponent implements OnDestroy {
|
|||||||
this.buttons = msg.buttons;
|
this.buttons = msg.buttons;
|
||||||
this.open();
|
this.open();
|
||||||
});
|
});
|
||||||
this.batchInfoSubscription = confirmationService.confirmationBatch$.subscribe(data => {
|
|
||||||
this.resultLists = data;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
if (this.annouceSubscription) {
|
if (this.annouceSubscription) {
|
||||||
this.annouceSubscription.unsubscribe();
|
this.annouceSubscription.unsubscribe();
|
||||||
}
|
}
|
||||||
if (this.batchInfoSubscription) {
|
|
||||||
this.resultLists = [];
|
|
||||||
this.batchInfoSubscription.unsubscribe();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
open(): void {
|
open(): void {
|
||||||
@ -91,7 +60,6 @@ export class ConfirmationDialogComponent implements OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
close(): void {
|
close(): void {
|
||||||
this.resultLists = [];
|
|
||||||
this.opened = false;
|
this.opened = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,26 +81,6 @@ export class ConfirmationDialogComponent implements OnDestroy {
|
|||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
operate(): void {
|
|
||||||
if (!this.message) {// Improper condition
|
|
||||||
this.close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.resultLists.length) {
|
|
||||||
this.resultLists.every(item => item.loading = true);
|
|
||||||
this.isDelete = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let data: any = this.message.data ? this.message.data : {};
|
|
||||||
let target = this.message.targetId ? this.message.targetId : ConfirmationTargets.EMPTY;
|
|
||||||
this.confirmationService.confirm(new ConfirmationAcknowledgement(
|
|
||||||
ConfirmationState.CONFIRMED,
|
|
||||||
data,
|
|
||||||
target
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
confirm(): void {
|
confirm(): void {
|
||||||
if (!this.message) {
|
if (!this.message) {
|
||||||
// Inproper condition
|
// Inproper condition
|
||||||
|
@ -16,17 +16,14 @@ import { Subject } from 'rxjs/Subject';
|
|||||||
|
|
||||||
import { ConfirmationMessage } from './confirmation-message';
|
import { ConfirmationMessage } from './confirmation-message';
|
||||||
import { ConfirmationAcknowledgement } from './confirmation-state-message';
|
import { ConfirmationAcknowledgement } from './confirmation-state-message';
|
||||||
import {BatchInfo} from "./confirmation-batch-message";
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ConfirmationDialogService {
|
export class ConfirmationDialogService {
|
||||||
confirmationAnnoucedSource = new Subject<ConfirmationMessage>();
|
confirmationAnnoucedSource = new Subject<ConfirmationMessage>();
|
||||||
confirmationConfirmSource = new Subject<ConfirmationAcknowledgement>();
|
confirmationConfirmSource = new Subject<ConfirmationAcknowledgement>();
|
||||||
confirmationBatchSource = new Subject<BatchInfo[]>();
|
|
||||||
|
|
||||||
confirmationAnnouced$ = this.confirmationAnnoucedSource.asObservable();
|
confirmationAnnouced$ = this.confirmationAnnoucedSource.asObservable();
|
||||||
confirmationConfirm$ = this.confirmationConfirmSource.asObservable();
|
confirmationConfirm$ = this.confirmationConfirmSource.asObservable();
|
||||||
confirmationBatch$ = this.confirmationBatchSource.asObservable();
|
|
||||||
|
|
||||||
// User confirm the action
|
// User confirm the action
|
||||||
public confirm(ack: ConfirmationAcknowledgement): void {
|
public confirm(ack: ConfirmationAcknowledgement): void {
|
||||||
@ -42,7 +39,4 @@ export class ConfirmationDialogService {
|
|||||||
public openComfirmDialog(message: ConfirmationMessage): void {
|
public openComfirmDialog(message: ConfirmationMessage): void {
|
||||||
this.confirmationAnnoucedSource.next(message);
|
this.confirmationAnnoucedSource.next(message);
|
||||||
}
|
}
|
||||||
public addBatchInfoList(data: BatchInfo[]): void {
|
|
||||||
this.confirmationBatchSource.next(data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -20,14 +20,13 @@ import { TranslateService } from '@ngx-translate/core';
|
|||||||
import { ConfirmationState, ConfirmationTargets, ConfirmationButtons } from '../shared/shared.const';
|
import { ConfirmationState, ConfirmationTargets, ConfirmationButtons } from '../shared/shared.const';
|
||||||
import { ConfirmationDialogService } from '../shared/confirmation-dialog/confirmation-dialog.service';
|
import { ConfirmationDialogService } from '../shared/confirmation-dialog/confirmation-dialog.service';
|
||||||
import { ConfirmationMessage } from '../shared/confirmation-dialog/confirmation-message';
|
import { ConfirmationMessage } from '../shared/confirmation-dialog/confirmation-message';
|
||||||
import {BatchInfo, BathInfoChanges} from '../shared/confirmation-dialog/confirmation-batch-message';
|
|
||||||
import { MessageHandlerService } from '../shared/message-handler/message-handler.service';
|
import { MessageHandlerService } from '../shared/message-handler/message-handler.service';
|
||||||
import { SessionService } from '../shared/session.service';
|
import { SessionService } from '../shared/session.service';
|
||||||
import { AppConfigService } from '../app-config.service';
|
import { AppConfigService } from '../app-config.service';
|
||||||
|
|
||||||
import { NewUserModalComponent } from './new-user-modal.component';
|
import { NewUserModalComponent } from './new-user-modal.component';
|
||||||
import { UserService } from './user.service';
|
import { UserService } from './user.service';
|
||||||
import { User } from './user';
|
import { User } from './user';
|
||||||
|
import {operateChanges, OperateInfo, OperationService, OperationState} from "harbor-ui";
|
||||||
/**
|
/**
|
||||||
* NOTES:
|
* NOTES:
|
||||||
* Pagination for this component is a temporary workaround solution. It will be replaced in future release.
|
* Pagination for this component is a temporary workaround solution. It will be replaced in future release.
|
||||||
@ -51,7 +50,6 @@ export class UserComponent implements OnInit, OnDestroy {
|
|||||||
originalUsers: Promise<User[]>;
|
originalUsers: Promise<User[]>;
|
||||||
selectedRow: User[] = [];
|
selectedRow: User[] = [];
|
||||||
ISADMNISTRATOR: string = "USER.ENABLE_ADMIN_ACTION";
|
ISADMNISTRATOR: string = "USER.ENABLE_ADMIN_ACTION";
|
||||||
batchDelectionInfos: BatchInfo[] = [];
|
|
||||||
|
|
||||||
currentTerm: string;
|
currentTerm: string;
|
||||||
totalCount: number = 0;
|
totalCount: number = 0;
|
||||||
@ -72,6 +70,7 @@ export class UserComponent implements OnInit, OnDestroy {
|
|||||||
private msgHandler: MessageHandlerService,
|
private msgHandler: MessageHandlerService,
|
||||||
private session: SessionService,
|
private session: SessionService,
|
||||||
private appConfigService: AppConfigService,
|
private appConfigService: AppConfigService,
|
||||||
|
private operationService: OperationService,
|
||||||
private ref: ChangeDetectorRef) {
|
private ref: ChangeDetectorRef) {
|
||||||
this.deletionSubscription = deletionDialogService.confirmationConfirm$.subscribe(confirmed => {
|
this.deletionSubscription = deletionDialogService.confirmationConfirm$.subscribe(confirmed => {
|
||||||
if (confirmed &&
|
if (confirmed &&
|
||||||
@ -228,19 +227,15 @@ export class UserComponent implements OnInit, OnDestroy {
|
|||||||
// Delete the specified user
|
// Delete the specified user
|
||||||
deleteUsers(users: User[]): void {
|
deleteUsers(users: User[]): void {
|
||||||
let userArr: string[] = [];
|
let userArr: string[] = [];
|
||||||
this.batchDelectionInfos = [];
|
|
||||||
if (this.onlySelf) {
|
if (this.onlySelf) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (users && users.length) {
|
if (users && users.length) {
|
||||||
users.forEach(user => {
|
users.forEach(user => {
|
||||||
let initBatchMessage = new BatchInfo ();
|
|
||||||
initBatchMessage.name = user.username;
|
|
||||||
this.batchDelectionInfos.push(initBatchMessage);
|
|
||||||
userArr.push(user.username);
|
userArr.push(user.username);
|
||||||
});
|
});
|
||||||
this.deletionDialogService.addBatchInfoList(this.batchDelectionInfos);
|
}
|
||||||
// Confirm deletion
|
// Confirm deletion
|
||||||
let msg: ConfirmationMessage = new ConfirmationMessage(
|
let msg: ConfirmationMessage = new ConfirmationMessage(
|
||||||
"USER.DELETION_TITLE",
|
"USER.DELETION_TITLE",
|
||||||
@ -252,21 +247,12 @@ export class UserComponent implements OnInit, OnDestroy {
|
|||||||
);
|
);
|
||||||
this.deletionDialogService.openComfirmDialog(msg);
|
this.deletionDialogService.openComfirmDialog(msg);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
delUser(users: User[]): void {
|
delUser(users: User[]): void {
|
||||||
// this.batchInfoDialog.open();
|
|
||||||
let promiseLists: any[] = [];
|
let promiseLists: any[] = [];
|
||||||
if (users && users.length) {
|
if (users && users.length) {
|
||||||
users.forEach(user => {
|
users.forEach(user => {
|
||||||
let findedList = this.batchDelectionInfos.find(data => data.name === user.username);
|
promiseLists.push(this.delOperate(user));
|
||||||
if (this.isMySelf(user.user_id)) {
|
|
||||||
this.translate.get('BATCH.DELETED_FAILURE').subscribe(res => {
|
|
||||||
findedList = BathInfoChanges(findedList, res, false, true);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
promiseLists.push(this.delOperate(user.user_id, user.username));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Promise.all(promiseLists).then((item) => {
|
Promise.all(promiseLists).then((item) => {
|
||||||
@ -276,15 +262,31 @@ export class UserComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delOperate(id: number, name: string) {
|
|
||||||
let findedList = this.batchDelectionInfos.find(data => data.name === name);
|
delOperate(user: User) {
|
||||||
return this.userService.deleteUser(id).then(() => {
|
// init operation info
|
||||||
|
let operMessage = new OperateInfo();
|
||||||
|
operMessage.name = 'OPERATION.DELETE_USER';
|
||||||
|
operMessage.data.id = user.user_id;
|
||||||
|
operMessage.state = OperationState.progressing;
|
||||||
|
operMessage.data.name = user.username;
|
||||||
|
this.operationService.publishInfo(operMessage);
|
||||||
|
|
||||||
|
if (this.isMySelf(user.user_id)) {
|
||||||
|
this.translate.get('BATCH.DELETED_FAILURE').subscribe(res => {
|
||||||
|
operateChanges(operMessage, OperationState.failure, res);
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return this.userService.deleteUser(user.user_id).then(() => {
|
||||||
this.translate.get('BATCH.DELETED_SUCCESS').subscribe(res => {
|
this.translate.get('BATCH.DELETED_SUCCESS').subscribe(res => {
|
||||||
findedList = BathInfoChanges(findedList, res);
|
operateChanges(operMessage, OperationState.success);
|
||||||
});
|
});
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.translate.get('BATCH.DELETED_FAILURE').subscribe(res => {
|
this.translate.get('BATCH.DELETED_FAILURE').subscribe(res => {
|
||||||
findedList = BathInfoChanges(findedList, res, false, true);
|
operateChanges(operMessage, OperationState.failure, res);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -654,6 +654,27 @@
|
|||||||
"SATURDAY": "Saturday",
|
"SATURDAY": "Saturday",
|
||||||
"SUNDAY": "Sunday"
|
"SUNDAY": "Sunday"
|
||||||
},
|
},
|
||||||
|
"OPERATION": {
|
||||||
|
"LOCAL_EVENT": "Local Events",
|
||||||
|
"ALL": "All",
|
||||||
|
"RUNNING": "Running",
|
||||||
|
"FAILED": "Failed",
|
||||||
|
"DELETE_PROJECT": "Delete project",
|
||||||
|
"DELETE_REPO": "Delete repository",
|
||||||
|
"DELETE_TAG": "Delete tag",
|
||||||
|
"DELETE_USER": "Delete user",
|
||||||
|
"DELETE_REGISTRY": "Delete registry",
|
||||||
|
"DELETE_REPLICATION": "Delete replication",
|
||||||
|
"DELETE_MEMBER": "Delete member",
|
||||||
|
"SWITCH_ROLE": "Switch role",
|
||||||
|
"DELETE_LABEL": "Delete label",
|
||||||
|
"REPLICATION": "Replication",
|
||||||
|
"DAY_AGO": " day(s) ago",
|
||||||
|
"HOUR_AGO": " hour(s) ago",
|
||||||
|
"MINUTE_AGO": " minute(s) ago",
|
||||||
|
"SECOND_AGO": "less 1 minute",
|
||||||
|
"EVENT_LOG": "EVENT LOG"
|
||||||
|
},
|
||||||
"UNKNOWN_ERROR": "Unknown errors have occurred. Please try again later.",
|
"UNKNOWN_ERROR": "Unknown errors have occurred. Please try again later.",
|
||||||
"UNAUTHORIZED_ERROR": "Your session is invalid or has expired. You need to sign in to continue your action.",
|
"UNAUTHORIZED_ERROR": "Your session is invalid or has expired. You need to sign in to continue your action.",
|
||||||
"REPO_READ_ONLY": "Harbor is set to read-only mode, Deleting repository, tag and pushing image will be disabled under read-only mode.",
|
"REPO_READ_ONLY": "Harbor is set to read-only mode, Deleting repository, tag and pushing image will be disabled under read-only mode.",
|
||||||
|
@ -654,6 +654,27 @@
|
|||||||
"SATURDAY": "Saturday",
|
"SATURDAY": "Saturday",
|
||||||
"SUNDAY": "Sunday"
|
"SUNDAY": "Sunday"
|
||||||
},
|
},
|
||||||
|
"OPERATION": {
|
||||||
|
"LOCAL_EVENT": "Local Events",
|
||||||
|
"ALL": "All",
|
||||||
|
"RUNNING": "Running",
|
||||||
|
"FAILED": "Failed",
|
||||||
|
"DELETE_PROJECT": "Delete project",
|
||||||
|
"DELETE_REPO": "Delete repository",
|
||||||
|
"DELETE_TAG": "Delete tag",
|
||||||
|
"DELETE_USER": "Delete user",
|
||||||
|
"DELETE_REGISTRY": "Delete registry",
|
||||||
|
"DELETE_REPLICATION": "Delete replication",
|
||||||
|
"DELETE_MEMBER": "Delete member",
|
||||||
|
"SWITCH_ROLE": "Switch role",
|
||||||
|
"DELETE_LABEL": "Delete label",
|
||||||
|
"REPLICATION": "Replication",
|
||||||
|
"DAY_AGO": " day(s) ago",
|
||||||
|
"HOUR_AGO": " hour(s) ago",
|
||||||
|
"MINUTE_AGO": " minute(s) ago",
|
||||||
|
"SECOND_AGO": "less 1 minute",
|
||||||
|
"EVENT_LOG": "EVENT LOG"
|
||||||
|
},
|
||||||
"UNKNOWN_ERROR": "Ha ocurrido un error desconocido. Por favor, inténtelo de nuevo más tarde.",
|
"UNKNOWN_ERROR": "Ha ocurrido un error desconocido. Por favor, inténtelo de nuevo más tarde.",
|
||||||
"UNAUTHORIZED_ERROR": "La sesión no es válida o ha caducado. Necesita identificarse de nuevo para llevar a cabo esa acción.",
|
"UNAUTHORIZED_ERROR": "La sesión no es válida o ha caducado. Necesita identificarse de nuevo para llevar a cabo esa acción.",
|
||||||
"REPO_READ_ONLY": "Harbor is set to read-only mode, Deleting repository, tag and pushing image will be disabled under read-only mode.",
|
"REPO_READ_ONLY": "Harbor is set to read-only mode, Deleting repository, tag and pushing image will be disabled under read-only mode.",
|
||||||
|
@ -612,6 +612,27 @@
|
|||||||
"SATURDAY": "Saturday",
|
"SATURDAY": "Saturday",
|
||||||
"SUNDAY": "Sunday"
|
"SUNDAY": "Sunday"
|
||||||
},
|
},
|
||||||
|
"OPERATION": {
|
||||||
|
"LOCAL_EVENT": "Local Events",
|
||||||
|
"ALL": "All",
|
||||||
|
"RUNNING": "Running",
|
||||||
|
"FAILED": "Failed",
|
||||||
|
"DELETE_PROJECT": "Delete project",
|
||||||
|
"DELETE_REPO": "Delete repository",
|
||||||
|
"DELETE_TAG": "Delete tag",
|
||||||
|
"DELETE_USER": "Delete user",
|
||||||
|
"DELETE_REGISTRY": "Delete registry",
|
||||||
|
"DELETE_REPLICATION": "Delete replication",
|
||||||
|
"DELETE_MEMBER": "Delete member",
|
||||||
|
"SWITCH_ROLE": "Switch role",
|
||||||
|
"DELETE_LABEL": "Delete label",
|
||||||
|
"REPLICATION": "Replication",
|
||||||
|
"DAY_AGO": " day(s) ago",
|
||||||
|
"HOUR_AGO": " hour(s) ago",
|
||||||
|
"MINUTE_AGO": " minute(s) ago",
|
||||||
|
"SECOND_AGO": "less 1 minute",
|
||||||
|
"EVENT_LOG": "EVENT LOG"
|
||||||
|
},
|
||||||
"UNKNOWN_ERROR": "Des erreurs inconnues sont survenues. Veuillez réessayer plus tard.",
|
"UNKNOWN_ERROR": "Des erreurs inconnues sont survenues. Veuillez réessayer plus tard.",
|
||||||
"UNAUTHORIZED_ERROR": "Votre session est invalide ou a expiré. Vous devez vous connecter pour continuer votre action.",
|
"UNAUTHORIZED_ERROR": "Votre session est invalide ou a expiré. Vous devez vous connecter pour continuer votre action.",
|
||||||
"REPO_READ_ONLY": "Harbor is set to read-only mode, Deleting repository, tag and pushing image will be disabled under read-only mode.",
|
"REPO_READ_ONLY": "Harbor is set to read-only mode, Deleting repository, tag and pushing image will be disabled under read-only mode.",
|
||||||
|
@ -654,6 +654,27 @@
|
|||||||
"SATURDAY": "周六",
|
"SATURDAY": "周六",
|
||||||
"SUNDAY": "周日"
|
"SUNDAY": "周日"
|
||||||
},
|
},
|
||||||
|
"OPERATION": {
|
||||||
|
"LOCAL_EVENT": "本地事件",
|
||||||
|
"ALL": "所有",
|
||||||
|
"RUNNING": "进行中",
|
||||||
|
"FAILED": "失败",
|
||||||
|
"DELETE_PROJECT": "删除项目",
|
||||||
|
"DELETE_REPO": "删除仓库",
|
||||||
|
"DELETE_TAG": "删除镜像标签",
|
||||||
|
"DELETE_USER": "删除用户",
|
||||||
|
"DELETE_REGISTRY": "Delete registry",
|
||||||
|
"DELETE_REPLICATION": "删除复制",
|
||||||
|
"DELETE_MEMBER": "删除成员",
|
||||||
|
"SWITCH_ROLE": "切换角色",
|
||||||
|
"DELETE_LABEL": "删除标签",
|
||||||
|
"REPLICATION": "复制",
|
||||||
|
"DAY_AGO": "天前",
|
||||||
|
"HOUR_AGO": "小时前",
|
||||||
|
"MINUTE_AGO": "分钟前",
|
||||||
|
"SECOND_AGO": "少于一分钟",
|
||||||
|
"EVENT_LOG": "事件日志"
|
||||||
|
},
|
||||||
"UNKNOWN_ERROR": "发生未知错误,请稍后再试。",
|
"UNKNOWN_ERROR": "发生未知错误,请稍后再试。",
|
||||||
"UNAUTHORIZED_ERROR": "会话无效或者已经过期, 请重新登录以继续。",
|
"UNAUTHORIZED_ERROR": "会话无效或者已经过期, 请重新登录以继续。",
|
||||||
"REPO_READ_ONLY": "Harbor被设置为只读模式,在此模式下,不能删除仓库、标签及推送镜像。",
|
"REPO_READ_ONLY": "Harbor被设置为只读模式,在此模式下,不能删除仓库、标签及推送镜像。",
|
||||||
|
@ -103,7 +103,6 @@ Delete Repo
|
|||||||
Sleep 1
|
Sleep 1
|
||||||
Click Element xpath=//clr-modal//button[2]
|
Click Element xpath=//clr-modal//button[2]
|
||||||
Sleep 1
|
Sleep 1
|
||||||
Click Element xpath=//button[contains(.,"CLOSE")]
|
|
||||||
|
|
||||||
Delete Repo on CardView
|
Delete Repo on CardView
|
||||||
[Arguments] ${reponame}
|
[Arguments] ${reponame}
|
||||||
|
Loading…
Reference in New Issue
Block a user