Remove Confirmation on some simple batch actions

This commit is contained in:
Deng, Qian 2018-01-24 21:50:14 +08:00
parent 9a87c8b663
commit bec2780576
7 changed files with 176 additions and 200 deletions

View File

@ -1,6 +1,6 @@
<clr-modal [(clrModalOpen)]="createProjectOpened" [clrModalStaticBackdrop]="staticBackdrop" [clrModalClosable]="closable"> <clr-modal [(clrModalOpen)]="createProjectOpened" [clrModalStaticBackdrop]="staticBackdrop" [clrModalClosable]="closable">
<h3 class="modal-title">{{'PROJECT.NEW_PROJECT' | translate}}</h3> <h3 class="modal-title">{{'PROJECT.NEW_PROJECT' | translate}}</h3>
<inline-alert class="modal-title" (confirmEvt)="confirmCancel($event)"></inline-alert> <inline-alert class="modal-title"></inline-alert>
<div class="modal-body" style="height: 16.8em; overflow-y: hidden;"> <div class="modal-body" style="height: 16.8em; overflow-y: hidden;">
<form #projectForm="ngForm"> <form #projectForm="ngForm">
<section class="form-block"> <section class="form-block">

View File

@ -17,35 +17,34 @@ import {
Output, Output,
ViewChild, ViewChild,
AfterViewChecked, AfterViewChecked,
HostBinding,
OnInit, OnInit,
OnDestroy OnDestroy
} from '@angular/core'; } from "@angular/core";
import { Response } from '@angular/http'; import { Response } from "@angular/http";
import { NgForm } from '@angular/forms'; import { NgForm } from "@angular/forms";
import { Project } from '../project'; import { Project } from "../project";
import { ProjectService } from '../project.service'; import { ProjectService } from "../project.service";
import { MessageHandlerService } from '../../shared/message-handler/message-handler.service'; import { MessageHandlerService } from "../../shared/message-handler/message-handler.service";
import { InlineAlertComponent } from '../../shared/inline-alert/inline-alert.component'; import { InlineAlertComponent } from "../../shared/inline-alert/inline-alert.component";
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from "@ngx-translate/core";
import { Subject } from 'rxjs/Subject'; import { Subject } from "rxjs/Subject";
import 'rxjs/add/operator/debounceTime'; import "rxjs/add/operator/debounceTime";
import 'rxjs/add/operator/distinctUntilChanged'; import "rxjs/add/operator/distinctUntilChanged";
@Component({ @Component({
selector: 'create-project', selector: "create-project",
templateUrl: 'create-project.component.html', templateUrl: "create-project.component.html",
styleUrls: ['create-project.css'] styleUrls: ["create-project.css"]
}) })
export class CreateProjectComponent implements AfterViewChecked, OnInit, OnDestroy { export class CreateProjectComponent implements AfterViewChecked, OnInit, OnDestroy {
projectForm: NgForm; projectForm: NgForm;
@ViewChild('projectForm') @ViewChild("projectForm")
currentForm: NgForm; currentForm: NgForm;
project: Project = new Project(); project: Project = new Project();
@ -54,14 +53,14 @@ export class CreateProjectComponent implements AfterViewChecked, OnInit, OnDestr
createProjectOpened: boolean; createProjectOpened: boolean;
hasChanged: boolean; hasChanged: boolean;
isSubmitOnGoing:boolean=false; isSubmitOnGoing = false;
staticBackdrop: boolean = true; staticBackdrop = true;
closable: boolean = false; closable = false;
isNameValid: boolean = true; isNameValid = true;
nameTooltipText: string = 'PROJECT.NAME_TOOLTIP'; nameTooltipText = "PROJECT.NAME_TOOLTIP";
checkOnGoing: boolean = false; checkOnGoing = false;
proNameChecker: Subject<string> = new Subject<string>(); proNameChecker: Subject<string> = new Subject<string>();
@Output() create = new EventEmitter<boolean>(); @Output() create = new EventEmitter<boolean>();
@ -71,7 +70,6 @@ export class CreateProjectComponent implements AfterViewChecked, OnInit, OnDestr
constructor(private projectService: ProjectService, constructor(private projectService: ProjectService,
private translateService: TranslateService, private translateService: TranslateService,
private messageHandlerService: MessageHandlerService) { } private messageHandlerService: MessageHandlerService) { }
ngOnInit(): void { ngOnInit(): void {
this.proNameChecker this.proNameChecker
@ -82,20 +80,20 @@ export class CreateProjectComponent implements AfterViewChecked, OnInit, OnDestr
if (cont && this.hasChanged) { if (cont && this.hasChanged) {
this.isNameValid = cont.valid; this.isNameValid = cont.valid;
if (this.isNameValid) { if (this.isNameValid) {
//Check exiting from backend // Check exiting from backend
this.projectService this.projectService
.checkProjectExists(cont.value).toPromise() .checkProjectExists(cont.value).toPromise()
.then(() => { .then(() => {
//Project existing // Project existing
this.isNameValid = false; this.isNameValid = false;
this.nameTooltipText = 'PROJECT.NAME_ALREADY_EXISTS'; this.nameTooltipText = "PROJECT.NAME_ALREADY_EXISTS";
this.checkOnGoing = false; this.checkOnGoing = false;
}) })
.catch(error => { .catch(error => {
this.checkOnGoing = false; this.checkOnGoing = false;
}); });
} else { } else {
this.nameTooltipText = 'PROJECT.NAME_TOOLTIP'; this.nameTooltipText = "PROJECT.NAME_TOOLTIP";
} }
} }
}); });
@ -106,35 +104,35 @@ export class CreateProjectComponent implements AfterViewChecked, OnInit, OnDestr
} }
onSubmit() { onSubmit() {
if (this.isSubmitOnGoing){ if (this.isSubmitOnGoing) {
return ; return ;
} }
this.isSubmitOnGoing=true; this.isSubmitOnGoing = true;
this.projectService this.projectService
.createProject(this.project.name, this.project.metadata) .createProject(this.project.name, this.project.metadata)
.subscribe( .subscribe(
status => { status => {
this.isSubmitOnGoing=false; this.isSubmitOnGoing = false;
this.create.emit(true); this.create.emit(true);
this.messageHandlerService.showSuccess('PROJECT.CREATED_SUCCESS'); this.messageHandlerService.showSuccess("PROJECT.CREATED_SUCCESS");
this.createProjectOpened = false; this.createProjectOpened = false;
}, },
error => { error => {
this.isSubmitOnGoing=false; this.isSubmitOnGoing = false;
let errorMessage: string; let errorMessage: string;
if (error instanceof Response) { if (error instanceof Response) {
switch (error.status) { switch (error.status) {
case 409: case 409:
this.translateService.get('PROJECT.NAME_ALREADY_EXISTS').subscribe(res => errorMessage = res); this.translateService.get("PROJECT.NAME_ALREADY_EXISTS").subscribe(res => errorMessage = res);
break; break;
case 400: case 400:
this.translateService.get('PROJECT.NAME_IS_ILLEGAL').subscribe(res => errorMessage = res); this.translateService.get("PROJECT.NAME_IS_ILLEGAL").subscribe(res => errorMessage = res);
break; break;
default: default:
this.translateService.get('PROJECT.UNKNOWN_ERROR').subscribe(res => errorMessage = res); this.translateService.get("PROJECT.UNKNOWN_ERROR").subscribe(res => errorMessage = res);
} }
if (this.messageHandlerService.isAppLevel(error)) { if (this.messageHandlerService.isAppLevel(error)) {
this.messageHandlerService.handleError(error); this.messageHandlerService.handleError(error);
@ -147,13 +145,8 @@ export class CreateProjectComponent implements AfterViewChecked, OnInit, OnDestr
} }
onCancel() { onCancel() {
if (this.hasChanged) {
this.inlineAlert.showInlineConfirmation({ message: 'ALERT.FORM_CHANGE_CONFIRMATION' });
} else {
this.createProjectOpened = false; this.createProjectOpened = false;
this.projectForm.reset(); this.projectForm.reset();
}
} }
ngAfterViewChecked(): void { ngAfterViewChecked(): void {
@ -181,21 +174,15 @@ export class CreateProjectComponent implements AfterViewChecked, OnInit, OnDestr
this.createProjectOpened = true; this.createProjectOpened = true;
} }
confirmCancel(event: boolean): void {
this.createProjectOpened = false;
this.inlineAlert.close();
this.projectForm.reset();
}
public get isValid(): boolean { public get isValid(): boolean {
return this.currentForm && return this.currentForm &&
this.currentForm.valid && this.currentForm.valid &&
!this.isSubmitOnGoing&& !this.isSubmitOnGoing &&
this.isNameValid && this.isNameValid &&
!this.checkOnGoing; !this.checkOnGoing;
} }
//Handle the form validation // Handle the form validation
handleValidation(): void { handleValidation(): void {
let cont = this.currentForm.controls["create_project_name"]; let cont = this.currentForm.controls["create_project_name"];
if (cont) { if (cont) {

View File

@ -14,42 +14,41 @@
import { import {
Component, Component,
Output, Output,
Input,
ChangeDetectionStrategy, ChangeDetectionStrategy,
ChangeDetectorRef, ChangeDetectorRef,
OnDestroy, EventEmitter OnDestroy, EventEmitter
} from '@angular/core'; } from "@angular/core";
import { Router, NavigationExtras } from '@angular/router'; import { Router } from "@angular/router";
import { Project } from '../project'; import { Project } from "../project";
import { ProjectService } from '../project.service'; import { ProjectService } from "../project.service";
import { SessionService } from '../../shared/session.service'; import { SessionService } from "../../shared/session.service";
import { SearchTriggerService } from '../../base/global-search/search-trigger.service'; import { SearchTriggerService } from "../../base/global-search/search-trigger.service";
import { ProjectTypes, RoleInfo } from '../../shared/shared.const'; import { RoleInfo } from "../../shared/shared.const";
import { CustomComparator, doFiltering, doSorting, calculatePage } from '../../shared/shared.utils'; import { CustomComparator, doFiltering, doSorting, calculatePage } from "../../shared/shared.utils";
import { Comparator, State } from 'clarity-angular'; import { Comparator, State } from "clarity-angular";
import { MessageHandlerService } from '../../shared/message-handler/message-handler.service'; import { MessageHandlerService } from "../../shared/message-handler/message-handler.service";
import { StatisticHandler } from '../../shared/statictics/statistic-handler.service'; import { StatisticHandler } from "../../shared/statictics/statistic-handler.service";
import { Subscription } from 'rxjs/Subscription'; import { Subscription } from "rxjs/Subscription";
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 { ConfirmationTargets, ConfirmationState, ConfirmationButtons } from '../../shared/shared.const'; import { ConfirmationTargets, ConfirmationState, ConfirmationButtons } from "../../shared/shared.const";
import {TranslateService} from "@ngx-translate/core"; import {TranslateService} from "@ngx-translate/core";
import {BatchInfo, BathInfoChanges} from "../../shared/confirmation-dialog/confirmation-batch-message"; import {BatchInfo, BathInfoChanges} from "../../shared/confirmation-dialog/confirmation-batch-message";
import {Observable} from "rxjs/Observable"; import {Observable} from "rxjs/Observable";
import {AppConfigService} from "../../app-config.service"; import {AppConfigService} from "../../app-config.service";
@Component({ @Component({
selector: 'list-project', selector: "list-project",
templateUrl: 'list-project.component.html', templateUrl: "list-project.component.html",
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class ListProjectComponent implements OnDestroy { export class ListProjectComponent implements OnDestroy {
loading: boolean = true; loading = true;
projects: Project[] = []; projects: Project[] = [];
filteredType: number = 0;//All projects filteredType = 0; // All projects
searchKeyword: string = ""; searchKeyword = "";
selectedRow: Project[] = []; selectedRow: Project[] = [];
batchDelectionInfos: BatchInfo[] = []; batchDelectionInfos: BatchInfo[] = [];
@ -60,9 +59,9 @@ export class ListProjectComponent implements OnDestroy {
timeComparator: Comparator<Project> = new CustomComparator<Project>("creation_time", "date"); timeComparator: Comparator<Project> = new CustomComparator<Project>("creation_time", "date");
accessLevelComparator: Comparator<Project> = new CustomComparator<Project>("public", "number"); accessLevelComparator: Comparator<Project> = new CustomComparator<Project>("public", "number");
roleComparator: Comparator<Project> = new CustomComparator<Project>("current_user_role_id", "number"); roleComparator: Comparator<Project> = new CustomComparator<Project>("current_user_role_id", "number");
currentPage: number = 1; currentPage = 1;
totalCount: number = 0; totalCount = 0;
pageSize: number = 15; pageSize = 15;
currentState: State; currentState: State;
subscription: Subscription; subscription: Subscription;
@ -97,9 +96,9 @@ export class ListProjectComponent implements OnDestroy {
let account = this.session.getCurrentUser(); let account = this.session.getCurrentUser();
if (account) { if (account) {
switch (this.appConfigService.getConfig().project_creation_restriction) { switch (this.appConfigService.getConfig().project_creation_restriction) {
case 'adminonly': case "adminonly":
return (account.has_admin_role === 1); return (account.has_admin_role === 1);
case 'everyone': case "everyone":
return true; return true;
} }
} }
@ -131,7 +130,7 @@ export class ListProjectComponent implements OnDestroy {
goToLink(proId: number): void { goToLink(proId: number): void {
this.searchTrigger.closeSearch(true); this.searchTrigger.closeSearch(true);
let linkUrl = ['harbor', 'projects', proId, 'repositories']; let linkUrl = ["harbor", "projects", proId, "repositories"];
this.router.navigate(linkUrl); this.router.navigate(linkUrl);
} }
@ -143,7 +142,7 @@ export class ListProjectComponent implements OnDestroy {
clrLoad(state: State) { clrLoad(state: State) {
this.selectedRow = []; this.selectedRow = [];
//Keep state for future filtering and sorting // Keep state for future filtering and sorting
this.currentState = state; this.currentState = state;
let pageNumber: number = calculatePage(state); let pageNumber: number = calculatePage(state);
@ -157,7 +156,7 @@ export class ListProjectComponent implements OnDestroy {
} }
this.proService.listProjects(this.searchKeyword, passInFilteredType, pageNumber, this.pageSize).toPromise() this.proService.listProjects(this.searchKeyword, passInFilteredType, pageNumber, this.pageSize).toPromise()
.then(response => { .then(response => {
//Get total count // Get total count
if (response.headers) { if (response.headers) {
let xHeader: string = response.headers.get("X-Total-Count"); let xHeader: string = response.headers.get("X-Total-Count");
if (xHeader) { if (xHeader) {
@ -166,7 +165,7 @@ export class ListProjectComponent implements OnDestroy {
} }
this.projects = response.json() as Project[]; this.projects = response.json() as Project[];
//Do customising filtering and sorting // Do customising filtering and sorting
this.projects = doFiltering<Project>(this.projects, state); this.projects = doFiltering<Project>(this.projects, state);
this.projects = doSorting<Project>(this.projects, state); this.projects = doSorting<Project>(this.projects, state);
@ -177,7 +176,7 @@ export class ListProjectComponent implements OnDestroy {
this.msgHandler.handleError(error); this.msgHandler.handleError(error);
}); });
//Force refresh view // Force refresh view
let hnd = setInterval(() => this.ref.markForCheck(), 100); let hnd = setInterval(() => this.ref.markForCheck(), 100);
setTimeout(() => clearInterval(hnd), 5000); setTimeout(() => clearInterval(hnd), 5000);
} }
@ -190,12 +189,12 @@ export class ListProjectComponent implements OnDestroy {
toggleProject(p: Project) { toggleProject(p: Project) {
if (p) { if (p) {
p.metadata.public === 'true' ? p.metadata.public = 'false' : p.metadata.public = 'true'; p.metadata.public === "true" ? p.metadata.public = "false" : p.metadata.public = "true";
this.proService this.proService
.toggleProjectPublic(p.project_id, p.metadata.public) .toggleProjectPublic(p.project_id, p.metadata.public)
.subscribe( .subscribe(
response => { response => {
this.msgHandler.showSuccess('PROJECT.TOGGLED_SUCCESS'); this.msgHandler.showSuccess("PROJECT.TOGGLED_SUCCESS");
let pp: Project = this.projects.find((item: Project) => item.project_id === p.project_id); let pp: Project = this.projects.find((item: Project) => item.project_id === p.project_id);
if (pp) { if (pp) {
pp.metadata.public = p.metadata.public; pp.metadata.public = p.metadata.public;
@ -205,7 +204,7 @@ export class ListProjectComponent implements OnDestroy {
error => this.msgHandler.handleError(error) error => this.msgHandler.handleError(error)
); );
//Force refresh view // Force refresh view
let hnd = setInterval(() => this.ref.markForCheck(), 100); let hnd = setInterval(() => this.ref.markForCheck(), 100);
setTimeout(() => clearInterval(hnd), 2000); setTimeout(() => clearInterval(hnd), 2000);
} }
@ -222,21 +221,13 @@ export class ListProjectComponent implements OnDestroy {
this.batchDelectionInfos.push(initBatchMessage); this.batchDelectionInfos.push(initBatchMessage);
}); });
this.deletionDialogService.addBatchInfoList(this.batchDelectionInfos); this.deletionDialogService.addBatchInfoList(this.batchDelectionInfos);
let deletionMessage = new ConfirmationMessage( this.delProjects(p);
'PROJECT.DELETION_TITLE',
'PROJECT.DELETION_SUMMARY',
nameArr.join(','),
p,
ConfirmationTargets.PROJECT,
ConfirmationButtons.DELETE_CANCEL
);
this.deletionDialogService.openComfirmDialog(deletionMessage);
} }
} }
delProjects(datas: Project[]) { delProjects(projects: Project[]) {
let observableLists: any[] = []; let observableLists: any[] = [];
if (datas && datas.length) { if (projects && projects.length) {
datas.forEach(data => { projects.forEach(data => {
observableLists.push(this.delOperate(data.project_id, data.name)); observableLists.push(this.delOperate(data.project_id, data.name));
}); });
Promise.all(observableLists).then(item => { Promise.all(observableLists).then(item => {
@ -252,23 +243,23 @@ export class ListProjectComponent implements OnDestroy {
} }
} }
delOperate(id: number, name: string) { delOperate(id: number, name: string) {
let findedList = this.batchDelectionInfos.find(list => list.name === name); let findedList = this.batchDelectionInfos.find(list => list.name === name);
return this.proService.deleteProject(id) return this.proService.deleteProject(id)
.then( .then(
() => { () => {
this.translate.get('BATCH.DELETED_SUCCESS').subscribe(res => { this.translate.get("BATCH.DELETED_SUCCESS").subscribe(res => {
findedList = BathInfoChanges(findedList, res); findedList = BathInfoChanges(findedList, res);
}); });
}, },
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]); findedList = BathInfoChanges(findedList, res[0], false, true, 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); findedList = BathInfoChanges(findedList, res, false, true);
}); });
} }
@ -318,7 +309,7 @@ export class ListProjectComponent implements OnDestroy {
let targetPageNumber: number = this.currentPage; let targetPageNumber: number = this.currentPage;
if (this.currentPage > totalPages) { if (this.currentPage > totalPages) {
targetPageNumber = totalPages;//Should == currentPage -1 targetPageNumber = totalPages; // Should == currentPage -1
} }
let st: State = this.currentState; let st: State = this.currentState;

View File

@ -12,23 +12,31 @@
</div> </div>
</div> </div>
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12"> <div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<clr-dg-action-bar>
<button class="btn btn-sm btn-secondary" (click)="openAddMemberModal()" [disabled]="!hasProjectAdminRole">
<span><clr-icon shape="plus"></clr-icon>{{'MEMBER.NEW_MEMBER' | translate }}</span>
</button>
<clr-dropdown [clrCloseMenuOnItemClick]="false" class="btn btn-sm btn-secondary" clrDropdownTrigger>
<span>{{'MEMBER.REMOVE' | translate}}<clr-icon shape="caret down"></clr-icon></span>
<clr-dropdown-menu *clrIfOpen>
<button class="btn btn-sm btn-secondary" (click)="changeRole(selectedRow, 1)" [disabled]="!(selectedRow.length && hasProjectAdminRole)">{{'MEMBER.PROJECT_ADMIN' | translate}}</button>
<button class="btn btn-sm btn-secondary" (click)="changeRole(selectedRow, 2)" [disabled]="!(selectedRow.length && hasProjectAdminRole)">{{'MEMBER.DEVELOPER' | translate}}</button>
<button class="btn btn-sm btn-secondary" (click)="changeRole(selectedRow, 3)" [disabled]="!(selectedRow.length && hasProjectAdminRole)">{{'MEMBER.GUEST' | translate}}</button>
</clr-dropdown-menu>
</clr-dropdown>
<button class="btn btn-sm btn-secondary" (click)="deleteMembers(selectedRow)" [disabled]="!(selectedRow.length && hasProjectAdminRole)">
<span>{{'MEMBER.REMOVE' | translate}}</span>
</button>
</clr-dg-action-bar>
<clr-datagrid [(clrDgSelected)]="selectedRow" (clrDgSelectedChange)="SelectedChange()"> <clr-datagrid [(clrDgSelected)]="selectedRow" (clrDgSelectedChange)="SelectedChange()">
<clr-dg-action-bar>
<div class="btn-group">
<clr-button-group [clrMenuPosition]="'bottom-right'" >
<clr-button class="btn btn-sm btn-secondary" (click)="openAddMemberModal()" [disabled]="!hasProjectAdminRole">{{'MEMBER.NEW_MEMBER' | translate }}</clr-button>
<clr-button class="btn btn-sm btn-secondary" (click)="deleteMembers(selectedRow)" [disabled]="!(selectedRow.length && hasProjectAdminRole)">{{'MEMBER.DELETE' | translate}}</clr-button>
<clr-button class="btn btn-sm btn-secondary" [clrInMenu]="true" (click)="changeRole(selectedRow, 1)" [disabled]="!(selectedRow.length && hasProjectAdminRole)">{{'MEMBER.PROJECT_ADMIN' | translate}}</clr-button>
<clr-button class="btn btn-sm btn-secondary" [clrInMenu]="true" (click)="changeRole(selectedRow, 2)" [disabled]="!(selectedRow.length && hasProjectAdminRole)">{{'MEMBER.DEVELOPER' | translate}}</clr-button>
<clr-button class="btn btn-sm btn-secondary" [clrInMenu]="true" (click)="changeRole(selectedRow, 3)" [disabled]="!(selectedRow.length && hasProjectAdminRole)">{{'MEMBER.GUEST' | translate}}</clr-button>
</clr-button-group>
</div>
</clr-dg-action-bar>
<clr-dg-column>{{'MEMBER.NAME' | translate}}</clr-dg-column> <clr-dg-column>{{'MEMBER.NAME' | translate}}</clr-dg-column>
<clr-dg-column>{{'MEMBER.ROLE' | translate}}</clr-dg-column> <clr-dg-column>{{'MEMBER.ROLE' | translate}}</clr-dg-column>
<clr-dg-row *ngFor="let m of members" [clrDgItem]="m"> <clr-dg-row *ngFor="let m of members" [clrDgItem]="m">
<clr-dg-cell>{{m.username}}</clr-dg-cell> <clr-dg-cell>{{m.username}}</clr-dg-cell>
<clr-dg-cell>{{roleInfo[m.role_id] | translate}}</clr-dg-cell> <clr-dg-cell>
<span class="spinner spinner-inline"> Loading... </span>
<span *ngIf="!ChangeRoleOngoing(m.username)">{{roleInfo[m.role_id] | translate}}</span>
</clr-dg-cell>
</clr-dg-row> </clr-dg-row>
<clr-dg-footer> <clr-dg-footer>
<span *ngIf="pagination.totalItems">{{pagination.firstItem + 1}} - {{pagination.lastItem +1 }} {{'MEMBER.OF' | translate}} </span> <span *ngIf="pagination.totalItems">{{pagination.firstItem + 1}} - {{pagination.lastItem +1 }} {{'MEMBER.OF' | translate}} </span>

View File

@ -11,39 +11,37 @@
// 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, OnInit, ViewChild, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; import { Component, OnInit, ViewChild, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef } from "@angular/core";
import { ActivatedRoute, Params, Router } from '@angular/router'; import { ActivatedRoute, Router } from "@angular/router";
import { Response } from '@angular/http';
import { SessionUser } from '../../shared/session-user'; import { SessionUser } from "../../shared/session-user";
import { Member } from './member'; import { Member } from "./member";
import { MemberService } from './member.service'; import { MemberService } from "./member.service";
import { AddMemberComponent } from './add-member/add-member.component'; import { AddMemberComponent } from "./add-member/add-member.component";
import { MessageHandlerService } from '../../shared/message-handler/message-handler.service'; import { MessageHandlerService } from "../../shared/message-handler/message-handler.service";
import { ConfirmationTargets, ConfirmationState, ConfirmationButtons } from '../../shared/shared.const'; import { ConfirmationTargets, ConfirmationState, 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 { SessionService } from '../../shared/session.service'; import { SessionService } from "../../shared/session.service";
import { RoleInfo } from '../../shared/shared.const'; import { RoleInfo } from "../../shared/shared.const";
import { Observable } from 'rxjs/Observable'; import "rxjs/add/operator/switchMap";
import 'rxjs/add/operator/switchMap'; import "rxjs/add/operator/catch";
import 'rxjs/add/operator/catch'; import "rxjs/add/operator/map";
import 'rxjs/add/operator/map'; import "rxjs/add/observable/throw";
import 'rxjs/add/observable/throw'; import { Subscription } from "rxjs/Subscription";
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 {BatchInfo, BathInfoChanges} from "../../shared/confirmation-dialog/confirmation-batch-message";
@Component({ @Component({
templateUrl: 'member.component.html', templateUrl: "member.component.html",
styleUrls: ['./member.component.css'], styleUrls: ["./member.component.css"],
changeDetection: ChangeDetectionStrategy.OnPush changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class MemberComponent implements OnInit, OnDestroy { export class MemberComponent implements OnInit, OnDestroy {
@ -60,22 +58,22 @@ export class MemberComponent implements OnInit, OnDestroy {
hasProjectAdminRole: boolean; hasProjectAdminRole: boolean;
searchMember: string; searchMember: string;
selectedRow: Member[] = [] selectedRow: Member[] = [];
roleNum: number; roleNum: number;
isDelete: boolean =false; isDelete = false;
isChangeRole: boolean =false; isChangeRole = false;
batchDelectionInfos: BatchInfo[] = []; batchActionInfos: BatchInfo[] = [];
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router, private router: Router,
private memberService: MemberService, private memberService: MemberService,
private translate: TranslateService, private translate: TranslateService,
private messageHandlerService: MessageHandlerService, private messageHandlerService: MessageHandlerService,
private OperateDialogService: ConfirmationDialogService, private OperateDialogService: ConfirmationDialogService,
private session: SessionService, private session: SessionService,
private ref: ChangeDetectorRef) { private ref: ChangeDetectorRef) {
this.delSub = OperateDialogService.confirmationConfirm$.subscribe(message => { this.delSub = OperateDialogService.confirmationConfirm$.subscribe(message => {
if (message && if (message &&
message.state === ConfirmationState.CONFIRMED && message.state === ConfirmationState.CONFIRMED &&
@ -88,8 +86,8 @@ export class MemberComponent implements OnInit, OnDestroy {
} }
} }
}); });
let hnd = setInterval(()=>ref.markForCheck(), 100); let hnd = setInterval(() => ref.markForCheck(), 100);
setTimeout(()=>clearInterval(hnd), 1000); setTimeout(() => clearInterval(hnd), 1000);
} }
retrieve(projectId: number, username: string) { retrieve(projectId: number, username: string) {
@ -99,11 +97,11 @@ export class MemberComponent implements OnInit, OnDestroy {
.subscribe( .subscribe(
response => { response => {
this.members = response; this.members = response;
let hnd = setInterval(()=>this.ref.markForCheck(), 100); let hnd = setInterval(() => this.ref.markForCheck(), 100);
setTimeout(()=>clearInterval(hnd), 1000); setTimeout(() => clearInterval(hnd), 1000);
}, },
error => { error => {
this.router.navigate(['/harbor', 'projects']); this.router.navigate(["/harbor", "projects"]);
this.messageHandlerService.handleError(error); this.messageHandlerService.handleError(error);
}); });
} }
@ -115,15 +113,15 @@ export class MemberComponent implements OnInit, OnDestroy {
} }
ngOnInit() { ngOnInit() {
//Get projectId from route params snapshot. // Get projectId from route params snapshot.
this.projectId = +this.route.snapshot.parent.params['id']; this.projectId = +this.route.snapshot.parent.params["id"];
//Get current user from registered resolver. // Get current user from registered resolver.
this.currentUser = this.session.getCurrentUser(); this.currentUser = this.session.getCurrentUser();
let resolverData = this.route.snapshot.parent.data; let resolverData = this.route.snapshot.parent.data;
if(resolverData) { if (resolverData) {
this.hasProjectAdminRole = (<Project>resolverData['projectResolver']).has_project_admin_role; this.hasProjectAdminRole = (<Project>resolverData["projectResolver"]).has_project_admin_role;
} }
this.retrieve(this.projectId, ''); this.retrieve(this.projectId, "");
} }
openAddMemberModal() { openAddMemberModal() {
@ -131,8 +129,8 @@ export class MemberComponent implements OnInit, OnDestroy {
} }
addedMember($event: any) { addedMember($event: any) {
this.searchMember = ''; this.searchMember = "";
this.retrieve(this.projectId, ''); this.retrieve(this.projectId, "");
} }
changeRole(m: Member[], roleId: number) { changeRole(m: Member[], roleId: number) {
@ -141,24 +139,16 @@ export class MemberComponent implements OnInit, OnDestroy {
this.isChangeRole = true; this.isChangeRole = true;
this.roleNum = roleId; this.roleNum = roleId;
let nameArr: string[] = []; let nameArr: string[] = [];
this.batchDelectionInfos = []; this.batchActionInfos = [];
m.forEach(data => { m.forEach(data => {
nameArr.push(data.username); nameArr.push(data.username);
let initBatchMessage = new BatchInfo(); let initBatchMessage = new BatchInfo();
initBatchMessage.name = data.username; initBatchMessage.name = data.username;
this.batchDelectionInfos.push(initBatchMessage); this.batchActionInfos.push(initBatchMessage);
}); });
this.OperateDialogService.addBatchInfoList(this.batchDelectionInfos); this.OperateDialogService.addBatchInfoList(this.batchActionInfos);
let switchMessage = new ConfirmationMessage( this.changeOpe(m);
'MEMBER.SWITCH_TITLE',
'MEMBER.SWITCH_SUMMARY',
nameArr.join(','),
m,
ConfirmationTargets.PROJECT_MEMBER,
ConfirmationButtons.SWITCH_CANCEL
);
this.OperateDialogService.openComfirmDialog(switchMessage);
} }
} }
@ -167,64 +157,64 @@ export class MemberComponent implements OnInit, OnDestroy {
let promiseList: any[] = []; let promiseList: any[] = [];
members.forEach(member => { members.forEach(member => {
if (member.user_id === this.currentUser.user_id) { if (member.user_id === this.currentUser.user_id) {
let findedList = this.batchDelectionInfos.find(data => data.name === member.username); let foundMember = this.batchActionInfos.find(batchInfo => batchInfo.name === member.username);
this.translate.get('BATCH.SWITCH_FAILURE').subscribe(res => { this.translate.get("BATCH.SWITCH_FAILURE").subscribe(res => {
findedList = BathInfoChanges(findedList, res, false, true); foundMember = BathInfoChanges(foundMember, res, false, true);
}); });
}else { } else {
promiseList.push(this.changeOperate(this.projectId, member.user_id, this.roleNum, member.username)); promiseList.push(this.changeOperate(this.projectId, member.user_id, this.roleNum, member.username));
} }
}); });
Promise.all(promiseList).then(num => { Promise.all(promiseList).then(num => {
this.retrieve(this.projectId, ''); this.retrieve(this.projectId, "");
}, },
); );
} }
} }
changeOperate(projectId: number, memberId: number, roleId: number, username: string) { changeOperate(projectId: number, memberId: number, roleId: number, username: string) {
let findedList = this.batchDelectionInfos.find(data => data.name === username); let foundMember = this.batchActionInfos.find(batchInfo => batchInfo.name === username);
return this.memberService return this.memberService
.changeMemberRole(projectId, memberId, roleId) .changeMemberRole(projectId, memberId, roleId)
.then( .then(
response => { response => {
this.translate.get('BATCH.SWITCH_SUCCESS').subscribe(res => { this.translate.get("BATCH.SWITCH_SUCCESS").subscribe(res => {
findedList = BathInfoChanges(findedList, res); foundMember = BathInfoChanges(foundMember, res);
}); });
}, },
error => { error => {
this.translate.get('BATCH.SWITCH_FAILURE').subscribe(res => { this.translate.get("BATCH.SWITCH_FAILURE").subscribe(res => {
findedList = BathInfoChanges(findedList, res, false, true); 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.batchDelectionInfos = []; this.batchActionInfos = [];
if (m && m.length) { if (m && m.length) {
m.forEach(data => { m.forEach(data => {
nameArr.push(data.username); nameArr.push(data.username);
let initBatchMessage = new BatchInfo (); let initBatchMessage = new BatchInfo ();
initBatchMessage.name = data.username; initBatchMessage.name = data.username;
this.batchDelectionInfos.push(initBatchMessage); this.batchActionInfos.push(initBatchMessage);
}); });
this.OperateDialogService.addBatchInfoList(this.batchDelectionInfos); this.OperateDialogService.addBatchInfoList(this.batchActionInfos);
let deletionMessage = new ConfirmationMessage( this.deleteMem(m);
'MEMBER.DELETION_TITLE',
'MEMBER.DELETION_SUMMARY',
nameArr.join(','),
m,
ConfirmationTargets.PROJECT_MEMBER,
ConfirmationButtons.DELETE_CANCEL
);
this.OperateDialogService.openComfirmDialog(deletionMessage);
} }
} }
@ -233,8 +223,8 @@ export class MemberComponent implements OnInit, OnDestroy {
let promiseLists: any[] = []; let promiseLists: any[] = [];
members.forEach(member => { members.forEach(member => {
if (member.user_id === this.currentUser.user_id) { if (member.user_id === this.currentUser.user_id) {
let findedList = this.batchDelectionInfos.find(data => data.name === member.username); let findedList = this.batchActionInfos.find(data => data.name === member.username);
this.translate.get('BATCH.DELETED_FAILURE').subscribe(res => { this.translate.get("BATCH.DELETED_FAILURE").subscribe(res => {
findedList = BathInfoChanges(findedList, res, false, true); findedList = BathInfoChanges(findedList, res, false, true);
}); });
}else { }else {
@ -245,23 +235,23 @@ export class MemberComponent implements OnInit, OnDestroy {
Promise.all(promiseLists).then(item => { Promise.all(promiseLists).then(item => {
this.selectedRow = []; this.selectedRow = [];
this.retrieve(this.projectId, ''); this.retrieve(this.projectId, "");
}); });
} }
} }
delOperate(projectId: number, memberId: number, username: string) { delOperate(projectId: number, memberId: number, username: string) {
let findedList = this.batchDelectionInfos.find(data => data.name === username); let findedList = this.batchActionInfos.find(data => data.name === username);
return this.memberService return this.memberService
.deleteMember(projectId, memberId) .deleteMember(projectId, memberId)
.then( .then(
response => { response => {
this.translate.get('BATCH.DELETED_SUCCESS').subscribe(res => { this.translate.get("BATCH.DELETED_SUCCESS").subscribe(res => {
findedList = BathInfoChanges(findedList, res); findedList = BathInfoChanges(findedList, res);
}); });
}, },
error => { error => {
this.translate.get('BATCH.DELETED_FAILURE').subscribe(res => { this.translate.get("BATCH.DELETED_FAILURE").subscribe(res => {
findedList = BathInfoChanges(findedList, res, false, true); findedList = BathInfoChanges(findedList, res, false, true);
}); });
} }
@ -269,7 +259,7 @@ export class MemberComponent implements OnInit, OnDestroy {
} }
SelectedChange(): void { SelectedChange(): void {
//this.forceRefreshView(5000); // this.forceRefreshView(5000);
} }
doSearch(searchMember: string) { doSearch(searchMember: string) {
@ -278,6 +268,6 @@ export class MemberComponent implements OnInit, OnDestroy {
} }
refresh() { refresh() {
this.retrieve(this.projectId, ''); this.retrieve(this.projectId, "");
} }
} }

View File

@ -10,10 +10,10 @@ export class BatchInfo {
errorState: boolean; errorState: boolean;
errorInfo: string; errorInfo: string;
constructor() { constructor() {
this.status = 'pending'; this.status = "pending";
this.loading = false; this.loading = false;
this.errorState = false; this.errorState = false;
this.errorInfo = ''; this.errorInfo = "";
} }
} }

View File

@ -113,7 +113,7 @@ export class ConfirmationDialogComponent implements OnDestroy {
} }
operate(): void { operate(): void {
if(!this.message){//Inproper condition if (!this.message) {// Improper condition
this.close(); this.close();
return; return;
} }