TSK-537 Filter Component for Tasks
TSK-537: Filter Component for Workplace
This commit is contained in:
parent
0c5d540c56
commit
3968bd4f54
|
@ -219,9 +219,9 @@ public class TaskController extends AbstractPagingController {
|
|||
params.remove(NAME);
|
||||
}
|
||||
if (params.containsKey(PRIORITY)) {
|
||||
String[] prioritesInString = extractCommaSeparatedFields(params.get(PRIORITY));
|
||||
int[] priorites = extractPriorities(prioritesInString);
|
||||
taskQuery.priorityIn(priorites);
|
||||
String[] prioritiesInString = extractCommaSeparatedFields(params.get(PRIORITY));
|
||||
int[] priorities = extractPriorities(prioritiesInString);
|
||||
taskQuery.priorityIn(priorities);
|
||||
params.remove(PRIORITY);
|
||||
}
|
||||
if (params.containsKey(STATE)) {
|
||||
|
@ -335,12 +335,12 @@ public class TaskController extends AbstractPagingController {
|
|||
return taskQuery;
|
||||
}
|
||||
|
||||
private int[] extractPriorities(String[] prioritesInString) {
|
||||
int[] priorites = new int[prioritesInString.length];
|
||||
for (int i = 0; i < prioritesInString.length; i++) {
|
||||
priorites[i] = Integer.getInteger(prioritesInString[i]);
|
||||
private int[] extractPriorities(String[] prioritiesInString) {
|
||||
int[] priorities = new int[prioritiesInString.length];
|
||||
for (int i = 0; i < prioritiesInString.length; i++) {
|
||||
priorities[i] = Integer.valueOf(prioritiesInString[i]);
|
||||
}
|
||||
return priorites;
|
||||
return priorities;
|
||||
}
|
||||
|
||||
private TaskState[] extractStates(MultiValueMap<String, String> params) throws InvalidArgumentException {
|
||||
|
|
|
@ -1,42 +1,38 @@
|
|||
// tslint:enable:max-line-length
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { Ng2AutoCompleteModule } from 'ng2-auto-complete';
|
||||
import { AngularSvgIconModule } from 'angular-svg-icon';
|
||||
import { AlertModule } from 'ngx-bootstrap';
|
||||
import { SharedModule } from 'app/shared/shared.module';
|
||||
import { AdministrationRoutingModule } from './administration-routing.module';
|
||||
import { TypeaheadModule } from 'ngx-bootstrap';
|
||||
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {NgModule} from '@angular/core';
|
||||
import {FormsModule, ReactiveFormsModule} from '@angular/forms';
|
||||
import {Ng2AutoCompleteModule} from 'ng2-auto-complete';
|
||||
import {AngularSvgIconModule} from 'angular-svg-icon';
|
||||
import {AlertModule, TypeaheadModule} from 'ngx-bootstrap';
|
||||
import {SharedModule} from 'app/shared/shared.module';
|
||||
import {AdministrationRoutingModule} from './administration-routing.module';
|
||||
/**
|
||||
* Components
|
||||
*/
|
||||
import { WorkbasketListComponent } from './workbasket/master/list/workbasket-list.component';
|
||||
import { WorkbasketListToolbarComponent } from './workbasket/master/list/workbasket-list-toolbar/workbasket-list-toolbar.component'
|
||||
import { WorkbasketDetailsComponent } from './workbasket/details/workbasket-details.component';
|
||||
import { WorkbasketInformationComponent } from './workbasket/details/information/workbasket-information.component';
|
||||
import { DistributionTargetsComponent } from './workbasket/details/distribution-targets/distribution-targets.component';
|
||||
import { DualListComponent } from './workbasket/details/distribution-targets/dual-list/dual-list.component';
|
||||
import { AccessItemsComponent } from './workbasket/details/access-items/access-items.component';
|
||||
import { FilterComponent } from './components/filter/filter.component';
|
||||
import { IconTypeComponent } from './components/type-icon/icon-type.component';
|
||||
import { PaginationComponent } from './workbasket/master/list/pagination/pagination.component';
|
||||
import { ClassificationListComponent } from './classification/master/list/classification-list.component';
|
||||
import { ClassificationDetailsComponent } from './classification/details/classification-details.component';
|
||||
import { ImportExportComponent } from './components/import-export/import-export.component';
|
||||
import { ClassificationTypesSelectorComponent } from 'app/shared/classification-types-selector/classification-types-selector.component';
|
||||
|
||||
import {WorkbasketListComponent} from './workbasket/master/list/workbasket-list.component';
|
||||
import {WorkbasketListToolbarComponent} from './workbasket/master/list/workbasket-list-toolbar/workbasket-list-toolbar.component'
|
||||
import {WorkbasketDetailsComponent} from './workbasket/details/workbasket-details.component';
|
||||
import {WorkbasketInformationComponent} from './workbasket/details/information/workbasket-information.component';
|
||||
import {DistributionTargetsComponent} from './workbasket/details/distribution-targets/distribution-targets.component';
|
||||
import {DualListComponent} from './workbasket/details/distribution-targets/dual-list/dual-list.component';
|
||||
import {AccessItemsComponent} from './workbasket/details/access-items/access-items.component';
|
||||
import {IconTypeComponent} from './components/type-icon/icon-type.component';
|
||||
import {PaginationComponent} from './workbasket/master/list/pagination/pagination.component';
|
||||
import {ClassificationListComponent} from './classification/master/list/classification-list.component';
|
||||
import {ClassificationDetailsComponent} from './classification/details/classification-details.component';
|
||||
import {ImportExportComponent} from './components/import-export/import-export.component';
|
||||
import {ClassificationTypesSelectorComponent} from 'app/shared/classification-types-selector/classification-types-selector.component';
|
||||
/**
|
||||
* Services
|
||||
*/
|
||||
import { WorkbasketService } from 'app/services/workbasket/workbasket.service';
|
||||
import { SavingWorkbasketService } from './services/saving-workbaskets/saving-workbaskets.service';
|
||||
import { ClassificationDefinitionService } from './services/classification-definition/classification-definition.service';
|
||||
import { WorkbasketDefinitionService } from './services/workbasket-definition/workbasket-definition.service';
|
||||
import { ClassificationsService } from './services/classifications/classifications.service';
|
||||
import { ClassificationTypesService } from './services/classification-types/classification-types.service';
|
||||
import { ClassificationCategoriesService } from './services/classification-categories-service/classification-categories.service';
|
||||
import {WorkbasketService} from 'app/services/workbasket/workbasket.service';
|
||||
import {SavingWorkbasketService} from './services/saving-workbaskets/saving-workbaskets.service';
|
||||
import {ClassificationDefinitionService} from './services/classification-definition/classification-definition.service';
|
||||
import {WorkbasketDefinitionService} from './services/workbasket-definition/workbasket-definition.service';
|
||||
import {ClassificationsService} from './services/classifications/classifications.service';
|
||||
import {ClassificationTypesService} from './services/classification-types/classification-types.service';
|
||||
import {ClassificationCategoriesService} from './services/classification-categories-service/classification-categories.service';
|
||||
|
||||
const MODULES = [
|
||||
CommonModule,
|
||||
|
@ -56,8 +52,6 @@ const DECLARATIONS = [
|
|||
AccessItemsComponent,
|
||||
WorkbasketDetailsComponent,
|
||||
WorkbasketInformationComponent,
|
||||
FilterComponent,
|
||||
IconTypeComponent,
|
||||
DistributionTargetsComponent,
|
||||
DualListComponent,
|
||||
PaginationComponent,
|
||||
|
@ -82,4 +76,5 @@ const DECLARATIONS = [
|
|||
})
|
||||
export class AdministrationModule {
|
||||
}
|
||||
|
||||
// tslint:enable:max-line-length
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Component, OnInit, OnDestroy } from '@angular/core';
|
|||
import { Subscription } from 'rxjs/Subscription';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
|
||||
import { ImportType } from 'app/models/import-type';
|
||||
import { TaskanaType } from 'app/models/taskana-type';
|
||||
import { Classification } from 'app/models/classification';
|
||||
import { TreeNodeModel } from 'app/models/tree-node';
|
||||
|
||||
|
@ -24,7 +24,7 @@ export class ClassificationListComponent implements OnInit, OnDestroy {
|
|||
|
||||
selectedCategory = '';
|
||||
selectedId: string;
|
||||
selectionToImport = ImportType.CLASSIFICATIONS;
|
||||
selectionToImport = TaskanaType.CLASSIFICATIONS;
|
||||
requestInProgress = false;
|
||||
initialized = false;
|
||||
inputValue: string;
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
<div id="{{target}}" class="list-group-search">
|
||||
<div class="row">
|
||||
<div class="dropdown col-xs-2">
|
||||
<button class="btn btn-default" data-toggle="dropdown" type="button" id="dropdownMenufilter" data-toggle="dropdown" aria-haspopup="true"
|
||||
aria-expanded="true">
|
||||
<taskana-icon-type [type]="filter.type" class="vertical-align"></taskana-icon-type>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-users" role="menu">
|
||||
<li>
|
||||
<a *ngFor="let type of allTypes | mapValues" type="button" (click)="selectType(type.key); search()" data-toggle="tooltip"
|
||||
[title]="type.value">
|
||||
<taskana-icon-type class="vertical-align" [type]='type.key' [text]="type.value"></taskana-icon-type>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<input type="text" [(ngModel)]="filter.name" (keyup.enter)="search()" class="form-control" id="wb-display-name-filter" placeholder="Filter name">
|
||||
</div>
|
||||
<div class="col-xs-4">
|
||||
<input type="text" [(ngModel)]="filter.key" (keyup.enter)="search()" class="form-control" id="wb-display-key-filter" placeholder="Filter key">
|
||||
</div>
|
||||
<button (click)="clear(); search()" type="button" class="btn btn-default glyphicon glyphicon-ban-circle blue pull-right margin-right"
|
||||
data-toggle="tooltip" title="Clear">
|
||||
</button>
|
||||
</div>
|
||||
<div class="row padding">
|
||||
<div class="col-xs-2">
|
||||
</div>
|
||||
<div class="col-xs-8">
|
||||
<input type="text" [(ngModel)]="filter.description" (keyup.enter)="search()" class="form-control" id="wb-display-description-filter"
|
||||
placeholder="Filter by description">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-2">
|
||||
</div>
|
||||
<div class="col-xs-8">
|
||||
<input type="text" [(ngModel)]="filter.owner" (keyup.enter)="search()" class="form-control" id="wb-display-task-owner-filter"
|
||||
placeholder="Filter by Task owner">
|
||||
</div>
|
||||
<button (click)="search()" type="button" class="btn btn-default glyphicon glyphicon-search blue pull-right margin-right"
|
||||
data-toggle="tooltip" title="Search">
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
|
@ -1,81 +0,0 @@
|
|||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { AngularSvgIconModule } from 'angular-svg-icon';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { HttpModule } from '@angular/http';
|
||||
|
||||
import { FilterModel } from 'app/models/filter';
|
||||
import { IconTypeComponent } from '../type-icon/icon-type.component';
|
||||
import { FilterComponent } from './filter.component';
|
||||
import { MapValuesPipe } from 'app/shared/pipes/mapValues/map-values.pipe';
|
||||
import { configureTests } from 'app/app.test.configuration';
|
||||
|
||||
describe('FilterComponent', () => {
|
||||
let component: FilterComponent,
|
||||
fixture: ComponentFixture<FilterComponent>,
|
||||
debugElement: any;
|
||||
|
||||
|
||||
beforeEach(done => {
|
||||
const configure = (testBed: TestBed) => {
|
||||
testBed.configureTestingModule({
|
||||
declarations: [FilterComponent, IconTypeComponent, MapValuesPipe],
|
||||
imports: [AngularSvgIconModule, FormsModule, HttpClientModule, HttpModule]
|
||||
})
|
||||
};
|
||||
configureTests(configure).then(testBed => {
|
||||
fixture = TestBed.createComponent(FilterComponent);
|
||||
component = fixture.componentInstance;
|
||||
debugElement = fixture.debugElement.nativeElement;
|
||||
fixture.detectChanges();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
document.body.removeChild(debugElement);
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should create a component with id target', () => {
|
||||
expect(debugElement.querySelector('#some-id')).toBeNull();
|
||||
component.target = 'some-id'
|
||||
fixture.detectChanges();
|
||||
expect(debugElement.querySelector('#some-id')).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have filter by: name, description, key, owner and type defined', () => {
|
||||
expect(debugElement.querySelector('#wb-display-name-filter')).toBeDefined();
|
||||
expect(debugElement.querySelector('#wb-display-description-filter')).toBeDefined();
|
||||
expect(debugElement.querySelector('#wb-display-key-filter')).toBeDefined();
|
||||
expect(debugElement.querySelector('#wb-display-owner-filter')).toBeDefined();
|
||||
expect(debugElement.querySelector('#wb-display-type-filter')).toBeDefined();
|
||||
});
|
||||
|
||||
it('should be able to clear all fields after pressing clear button', () => {
|
||||
component.filter = new FilterModel('a', 'a', 'a', 'a', 'a');
|
||||
debugElement.querySelector('[title="Clear"]').click();
|
||||
expect(component.filter.name).toBe('');
|
||||
expect(component.filter.description).toBe('');
|
||||
expect(component.filter.owner).toBe('');
|
||||
expect(component.filter.type).toBe('');
|
||||
expect(component.filter.key).toBe('');
|
||||
});
|
||||
|
||||
it('should be able to select a type and return it based on a number', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should be able to emit a filter after clicking on search button', (done) => {
|
||||
component.filter = new FilterModel('a', 'name1', 'a', 'a');
|
||||
component.performFilter.subscribe(filter => {
|
||||
expect(filter.name).toBe('name1');
|
||||
done();
|
||||
})
|
||||
debugElement.querySelector('[title="Search"]').click();
|
||||
});
|
||||
|
||||
});
|
|
@ -1,41 +0,0 @@
|
|||
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { ICONTYPES } from 'app/models/type';
|
||||
import { FilterModel } from 'app/models/filter';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-filter',
|
||||
templateUrl: './filter.component.html',
|
||||
styleUrls: ['./filter.component.scss']
|
||||
})
|
||||
export class FilterComponent {
|
||||
|
||||
|
||||
allTypes: Map<string, string>;
|
||||
filter: FilterModel = new FilterModel();
|
||||
|
||||
@Input()
|
||||
target: string;
|
||||
|
||||
@Output()
|
||||
performFilter = new EventEmitter<FilterModel>();
|
||||
|
||||
toggleDropDown = false;
|
||||
|
||||
constructor() {
|
||||
this.allTypes = new Map([['', 'All'], ['PERSONAL', 'Personal'], ['GROUP', 'Group'],
|
||||
['CLEARANCE', 'Clearance'], ['TOPIC', 'Topic']]);
|
||||
}
|
||||
|
||||
selectType(type: ICONTYPES) {
|
||||
this.filter.type = type;
|
||||
}
|
||||
|
||||
clear() {
|
||||
this.filter = new FilterModel();
|
||||
}
|
||||
|
||||
search() {
|
||||
this.performFilter.emit(this.filter);
|
||||
}
|
||||
|
||||
}
|
|
@ -2,7 +2,7 @@ import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core';
|
|||
import { ClassificationDefinitionService } from 'app/administration/services/classification-definition/classification-definition.service';
|
||||
import { WorkbasketDefinitionService } from 'app/administration/services/workbasket-definition/workbasket-definition.service';
|
||||
import { DomainService } from 'app/services/domain/domain.service';
|
||||
import { ImportType } from 'app/models/import-type';
|
||||
import { TaskanaType } from 'app/models/taskana-type';
|
||||
import { ErrorModel } from 'app/models/modal-error';
|
||||
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
||||
|
||||
|
@ -13,7 +13,7 @@ import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
|||
})
|
||||
export class ImportExportComponent implements OnInit {
|
||||
|
||||
@Input() currentSelection: ImportType;
|
||||
@Input() currentSelection: TaskanaType;
|
||||
|
||||
@Output() importSucessful = new EventEmitter();
|
||||
|
||||
|
@ -47,7 +47,7 @@ export class ImportExportComponent implements OnInit {
|
|||
}
|
||||
|
||||
const reader = new FileReader();
|
||||
if (this.currentSelection === ImportType.WORKBASKETS) {
|
||||
if (this.currentSelection === TaskanaType.WORKBASKETS) {
|
||||
reader.onload = <Event>(e) => this.workbasketDefinitionService.importWorkbasketDefinitions(e.target.result);
|
||||
this.importSucessful.emit();
|
||||
} else {
|
||||
|
@ -58,7 +58,7 @@ export class ImportExportComponent implements OnInit {
|
|||
}
|
||||
|
||||
export(domain = '') {
|
||||
if (this.currentSelection === ImportType.WORKBASKETS) {
|
||||
if (this.currentSelection === TaskanaType.WORKBASKETS) {
|
||||
this.workbasketDefinitionService.exportWorkbaskets(domain);
|
||||
} else {
|
||||
this.classificationDefinitionService.exportClassifications(domain);
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
<button type="button" (click)="addWorkbasket()" data-toggle="tooltip" title="Add" class="btn btn-default">
|
||||
<span class="glyphicon glyphicon-plus green-blue" aria-hidden="true"></span>
|
||||
</button>
|
||||
<taskana-import-export-component (importSucessful)="importEvent()" [currentSelection]="'selectionToImport'"></taskana-import-export-component>
|
||||
<taskana-import-export-component (importSucessful)="importEvent()"
|
||||
[currentSelection]="selectionToImport"></taskana-import-export-component>
|
||||
</div>
|
||||
<div class="pull-right margin-right">
|
||||
<taskana-sort
|
||||
|
@ -17,7 +18,9 @@
|
|||
</div>
|
||||
|
||||
</div>
|
||||
<div [@toggleDown]="toolbarState" *ngIf="toolbarState" class="row no-overflow">
|
||||
<taskana-filter (performFilter)="filtering($event)"></taskana-filter>
|
||||
<div [@toggle]="toolbarState" *ngIf="toolbarState" class="row no-overflow">
|
||||
<taskana-filter [allTypes]="filteringTypes" [filterParams]="filterParams"
|
||||
[filterType]="filterType"
|
||||
(performFilter)="filtering($event)"></taskana-filter>
|
||||
</div>
|
||||
</li>
|
||||
|
|
|
@ -16,7 +16,7 @@ import { Links } from 'app/models/links';
|
|||
import { FilterModel } from 'app/models/filter';
|
||||
import { SortingModel } from 'app/models/sorting';
|
||||
|
||||
import { FilterComponent } from 'app/administration/components/filter/filter.component';
|
||||
import { FilterComponent } from 'app/shared/filter/filter.component';
|
||||
import { IconTypeComponent } from 'app/administration/components/type-icon/icon-type.component';
|
||||
import { WorkbasketListToolbarComponent } from './workbasket-list-toolbar.component';
|
||||
import { ImportExportComponent } from 'app/administration/components/import-export/import-export.component';
|
||||
|
@ -48,8 +48,7 @@ describe('WorkbasketListToolbarComponent', () => {
|
|||
testBed.configureTestingModule({
|
||||
imports: [FormsModule, ReactiveFormsModule, AngularSvgIconModule, HttpModule,
|
||||
HttpClientModule, RouterTestingModule.withRoutes(routes), SharedModule, AppModule],
|
||||
declarations: [WorkbasketListToolbarComponent,
|
||||
FilterComponent, IconTypeComponent, DummyDetailComponent, ImportExportComponent],
|
||||
declarations: [WorkbasketListToolbarComponent, DummyDetailComponent, ImportExportComponent],
|
||||
providers: [
|
||||
WorkbasketService,
|
||||
ClassificationDefinitionService,
|
||||
|
|
|
@ -1,61 +1,77 @@
|
|||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import {animate, keyframes, style, transition, trigger} from '@angular/animations';
|
||||
import {ActivatedRoute, Router} from '@angular/router';
|
||||
|
||||
import { SortingModel } from 'app/models/sorting';
|
||||
import { FilterModel } from 'app/models/filter';
|
||||
import { Subscription } from 'rxjs/Subscription';
|
||||
import { WorkbasketSummary } from 'app/models/workbasket-summary';
|
||||
import {SortingModel} from 'app/models/sorting';
|
||||
import {FilterModel} from 'app/models/filter';
|
||||
import {Subscription} from 'rxjs/Subscription';
|
||||
import {WorkbasketSummary} from 'app/models/workbasket-summary';
|
||||
|
||||
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
||||
import { RequestInProgressService } from 'app/services/requestInProgress/request-in-progress.service';
|
||||
import { WorkbasketService } from 'app/services/workbasket/workbasket.service';
|
||||
import { AlertService } from 'app/services/alert/alert.service';
|
||||
import { ImportType } from 'app/models/import-type';
|
||||
import { expandDown } from 'app/shared/animations/expand.animation';
|
||||
import {ErrorModalService} from 'app/services/errorModal/error-modal.service';
|
||||
import {RequestInProgressService} from 'app/services/requestInProgress/request-in-progress.service';
|
||||
import {WorkbasketService} from 'app/services/workbasket/workbasket.service';
|
||||
import {AlertService} from 'app/services/alert/alert.service';
|
||||
import {TaskanaType} from 'app/models/taskana-type';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-workbasket-list-toolbar',
|
||||
animations: [expandDown],
|
||||
templateUrl: './workbasket-list-toolbar.component.html',
|
||||
styleUrls: ['./workbasket-list-toolbar.component.scss']
|
||||
selector: 'taskana-workbasket-list-toolbar',
|
||||
animations: [
|
||||
trigger('toggle', [
|
||||
transition('void => *', animate('300ms ease-in', keyframes([
|
||||
style({height: '0px'}),
|
||||
style({height: '50px'}),
|
||||
style({height: '*'})]))),
|
||||
transition('* => void', animate('300ms ease-out', keyframes([
|
||||
style({height: '*'}),
|
||||
style({height: '50px'}),
|
||||
style({height: '0px'})])))
|
||||
]
|
||||
)],
|
||||
templateUrl: './workbasket-list-toolbar.component.html',
|
||||
styleUrls: ['./workbasket-list-toolbar.component.scss']
|
||||
})
|
||||
export class WorkbasketListToolbarComponent implements OnInit {
|
||||
|
||||
|
||||
@Input() workbaskets: Array<WorkbasketSummary>;
|
||||
@Output() performSorting = new EventEmitter<SortingModel>();
|
||||
@Output() performFilter = new EventEmitter<FilterModel>();
|
||||
@Output() importSucessful = new EventEmitter();
|
||||
workbasketServiceSubscription: Subscription;
|
||||
selectionToImport = ImportType.WORKBASKETS;
|
||||
sortingFields = new Map([['name', 'Name'], ['key', 'Key'], ['description', 'Description'], ['owner', 'Owner'], ['type', 'Type']]);
|
||||
toolbarState = false;
|
||||
@Input() workbaskets: Array<WorkbasketSummary>;
|
||||
@Output() performSorting = new EventEmitter<SortingModel>();
|
||||
@Output() performFilter = new EventEmitter<FilterModel>();
|
||||
@Output() importSucessful = new EventEmitter();
|
||||
workbasketServiceSubscription: Subscription;
|
||||
selectionToImport = TaskanaType.WORKBASKETS;
|
||||
sortingFields = new Map([['name', 'Name'], ['key', 'Key'], ['description', 'Description'], ['owner', 'Owner'], ['type', 'Type']]);
|
||||
filteringTypes = new Map([['ALL', 'All'], ['PERSONAL', 'Personal'], ['GROUP', 'Group'],
|
||||
['CLEARANCE', 'Clearance'], ['TOPIC', 'Topic']]);
|
||||
filterParams = {name: '', key: '', type: '', description: '', owner: ''};
|
||||
toolbarState = false;
|
||||
filterType = TaskanaType.WORKBASKETS;
|
||||
|
||||
constructor(
|
||||
private workbasketService: WorkbasketService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private errorModalService: ErrorModalService,
|
||||
private requestInProgressService: RequestInProgressService,
|
||||
private alertService: AlertService) { }
|
||||
constructor(
|
||||
private workbasketService: WorkbasketService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private errorModalService: ErrorModalService,
|
||||
private requestInProgressService: RequestInProgressService,
|
||||
private alertService: AlertService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
sorting(sort: SortingModel) {
|
||||
this.performSorting.emit(sort);
|
||||
}
|
||||
sorting(sort: SortingModel) {
|
||||
this.performSorting.emit(sort);
|
||||
}
|
||||
|
||||
filtering(filterBy: FilterModel) {
|
||||
this.performFilter.emit(filterBy);
|
||||
}
|
||||
filtering(filterBy: FilterModel) {
|
||||
this.performFilter.emit(filterBy);
|
||||
}
|
||||
|
||||
addWorkbasket() {
|
||||
this.workbasketService.selectWorkBasket(undefined);
|
||||
this.router.navigate([{ outlets: { detail: ['new-workbasket'] } }], { relativeTo: this.route });
|
||||
}
|
||||
addWorkbasket() {
|
||||
this.workbasketService.selectWorkBasket(undefined);
|
||||
this.router.navigate([{outlets: {detail: ['new-workbasket']}}], {relativeTo: this.route});
|
||||
}
|
||||
|
||||
importEvent() {
|
||||
this.importSucessful.emit();
|
||||
}
|
||||
importEvent() {
|
||||
this.importSucessful.emit();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,182 +1,182 @@
|
|||
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { async, ComponentFixture, TestBed, tick, fakeAsync } from '@angular/core/testing';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import {Component, EventEmitter, Input, Output} from '@angular/core';
|
||||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {Observable} from 'rxjs/Observable';
|
||||
|
||||
import { AngularSvgIconModule } from 'angular-svg-icon';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { HttpModule } from '@angular/http';
|
||||
import { Routes } from '@angular/router';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { SharedModule } from 'app/shared/shared.module';
|
||||
import { AppModule } from 'app/app.module';
|
||||
import {AngularSvgIconModule} from 'angular-svg-icon';
|
||||
import {HttpClientModule} from '@angular/common/http';
|
||||
import {HttpModule} from '@angular/http';
|
||||
import {Routes} from '@angular/router';
|
||||
import {RouterTestingModule} from '@angular/router/testing';
|
||||
import {SharedModule} from 'app/shared/shared.module';
|
||||
import {AppModule} from 'app/app.module';
|
||||
|
||||
import { WorkbasketSummary } from 'app/models/workbasket-summary';
|
||||
import { WorkbasketSummaryResource } from 'app/models/workbasket-summary-resource';
|
||||
import { FilterModel } from 'app/models/filter';
|
||||
import { LinksWorkbasketSummary } from 'app/models/links-workbasket-summary';
|
||||
import {WorkbasketSummary} from 'app/models/workbasket-summary';
|
||||
import {WorkbasketSummaryResource} from 'app/models/workbasket-summary-resource';
|
||||
import {FilterModel} from 'app/models/filter';
|
||||
import {LinksWorkbasketSummary} from 'app/models/links-workbasket-summary';
|
||||
|
||||
|
||||
import { WorkbasketListComponent } from './workbasket-list.component';
|
||||
import { WorkbasketListToolbarComponent } from './workbasket-list-toolbar/workbasket-list-toolbar.component';
|
||||
import { IconTypeComponent } from 'app/administration/components/type-icon/icon-type.component';
|
||||
import { ImportExportComponent } from 'app/administration/components/import-export/import-export.component';
|
||||
import {WorkbasketListComponent} from './workbasket-list.component';
|
||||
import {WorkbasketListToolbarComponent} from './workbasket-list-toolbar/workbasket-list-toolbar.component';
|
||||
import {ImportExportComponent} from 'app/administration/components/import-export/import-export.component';
|
||||
|
||||
import { WorkbasketDefinitionService } from 'app/administration/services/workbasket-definition/workbasket-definition.service';
|
||||
import { ClassificationDefinitionService } from 'app/administration/services/classification-definition/classification-definition.service';
|
||||
import { WorkbasketService } from 'app/services/workbasket/workbasket.service';
|
||||
import { OrientationService } from 'app/services/orientation/orientation.service';
|
||||
import { Orientation } from '../../../../models/orientation';
|
||||
import { configureTests } from 'app/app.test.configuration';
|
||||
import {WorkbasketDefinitionService} from 'app/administration/services/workbasket-definition/workbasket-definition.service';
|
||||
import {ClassificationDefinitionService} from 'app/administration/services/classification-definition/classification-definition.service';
|
||||
import {WorkbasketService} from 'app/services/workbasket/workbasket.service';
|
||||
import {OrientationService} from 'app/services/orientation/orientation.service';
|
||||
import {configureTests} from 'app/app.test.configuration';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-dummy-detail',
|
||||
template: 'dummydetail'
|
||||
selector: 'taskana-dummy-detail',
|
||||
template: 'dummydetail'
|
||||
})
|
||||
class DummyDetailComponent {
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-pagination',
|
||||
template: 'dummydetail'
|
||||
selector: 'taskana-pagination',
|
||||
template: 'dummydetail'
|
||||
})
|
||||
class PaginationComponent {
|
||||
@Input()
|
||||
workbasketsResource: any;
|
||||
@Output()
|
||||
workbasketsResourceChange = new EventEmitter<any>();
|
||||
@Output() changePage = new EventEmitter<any>();
|
||||
@Input()
|
||||
workbasketsResource: any;
|
||||
@Output()
|
||||
workbasketsResourceChange = new EventEmitter<any>();
|
||||
@Output() changePage = new EventEmitter<any>();
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-filter',
|
||||
template: ''
|
||||
selector: 'taskana-filter',
|
||||
template: ''
|
||||
})
|
||||
class FilterComponent {
|
||||
|
||||
}
|
||||
|
||||
const workbasketSummaryResource: WorkbasketSummaryResource = new WorkbasketSummaryResource({
|
||||
'workbaskets': new Array<WorkbasketSummary>(
|
||||
new WorkbasketSummary('1', 'key1', 'NAME1', 'description 1', 'owner 1', '', '', 'PERSONAL', '', '', '', ''),
|
||||
new WorkbasketSummary('2', 'key2', 'NAME2', 'description 2', 'owner 2', '', '', 'GROUP', '', '', '', ''))
|
||||
}, new LinksWorkbasketSummary({ 'href': 'url' }));
|
||||
'workbaskets': new Array<WorkbasketSummary>(
|
||||
new WorkbasketSummary('1', 'key1', 'NAME1', 'description 1', 'owner 1', '', '', 'PERSONAL', '', '', '', ''),
|
||||
new WorkbasketSummary('2', 'key2', 'NAME2', 'description 2', 'owner 2', '', '', 'GROUP', '', '', '', ''))
|
||||
}, new LinksWorkbasketSummary({'href': 'url'}));
|
||||
|
||||
|
||||
describe('WorkbasketListComponent', () => {
|
||||
let component: WorkbasketListComponent;
|
||||
let fixture: ComponentFixture<WorkbasketListComponent>;
|
||||
let debugElement: any = undefined;
|
||||
let workbasketService: WorkbasketService;
|
||||
let workbasketSummarySpy;
|
||||
let component: WorkbasketListComponent;
|
||||
let fixture: ComponentFixture<WorkbasketListComponent>;
|
||||
let debugElement: any = undefined;
|
||||
let workbasketService: WorkbasketService;
|
||||
let workbasketSummarySpy;
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: ':id', component: DummyDetailComponent, outlet: 'detail' },
|
||||
{ path: 'workbaskets', component: DummyDetailComponent }
|
||||
];
|
||||
const routes: Routes = [
|
||||
{path: ':id', component: DummyDetailComponent, outlet: 'detail'},
|
||||
{path: 'workbaskets', component: DummyDetailComponent}
|
||||
];
|
||||
|
||||
|
||||
beforeEach(done => {
|
||||
const configure = (testBed: TestBed) => {
|
||||
testBed.configureTestingModule({
|
||||
declarations: [WorkbasketListComponent, DummyDetailComponent, FilterComponent, WorkbasketListToolbarComponent,
|
||||
IconTypeComponent, PaginationComponent, ImportExportComponent],
|
||||
imports: [
|
||||
AngularSvgIconModule,
|
||||
HttpModule,
|
||||
HttpClientModule,
|
||||
RouterTestingModule.withRoutes(routes),
|
||||
SharedModule,
|
||||
AppModule
|
||||
],
|
||||
providers: [
|
||||
WorkbasketService,
|
||||
WorkbasketDefinitionService,
|
||||
ClassificationDefinitionService,
|
||||
OrientationService
|
||||
]
|
||||
});
|
||||
};
|
||||
configureTests(configure).then(testBed => {
|
||||
fixture = TestBed.createComponent(WorkbasketListComponent);
|
||||
component = fixture.componentInstance;
|
||||
debugElement = fixture.debugElement.nativeElement;
|
||||
workbasketService = TestBed.get(WorkbasketService);
|
||||
const orientationService = TestBed.get(OrientationService);
|
||||
workbasketSummarySpy = spyOn(workbasketService, 'getWorkBasketsSummary').and.returnValue(Observable.of(workbasketSummaryResource));
|
||||
spyOn(workbasketService, 'getSelectedWorkBasket').and.returnValue(Observable.of('2'));
|
||||
spyOn(orientationService, 'getOrientation').and.returnValue(Observable.of(undefined));
|
||||
beforeEach(done => {
|
||||
const configure = (testBed: TestBed) => {
|
||||
testBed.configureTestingModule({
|
||||
declarations: [WorkbasketListComponent, DummyDetailComponent, WorkbasketListToolbarComponent,
|
||||
PaginationComponent, ImportExportComponent],
|
||||
imports: [
|
||||
AngularSvgIconModule,
|
||||
HttpModule,
|
||||
HttpClientModule,
|
||||
RouterTestingModule.withRoutes(routes),
|
||||
SharedModule,
|
||||
AppModule
|
||||
],
|
||||
providers: [
|
||||
WorkbasketService,
|
||||
WorkbasketDefinitionService,
|
||||
ClassificationDefinitionService,
|
||||
OrientationService
|
||||
]
|
||||
});
|
||||
};
|
||||
configureTests(configure).then(testBed => {
|
||||
fixture = TestBed.createComponent(WorkbasketListComponent);
|
||||
component = fixture.componentInstance;
|
||||
debugElement = fixture.debugElement.nativeElement;
|
||||
workbasketService = TestBed.get(WorkbasketService);
|
||||
const orientationService = TestBed.get(OrientationService);
|
||||
workbasketSummarySpy = spyOn(workbasketService, 'getWorkBasketsSummary').and.returnValue(Observable.of(workbasketSummaryResource));
|
||||
spyOn(workbasketService, 'getSelectedWorkBasket').and.returnValue(Observable.of('2'));
|
||||
spyOn(orientationService, 'getOrientation').and.returnValue(Observable.of(undefined));
|
||||
|
||||
fixture.detectChanges();
|
||||
done();
|
||||
});
|
||||
fixture.detectChanges();
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.detectChanges();
|
||||
document.body.removeChild(debugElement);
|
||||
});
|
||||
afterEach(() => {
|
||||
fixture.detectChanges();
|
||||
document.body.removeChild(debugElement);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
it('should be created', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should call workbasketService.getWorkbasketsSummary method on init', () => {
|
||||
component.ngOnInit();
|
||||
expect(workbasketService.getWorkBasketsSummary).toHaveBeenCalled();
|
||||
workbasketService.getWorkBasketsSummary().subscribe(value => {
|
||||
expect(value).toBe(workbasketSummaryResource);
|
||||
})
|
||||
});
|
||||
it('should call workbasketService.getWorkbasketsSummary method on init', () => {
|
||||
component.ngOnInit();
|
||||
expect(workbasketService.getWorkBasketsSummary).toHaveBeenCalled();
|
||||
workbasketService.getWorkBasketsSummary().subscribe(value => {
|
||||
expect(value).toBe(workbasketSummaryResource);
|
||||
})
|
||||
});
|
||||
|
||||
it('should have wb-action-toolbar, wb-search-bar, wb-list-container, wb-pagination,' +
|
||||
' collapsedMenufilterWb and taskana-filter created in the html', () => {
|
||||
expect(debugElement.querySelector('#wb-action-toolbar')).toBeDefined();
|
||||
expect(debugElement.querySelector('#wb-search-bar')).toBeDefined();
|
||||
expect(debugElement.querySelector('#wb-pagination')).toBeDefined();
|
||||
expect(debugElement.querySelector('#wb-list-container')).toBeDefined();
|
||||
expect(debugElement.querySelector('#collapsedMenufilterWb')).toBeDefined();
|
||||
expect(debugElement.querySelector('taskana-filter')).toBeDefined();
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li').length).toBe(3);
|
||||
});
|
||||
it('should have wb-action-toolbar, wb-search-bar, wb-list-container, wb-pagination,' +
|
||||
' collapsedMenufilterWb and taskana-filter created in the html', () => {
|
||||
expect(debugElement.querySelector('#wb-action-toolbar')).toBeDefined();
|
||||
expect(debugElement.querySelector('#wb-search-bar')).toBeDefined();
|
||||
expect(debugElement.querySelector('#wb-pagination')).toBeDefined();
|
||||
expect(debugElement.querySelector('#wb-list-container')).toBeDefined();
|
||||
expect(debugElement.querySelector('#collapsedMenufilterWb')).toBeDefined();
|
||||
expect(debugElement.querySelector('taskana-filter')).toBeDefined();
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li').length).toBe(3);
|
||||
});
|
||||
|
||||
// it('should have two workbasketsummary rows created with the second one selected.', fakeAsync(() => {
|
||||
// tick(0);
|
||||
// fixture.detectChanges();
|
||||
// fixture.whenStable().then(() => {
|
||||
// expect(debugElement.querySelectorAll('#wb-list-container > li').length).toBe(3);
|
||||
// expect(debugElement.querySelectorAll('#wb-list-container > li')[1].getAttribute('class'))
|
||||
// .toBe('list-group-item ng-star-inserted');
|
||||
// expect(debugElement.querySelectorAll('#wb-list-container > li')[2].getAttribute('class'))
|
||||
// .toBe('list-group-item ng-star-inserted active');
|
||||
// })
|
||||
//
|
||||
// }));
|
||||
// it('should have two workbasketsummary rows created with the second one selected.', fakeAsync(() => {
|
||||
// tick(0);
|
||||
// fixture.detectChanges();
|
||||
// fixture.whenStable().then(() => {
|
||||
// expect(debugElement.querySelectorAll('#wb-list-container > li').length).toBe(3);
|
||||
// expect(debugElement.querySelectorAll('#wb-list-container > li')[1].getAttribute('class'))
|
||||
// .toBe('list-group-item ng-star-inserted');
|
||||
// expect(debugElement.querySelectorAll('#wb-list-container > li')[2].getAttribute('class'))
|
||||
// .toBe('list-group-item ng-star-inserted active');
|
||||
// })
|
||||
//
|
||||
// }));
|
||||
|
||||
it('should have two workbasketsummary rows created with two different icons: user and users', () => {
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li')[1]
|
||||
.querySelector('svg-icon').getAttribute('ng-reflect-src')).toBe('./assets/icons/user.svg');
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li')[2]
|
||||
.querySelector('svg-icon').getAttribute('ng-reflect-src')).toBe('./assets/icons/users.svg');
|
||||
});
|
||||
it('should have two workbasketsummary rows created with two different icons: user and users', () => {
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li')[1]
|
||||
.querySelector('svg-icon').getAttribute('ng-reflect-src')).toBe('./assets/icons/user.svg');
|
||||
expect(debugElement.querySelectorAll('#wb-list-container > li')[2]
|
||||
.querySelector('svg-icon').getAttribute('ng-reflect-src')).toBe('./assets/icons/users.svg');
|
||||
});
|
||||
|
||||
it('should have rendered sort by: name, id, description, owner and type', () => {
|
||||
expect(debugElement.querySelector('#sort-by-name')).toBeDefined();
|
||||
expect(debugElement.querySelector('#sort-by-key')).toBeDefined();
|
||||
expect(debugElement.querySelector('#sort-by-description')).toBeDefined();
|
||||
expect(debugElement.querySelector('#sort-by-owner')).toBeDefined();
|
||||
expect(debugElement.querySelector('#sort-by-type')).toBeDefined();
|
||||
it('should have rendered sort by: name, id, description, owner and type', () => {
|
||||
expect(debugElement.querySelector('#sort-by-name')).toBeDefined();
|
||||
expect(debugElement.querySelector('#sort-by-key')).toBeDefined();
|
||||
expect(debugElement.querySelector('#sort-by-description')).toBeDefined();
|
||||
expect(debugElement.querySelector('#sort-by-owner')).toBeDefined();
|
||||
expect(debugElement.querySelector('#sort-by-type')).toBeDefined();
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
it('should have performRequest with forced = true after performFilter is triggered', (() => {
|
||||
const type = 'PERSONAL', name = 'someName', description = 'someDescription', owner = 'someOwner', key = 'someKey';
|
||||
const filter = new FilterModel(type, name, description, owner, key);
|
||||
component.performFilter(filter);
|
||||
it('should have performRequest with forced = true after performFilter is triggered', (() => {
|
||||
const filter = new FilterModel({
|
||||
name: 'someName', owner: 'someOwner', description: 'someDescription',
|
||||
key: 'someKey', type: 'PERSONAL'
|
||||
});
|
||||
component.performFilter(filter);
|
||||
|
||||
expect(workbasketSummarySpy.calls.all()[1].args).toEqual([true, 'key', 'asc',
|
||||
undefined, 'someName', 'someDescription', undefined, 'someOwner', 'PERSONAL', undefined, 'someKey', undefined]);
|
||||
expect(workbasketSummarySpy.calls.all()[1].args).toEqual([true, 'key', 'asc',
|
||||
undefined, 'someName', 'someDescription', undefined, 'someOwner', 'PERSONAL', undefined, 'someKey', undefined]);
|
||||
|
||||
}));
|
||||
}));
|
||||
|
||||
});
|
||||
|
|
|
@ -1,113 +1,121 @@
|
|||
import {
|
||||
Component, OnInit, OnDestroy,
|
||||
ViewChild, ElementRef, ChangeDetectorRef
|
||||
} from '@angular/core';
|
||||
import { Router, ActivatedRoute } from '@angular/router';
|
||||
import { Subscription } from 'rxjs/Subscription';
|
||||
import {ChangeDetectorRef, Component, ElementRef, OnDestroy, OnInit, ViewChild} from '@angular/core';
|
||||
import {ActivatedRoute, Router} from '@angular/router';
|
||||
import {Subscription} from 'rxjs/Subscription';
|
||||
|
||||
import { WorkbasketSummaryResource } from 'app/models/workbasket-summary-resource';
|
||||
import { WorkbasketSummary } from 'app/models/workbasket-summary';
|
||||
import { FilterModel } from 'app/models/filter'
|
||||
import { SortingModel } from 'app/models/sorting';
|
||||
import { Orientation } from 'app/models/orientation';
|
||||
import {WorkbasketSummaryResource} from 'app/models/workbasket-summary-resource';
|
||||
import {WorkbasketSummary} from 'app/models/workbasket-summary';
|
||||
import {FilterModel} from 'app/models/filter'
|
||||
import {SortingModel} from 'app/models/sorting';
|
||||
import {Orientation} from 'app/models/orientation';
|
||||
|
||||
import { WorkbasketService } from 'app/services/workbasket/workbasket.service'
|
||||
import { OrientationService } from 'app/services/orientation/orientation.service';
|
||||
import { TaskanaQueryParameters } from 'app/shared/util/query-parameters';
|
||||
import {WorkbasketService} from 'app/services/workbasket/workbasket.service'
|
||||
import {OrientationService} from 'app/services/orientation/orientation.service';
|
||||
import {TaskanaQueryParameters} from 'app/shared/util/query-parameters';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-workbasket-list',
|
||||
templateUrl: './workbasket-list.component.html',
|
||||
styleUrls: ['./workbasket-list.component.scss']
|
||||
selector: 'taskana-workbasket-list',
|
||||
templateUrl: './workbasket-list.component.html',
|
||||
styleUrls: ['./workbasket-list.component.scss']
|
||||
})
|
||||
export class WorkbasketListComponent implements OnInit, OnDestroy {
|
||||
|
||||
selectedId = '';
|
||||
workbasketsResource: WorkbasketSummaryResource;
|
||||
workbaskets: Array<WorkbasketSummary> = [];
|
||||
requestInProgress = false;
|
||||
selectedId = '';
|
||||
workbasketsResource: WorkbasketSummaryResource;
|
||||
workbaskets: Array<WorkbasketSummary> = [];
|
||||
requestInProgress = false;
|
||||
|
||||
sort: SortingModel = new SortingModel();
|
||||
filterBy: FilterModel = new FilterModel();
|
||||
sort: SortingModel = new SortingModel();
|
||||
filterBy: FilterModel = new FilterModel({name: '', owner: '', type: '', description: '', key: ''});
|
||||
|
||||
@ViewChild('wbToolbar')
|
||||
private toolbarElement: ElementRef;
|
||||
private workBasketSummarySubscription: Subscription;
|
||||
private workbasketServiceSubscription: Subscription;
|
||||
private workbasketServiceSavedSubscription: Subscription;
|
||||
private orientationSubscription: Subscription;
|
||||
@ViewChild('wbToolbar')
|
||||
private toolbarElement: ElementRef;
|
||||
private workBasketSummarySubscription: Subscription;
|
||||
private workbasketServiceSubscription: Subscription;
|
||||
private workbasketServiceSavedSubscription: Subscription;
|
||||
private orientationSubscription: Subscription;
|
||||
|
||||
constructor(
|
||||
private workbasketService: WorkbasketService,
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
private orientationService: OrientationService,
|
||||
private cd: ChangeDetectorRef) { }
|
||||
constructor(
|
||||
private workbasketService: WorkbasketService,
|
||||
private router: Router,
|
||||
private route: ActivatedRoute,
|
||||
private orientationService: OrientationService,
|
||||
private cd: ChangeDetectorRef) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.requestInProgress = true;
|
||||
this.workbasketServiceSubscription = this.workbasketService.getSelectedWorkBasket().subscribe(workbasketIdSelected => {
|
||||
// TODO should be done in a different way.
|
||||
setTimeout(() => { this.selectedId = workbasketIdSelected; }, 0);
|
||||
});
|
||||
ngOnInit() {
|
||||
this.requestInProgress = true;
|
||||
this.workbasketServiceSubscription = this.workbasketService.getSelectedWorkBasket().subscribe(workbasketIdSelected => {
|
||||
// TODO should be done in a different way.
|
||||
setTimeout(() => {
|
||||
this.selectedId = workbasketIdSelected;
|
||||
}, 0);
|
||||
});
|
||||
|
||||
this.workbasketServiceSavedSubscription = this.workbasketService.workbasketSavedTriggered().subscribe(value => {
|
||||
this.performRequest();
|
||||
});
|
||||
this.orientationSubscription = this.orientationService.getOrientation().subscribe((orientation: Orientation) => {
|
||||
this.refreshWorkbasketList();
|
||||
})
|
||||
}
|
||||
this.workbasketServiceSavedSubscription = this.workbasketService.workbasketSavedTriggered().subscribe(value => {
|
||||
this.performRequest();
|
||||
});
|
||||
this.orientationSubscription = this.orientationService.getOrientation().subscribe((orientation: Orientation) => {
|
||||
this.refreshWorkbasketList();
|
||||
})
|
||||
}
|
||||
|
||||
selectWorkbasket(id: string) {
|
||||
this.selectedId = id;
|
||||
this.router.navigate([{ outlets: { detail: [this.selectedId] } }], { relativeTo: this.route });
|
||||
}
|
||||
selectWorkbasket(id: string) {
|
||||
this.selectedId = id;
|
||||
this.router.navigate([{outlets: {detail: [this.selectedId]}}], {relativeTo: this.route});
|
||||
}
|
||||
|
||||
performSorting(sort: SortingModel) {
|
||||
this.sort = sort;
|
||||
this.performRequest();
|
||||
}
|
||||
performSorting(sort: SortingModel) {
|
||||
this.sort = sort;
|
||||
this.performRequest();
|
||||
}
|
||||
|
||||
performFilter(filterBy: FilterModel) {
|
||||
this.filterBy = filterBy;
|
||||
this.performRequest();
|
||||
}
|
||||
performFilter(filterBy: FilterModel) {
|
||||
this.filterBy = filterBy;
|
||||
this.performRequest();
|
||||
}
|
||||
|
||||
changePage(page) {
|
||||
TaskanaQueryParameters.page = page;
|
||||
this.performRequest();
|
||||
}
|
||||
changePage(page) {
|
||||
TaskanaQueryParameters.page = page;
|
||||
this.performRequest();
|
||||
}
|
||||
|
||||
refreshWorkbasketList() {
|
||||
const toolbarSize = this.toolbarElement.nativeElement.offsetHeight;
|
||||
const cardHeight = 75;
|
||||
const unusedHeight = 145
|
||||
const totalHeight = window.innerHeight;
|
||||
const cards = Math.round((totalHeight - (unusedHeight + toolbarSize)) / cardHeight);
|
||||
TaskanaQueryParameters.pageSize = cards;
|
||||
this.performRequest();
|
||||
}
|
||||
refreshWorkbasketList() {
|
||||
const toolbarSize = this.toolbarElement.nativeElement.offsetHeight;
|
||||
const cardHeight = 75;
|
||||
const unusedHeight = 145;
|
||||
const totalHeight = window.innerHeight;
|
||||
const cards = Math.round((totalHeight - (unusedHeight + toolbarSize)) / cardHeight);
|
||||
TaskanaQueryParameters.pageSize = cards;
|
||||
this.performRequest();
|
||||
}
|
||||
|
||||
private performRequest(): void {
|
||||
this.requestInProgress = true;
|
||||
this.workbaskets = [];
|
||||
this.workbasketServiceSubscription = this.workbasketService.getWorkBasketsSummary(
|
||||
true, this.sort.sortBy, this.sort.sortDirection, undefined,
|
||||
this.filterBy.name, this.filterBy.description, undefined, this.filterBy.owner,
|
||||
this.filterBy.type, undefined, this.filterBy.key, undefined)
|
||||
.subscribe(resultList => {
|
||||
this.workbasketsResource = resultList;
|
||||
this.workbaskets = resultList._embedded ? resultList._embedded.workbaskets : [];
|
||||
this.requestInProgress = false;
|
||||
});
|
||||
}
|
||||
private performRequest(): void {
|
||||
this.requestInProgress = true;
|
||||
this.workbaskets = [];
|
||||
this.workbasketServiceSubscription = this.workbasketService.getWorkBasketsSummary(
|
||||
true, this.sort.sortBy, this.sort.sortDirection, undefined,
|
||||
this.filterBy.filterParams.name, this.filterBy.filterParams.description, undefined, this.filterBy.filterParams.owner,
|
||||
this.filterBy.filterParams.type, undefined, this.filterBy.filterParams.key, undefined)
|
||||
.subscribe(resultList => {
|
||||
this.workbasketsResource = resultList;
|
||||
this.workbaskets = resultList._embedded ? resultList._embedded.workbaskets : [];
|
||||
this.requestInProgress = false;
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
if (this.workBasketSummarySubscription) { this.workBasketSummarySubscription.unsubscribe(); }
|
||||
if (this.workbasketServiceSubscription) { this.workbasketServiceSubscription.unsubscribe(); }
|
||||
if (this.workbasketServiceSavedSubscription) { this.workbasketServiceSavedSubscription.unsubscribe(); }
|
||||
if (this.orientationSubscription) { this.orientationSubscription.unsubscribe(); }
|
||||
ngOnDestroy() {
|
||||
if (this.workBasketSummarySubscription) {
|
||||
this.workBasketSummarySubscription.unsubscribe();
|
||||
}
|
||||
if (this.workbasketServiceSubscription) {
|
||||
this.workbasketServiceSubscription.unsubscribe();
|
||||
}
|
||||
if (this.workbasketServiceSavedSubscription) {
|
||||
this.workbasketServiceSavedSubscription.unsubscribe();
|
||||
}
|
||||
if (this.orientationSubscription) {
|
||||
this.orientationSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,7 @@
|
|||
export class FilterModel {
|
||||
type: string;
|
||||
name: string;
|
||||
description: string;
|
||||
owner: string;
|
||||
key: string;
|
||||
constructor(type: string = '', name: string = '', description: string = '', owner: string = '', key: string = '') {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.owner = owner;
|
||||
this.key = key;
|
||||
}
|
||||
filterParams: any;
|
||||
|
||||
constructor(filterParams?: any) {
|
||||
this.filterParams = filterParams;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
export enum ImportType {
|
||||
WORKBASKETS,
|
||||
CLASSIFICATIONS
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
export enum TaskanaType {
|
||||
WORKBASKETS,
|
||||
CLASSIFICATIONS,
|
||||
TASKS
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
<div class="list-group-search">
|
||||
<div class="row">
|
||||
|
||||
<div *ngIf="filterTypeIsWorkbasket(); else tasktype">
|
||||
<div class="dropdown col-xs-2">
|
||||
<button class="btn btn-default" data-toggle="dropdown" type="button" id="dropdownMenufilter"
|
||||
data-toggle="dropdown" aria-haspopup="true"
|
||||
aria-expanded="true">
|
||||
<taskana-icon-type [type]="filter.filterParams?.type" class="vertical-align"></taskana-icon-type>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-users" role="menu">
|
||||
<li>
|
||||
<a *ngFor="let type of allTypes | mapValues" type="button" (click)="selectType(type.key); search()"
|
||||
data-toggle="tooltip"
|
||||
[title]="type.value">
|
||||
<taskana-icon-type class="vertical-align" [type]='type.key' [text]="type.value"></taskana-icon-type>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-4">
|
||||
<input type="text" [(ngModel)]="filter.filterParams.name" (keyup.enter)="search()" class="form-control"
|
||||
id="display-name-filter" placeholder="Filter name">
|
||||
</div>
|
||||
|
||||
<div class="col-xs-4">
|
||||
<input type="text" [(ngModel)]="filter.filterParams.key" (keyup.enter)="search()" class="form-control"
|
||||
id="display-key-filter" placeholder="Filter key">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-template #tasktype>
|
||||
<div class="col-xs-2">
|
||||
</div>
|
||||
|
||||
<div class="col-xs-8">
|
||||
<input type="text" [(ngModel)]="filter.filterParams.name" (keyup.enter)="search()" class="form-control"
|
||||
id="display-name-filter" placeholder="Filter name">
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<button (click)="clear(); search()" type="button"
|
||||
class="btn btn-default glyphicon glyphicon-ban-circle blue pull-right margin-right"
|
||||
data-toggle="tooltip" title="Clear">
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="filter-list">
|
||||
<li class="" *ngFor="let filterType of getUnusedKeys()">
|
||||
<div class="row padding">
|
||||
<div class="col-xs-2">
|
||||
</div>
|
||||
<div class="col-xs-8">
|
||||
<div *ngIf="checkUppercaseFilterType(filterType); else normalFilter">
|
||||
<input type="text" [(ngModel)]="filter.filterParams[filterType]"
|
||||
(ngModelChange)="filter.filterParams[filterType] = $event.toLocaleUpperCase()"
|
||||
(keyup.enter)="search()"
|
||||
class="form-control" id="display-{{filterType}}-filter" placeholder="Filter {{filterType}}">
|
||||
</div>
|
||||
<ng-template #normalFilter>
|
||||
<input type="text" [(ngModel)]="filter.filterParams[filterType]"
|
||||
(keyup.enter)="search()"
|
||||
class="form-control" id="display-{{filterType}}-filter" placeholder="Filter {{filterType}}">
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
<div *ngIf="filterType === lastFilterKey" class="pull-right">
|
||||
<button (click)="search()" type="button"
|
||||
class="btn btn-default glyphicon glyphicon-search blue pull-right margin-right"
|
||||
data-toggle="tooltip" title="Search">
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
</div>
|
|
@ -14,4 +14,12 @@
|
|||
}
|
||||
row.padding {
|
||||
padding: 1px 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.filter-list {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.filter-list > li {
|
||||
padding-top: 5px;
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
import {ComponentFixture, TestBed} from '@angular/core/testing';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {AngularSvgIconModule} from 'angular-svg-icon';
|
||||
import {HttpClientModule} from '@angular/common/http';
|
||||
import {HttpModule} from '@angular/http';
|
||||
|
||||
import {FilterModel} from 'app/models/filter';
|
||||
import {IconTypeComponent} from '../../administration/components/type-icon/icon-type.component';
|
||||
import {FilterComponent} from './filter.component';
|
||||
import {MapValuesPipe} from 'app/shared/pipes/mapValues/map-values.pipe';
|
||||
import {configureTests} from 'app/app.test.configuration';
|
||||
|
||||
describe('FilterComponent', () => {
|
||||
let component: FilterComponent,
|
||||
fixture: ComponentFixture<FilterComponent>,
|
||||
debugElement: any;
|
||||
|
||||
|
||||
beforeEach(done => {
|
||||
const configure = (testBed: TestBed) => {
|
||||
testBed.configureTestingModule({
|
||||
declarations: [FilterComponent, IconTypeComponent, MapValuesPipe],
|
||||
imports: [AngularSvgIconModule, FormsModule, HttpClientModule, HttpModule]
|
||||
})
|
||||
};
|
||||
configureTests(configure).then(testBed => {
|
||||
fixture = TestBed.createComponent(FilterComponent);
|
||||
component = fixture.componentInstance;
|
||||
component.filter = new FilterModel({
|
||||
name: 'someName', owner: 'someOwner', description: 'someDescription',
|
||||
key: 'someKey', type: 'PERSONAL'
|
||||
});
|
||||
debugElement = fixture.debugElement.nativeElement;
|
||||
fixture.detectChanges();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
afterEach((done) => {
|
||||
document.body.removeChild(debugElement);
|
||||
});
|
||||
|
||||
it('should create', (done) => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should create a component', (done) => {
|
||||
expect(debugElement.querySelector('#some-id')).toBeNull();
|
||||
fixture.detectChanges();
|
||||
expect(debugElement.querySelector('#some-id')).toBeDefined();
|
||||
});
|
||||
|
||||
it('should have filter by: name, description, key, owner and type defined', (done) => {
|
||||
expect(debugElement.querySelector('#display-name-filter')).toBeDefined();
|
||||
expect(debugElement.querySelector('#display-description-filter')).toBeDefined();
|
||||
expect(debugElement.querySelector('#display-key-filter')).toBeDefined();
|
||||
expect(debugElement.querySelector('#display-owner-filter')).toBeDefined();
|
||||
expect(debugElement.querySelector('#display-type-filter')).toBeDefined();
|
||||
});
|
||||
|
||||
it('should be able to clear all fields after pressing clear button', (done) => {
|
||||
component.filter = new FilterModel({
|
||||
name: 'someName', owner: 'someOwner', description: 'someDescription',
|
||||
key: 'someKey', type: 'PERSONAL'
|
||||
});
|
||||
debugElement.querySelector('[title="Clear"]').click();
|
||||
expect(component.filter.filterParams.name).toBe('');
|
||||
expect(component.filter.filterParams.description).toBe('');
|
||||
expect(component.filter.filterParams.owner).toBe('');
|
||||
expect(component.filter.filterParams.type).toBe('');
|
||||
expect(component.filter.filterParams.key).toBe('');
|
||||
});
|
||||
|
||||
it('should be able to select a type and return it based on a number', (done) => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should be able to emit a filter after clicking on search button', (done) => {
|
||||
component.filter = new FilterModel({
|
||||
name: 'someName', owner: 'someOwner', description: 'someDescription',
|
||||
key: 'someKey', type: 'PERSONAL'
|
||||
});
|
||||
component.performFilter.subscribe(filter => {
|
||||
expect(filter.name).toBe('someName');
|
||||
done();
|
||||
});
|
||||
debugElement.querySelector('[title="Search"]').click();
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,76 @@
|
|||
import {AfterContentInit, Component, EventEmitter, Input, Output} from '@angular/core';
|
||||
import {ICONTYPES} from 'app/models/type';
|
||||
import {FilterModel} from 'app/models/filter';
|
||||
import {TaskanaType} from 'app/models/taskana-type';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-filter',
|
||||
templateUrl: './filter.component.html',
|
||||
styleUrls: ['./filter.component.scss']
|
||||
})
|
||||
export class FilterComponent implements AfterContentInit {
|
||||
@Input() allTypes: Map<string, string>;
|
||||
|
||||
@Input() filterParams: any;
|
||||
|
||||
@Input() filterType: TaskanaType;
|
||||
|
||||
@Output() performFilter = new EventEmitter<FilterModel>();
|
||||
|
||||
filter: FilterModel;
|
||||
filterParamKeys = [];
|
||||
lastFilterKey: string;
|
||||
toggleDropDown = false;
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
ngAfterContentInit(): void {
|
||||
this.initializeFilterModel();
|
||||
if (this.filterParams) {
|
||||
this.filterParamKeys = Object.keys(this.filterParams);
|
||||
this.lastFilterKey = this.filterParamKeys[this.filterParamKeys.length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
selectType(type: ICONTYPES) {
|
||||
this.filter.filterParams.type = type;
|
||||
}
|
||||
|
||||
clear() {
|
||||
for (const key of Object.keys(this.filterParams)) {
|
||||
this.filterParams[key] = '';
|
||||
}
|
||||
this.initializeFilterModel();
|
||||
}
|
||||
|
||||
search() {
|
||||
this.performFilter.emit(this.filter);
|
||||
}
|
||||
|
||||
initializeFilterModel(): void {
|
||||
this.filter = new FilterModel(this.filterParams);
|
||||
}
|
||||
|
||||
checkUppercaseFilterType(filterType: string) {
|
||||
return filterType === 'type' || filterType === 'state';
|
||||
}
|
||||
|
||||
filterTypeIsWorkbasket(): boolean {
|
||||
return this.filterType === TaskanaType.WORKBASKETS;
|
||||
}
|
||||
|
||||
/**
|
||||
* keys that are hardcoded in the HTML need to be specified here
|
||||
* @returns {string[]}
|
||||
*/
|
||||
getUnusedKeys(): string[] {
|
||||
const unusedKeys = [];
|
||||
for (const key of this.filterParamKeys) {
|
||||
if (['name', 'key'].indexOf(key) < 0) {
|
||||
unusedKeys.push(key);
|
||||
}
|
||||
}
|
||||
return unusedKeys;
|
||||
}
|
||||
}
|
|
@ -32,6 +32,9 @@ import { MapToIterable } from './pipes/mapToIterable/mapToIterable';
|
|||
*/
|
||||
import { HttpClientInterceptor } from './services/httpClientInterceptor/http-client-interceptor.service';
|
||||
import { AccessIdsService } from './services/access-ids/access-ids.service';
|
||||
import {SortComponent} from 'app/shared/sort/sort.component';
|
||||
import {FilterComponent} from 'app/shared/filter/filter.component';
|
||||
import {IconTypeComponent} from 'app/administration/components/type-icon/icon-type.component';
|
||||
import { FormsValidatorService } from './services/forms/forms-validator.service';
|
||||
|
||||
|
||||
|
@ -61,6 +64,8 @@ const DECLARATIONS = [
|
|||
OrderBy,
|
||||
MapToIterable,
|
||||
SortComponent,
|
||||
FilterComponent,
|
||||
IconTypeComponent,
|
||||
RemoveConfirmationComponent
|
||||
];
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<div class="dropdown clearfix btn-group">
|
||||
<button class="btn btn-default" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||
<button [disabled]="!enabled" class="btn btn-default" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||
<span class="glyphicon {{sort.sortDirection === 'asc'? 'glyphicon-sort-by-attributes-alt' : 'glyphicon-sort-by-attributes' }} blue"
|
||||
data-toggle= "tooltip" title="{{sort.sortDirection === 'asc'? 'A-Z' : 'Z-A' }}"></span>
|
||||
</button>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {Component, OnInit, Output, EventEmitter, Input} from '@angular/core';
|
||||
import { SortingModel, Direction } from 'app/models/sorting';
|
||||
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import {Direction, SortingModel} from 'app/models/sorting';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-sort',
|
||||
|
@ -8,12 +8,14 @@ import { SortingModel, Direction } from 'app/models/sorting';
|
|||
})
|
||||
export class SortComponent implements OnInit {
|
||||
@Input() sortingFields: Map<string, string>;
|
||||
@Input() enabled = true;
|
||||
|
||||
@Output() performSorting = new EventEmitter<SortingModel>();
|
||||
|
||||
@Output()
|
||||
performSorting = new EventEmitter<SortingModel>();
|
||||
sort: SortingModel = new SortingModel();
|
||||
|
||||
constructor() { }
|
||||
constructor() {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
|
|
@ -9,6 +9,14 @@ import {Direction} from 'app/models/sorting';
|
|||
|
||||
@Injectable()
|
||||
export class TaskService {
|
||||
WORKBASKET_ID = 'workbasket-id';
|
||||
SORT_BY = 'sortBy';
|
||||
SORT_DIRECTION = 'order';
|
||||
NAME = 'name';
|
||||
OWNER = 'owner';
|
||||
PRIORITY = 'priority';
|
||||
STATE = 'state';
|
||||
|
||||
url = `${environment.taskanaRestUrl}/v1/tasks`;
|
||||
|
||||
taskChangedSource = new Subject<Task>();
|
||||
|
@ -35,9 +43,12 @@ export class TaskService {
|
|||
*/
|
||||
findTasksWithWorkbasket(basketId: string,
|
||||
sortBy = 'priority',
|
||||
order: string = Direction.ASC): Observable<TaskResource> {
|
||||
|
||||
const url = `${this.url}?workbasket-id=${basketId}&sortBy=${sortBy}&order=${order}`;
|
||||
sortDirection: string = Direction.ASC,
|
||||
name: string,
|
||||
owner: string,
|
||||
priority: string,
|
||||
state: string): Observable<TaskResource> {
|
||||
const url = `${this.url}${this.getTaskQueryParameters(basketId, sortBy, sortDirection, name, owner, priority, state)}`;
|
||||
return this.httpClient.get<TaskResource>(url);
|
||||
}
|
||||
|
||||
|
@ -64,4 +75,26 @@ export class TaskService {
|
|||
deleteTask(task: Task): Observable<Task> {
|
||||
return this.httpClient.delete<Task>(`${this.url}/${task.taskId}`);
|
||||
}
|
||||
|
||||
private getTaskQueryParameters(basketId: string,
|
||||
sortBy: string,
|
||||
sortDirection: string,
|
||||
name: string,
|
||||
owner: string,
|
||||
priority: string,
|
||||
state: string): string {
|
||||
let query = '?';
|
||||
query += basketId ? `${this.WORKBASKET_ID}=${basketId}&` : '';
|
||||
query += `${this.SORT_BY}=${sortBy}&`;
|
||||
query += `${this.SORT_DIRECTION}=${sortDirection}&`;
|
||||
query += name ? `${this.NAME}=${name}&` : '';
|
||||
query += owner ? `${this.OWNER}=${owner}&` : '';
|
||||
query += priority ? `${this.PRIORITY}=${priority}&` : '';
|
||||
query += state ? `${this.STATE}=${state}&` : '';
|
||||
|
||||
if (query.lastIndexOf('&') === query.length - 1) {
|
||||
query = query.slice(0, query.lastIndexOf('&'))
|
||||
}
|
||||
return query;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,23 @@
|
|||
<input type="text" class="form-control" id="task-owner" placeholder="Owner" [(ngModel)]="task.owner"
|
||||
name="task.owner">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="task-priority" disabled class="control-label">Priority</label>
|
||||
<input type="text" class="form-control" id="task-priority" placeholder="no priotity set"
|
||||
[(ngModel)]="task.priority"
|
||||
name="task.priority">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="task-state" class="control-label">State</label>
|
||||
<input type="text" disabled class="form-control" id="task-state" placeholder="Task has no State"
|
||||
[(ngModel)]="task.state"
|
||||
name="task.state">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="task-note" class="control-label">Note</label>
|
||||
<input type="text" class="form-control" id="task-note" placeholder="Task has no Note" [(ngModel)]="task.note"
|
||||
name="task.note">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="task-created" class="control-label">Creation Date</label>
|
||||
<input type="text" disabled class="form-control" id="task-created" [(ngModel)]="task.created"
|
||||
|
@ -65,23 +82,6 @@
|
|||
[(ngModel)]="task.due"
|
||||
name="task.due">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="task-priority" disabled class="control-label">Priority</label>
|
||||
<input type="text" class="form-control" id="task-priority" placeholder="no priotity set"
|
||||
[(ngModel)]="task.priority"
|
||||
name="task.priority">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="task-state" class="control-label">State</label>
|
||||
<input type="text" disabled class="form-control" id="task-state" placeholder="Task has no State"
|
||||
[(ngModel)]="task.state"
|
||||
name="task.state">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="task-note" class="control-label">Note</label>
|
||||
<input type="text" class="form-control" id="task-note" placeholder="Task has no Note" [(ngModel)]="task.note"
|
||||
name="task.note">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="task-workbasket" class="control-label">Workbasket ID</label>
|
||||
<input type="text" disabled class="form-control" id="task-workbasket"
|
||||
|
@ -90,10 +90,10 @@
|
|||
name="task.workbasket">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="task-classification" class="control-label">Classification ID</label>
|
||||
<label for="task-classification" class="control-label">Classification Key</label>
|
||||
<input type="text" disabled class="form-control" id="task-classification"
|
||||
placeholder="Task does not belong to a Classification"
|
||||
[(ngModel)]="task.classificationSummaryResource.classificationId"
|
||||
[(ngModel)]="task.classificationSummaryResource.key"
|
||||
name="task.classification">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
|
@ -1,17 +1,35 @@
|
|||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="input-group">
|
||||
<input [(ngModel)]="result" [typeahead]="workbasketNames" class="form-control" (typeaheadOnSelect)="workbasketSelected = true"
|
||||
typeaheadMinLength="0" (typeaheadNoResults)="workbasketSelected = false" placeholder="Search for Workbasket ..." />
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-primary" type="button" (click)="searchBasket()" [disabled]="!workbasketSelected">Go!</button>
|
||||
<li id="tasklist-action-toolbar" class="list-group-item tab-align">
|
||||
<div class="row">
|
||||
<div class="col-xs-9">
|
||||
<div class="input-group">
|
||||
<input [(ngModel)]="result" [typeahead]="workbasketNames" class="form-control"
|
||||
(typeaheadOnSelect)="workbasketSelected = true" (typeaheadNoResults)="workbasketSelected = false"
|
||||
placeholder="Search for Workbasket ..."/>
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-primary" type="button" (click)="searchBasket()"
|
||||
[disabled]="!workbasketSelected">Go!</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pull-right margin-right">
|
||||
<taskana-sort
|
||||
[enabled]="tasks.length > 0"
|
||||
[sortingFields]="sortingFields"
|
||||
(performSorting)="sorting($event)"></taskana-sort>
|
||||
<button [disabled]="tasks.length === 0" class="btn btn-default collapsed" type="button"
|
||||
id="collapsedMenufilterWb" aria-expanded="false"
|
||||
(click)="toolbarState=!toolbarState">
|
||||
<span class="glyphicon glyphicon-filter blue"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="pull-right margin-right">
|
||||
<taskana-sort [sortingFields]="sortingFields" (performSorting)="sorting($event)"></taskana-sort>
|
||||
</div>
|
||||
<div [@toggle]="toolbarState" *ngIf="toolbarState" class="row no-overflow">
|
||||
<taskana-filter
|
||||
[filterParams]="filterParams"
|
||||
[filterType]="filterType"
|
||||
(performFilter)="filtering($event)">
|
||||
</taskana-filter>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
.list-group-item {
|
||||
padding: 5px 0px 2px 1px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.tab-align{
|
||||
margin-bottom: 0px;
|
||||
|
||||
&>div{
|
||||
margin: 6px 0px;
|
||||
}
|
||||
}
|
|
@ -1,21 +1,39 @@
|
|||
import {Component, EventEmitter, OnInit, Output} from '@angular/core';
|
||||
import {animate, keyframes, style, transition, trigger} from '@angular/animations';
|
||||
import {Task} from 'app/workplace/models/task';
|
||||
import {Workbasket} from 'app/models/workbasket';
|
||||
import {TaskService} from 'app/workplace/services/task.service';
|
||||
import {WorkbasketService} from 'app/services/workbasket/workbasket.service';
|
||||
import {SortingModel} from 'app/models/sorting';
|
||||
import {FilterModel} from 'app/models/filter';
|
||||
import {TaskanaType} from 'app/models/taskana-type';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-tasklist-toolbar',
|
||||
templateUrl: './tasklist-toolbar.component.html'
|
||||
animations: [
|
||||
trigger('toggle', [
|
||||
transition('void => *', animate('300ms ease-in', keyframes([
|
||||
style({height: '0px'}),
|
||||
style({height: '50px'}),
|
||||
style({height: '*'})]))),
|
||||
transition('* => void', animate('300ms ease-out', keyframes([
|
||||
style({height: '*'}),
|
||||
style({height: '50px'}),
|
||||
style({height: '0px'})])))
|
||||
]
|
||||
)],
|
||||
templateUrl: './tasklist-toolbar.component.html',
|
||||
styleUrls: ['./tasklist-toolbar.component.scss']
|
||||
})
|
||||
export class TaskListToolbarComponent implements OnInit {
|
||||
|
||||
@Output() tasksChanged = new EventEmitter<Task[]>();
|
||||
@Output() basketChanged = new EventEmitter<Workbasket>();
|
||||
@Output() performSorting = new EventEmitter<SortingModel>();
|
||||
@Output() performFilter = new EventEmitter<FilterModel>();
|
||||
|
||||
sortingFields = new Map([['name', 'Name'], ['priority', 'Priority'], ['due', 'Due'], ['planned', 'Planned']]);
|
||||
filterParams = {name: '', key: '', owner: '', priority: '', state: ''};
|
||||
tasks: Task[] = [];
|
||||
|
||||
workbasketNames: string[] = [];
|
||||
|
@ -24,6 +42,8 @@ export class TaskListToolbarComponent implements OnInit {
|
|||
workbaskets: Workbasket[];
|
||||
currentBasket: Workbasket;
|
||||
workbasketSelected = false;
|
||||
toolbarState = false;
|
||||
filterType = TaskanaType.TASKS;
|
||||
|
||||
constructor(private taskService: TaskService,
|
||||
private workbasketService: WorkbasketService) {
|
||||
|
@ -39,6 +59,7 @@ export class TaskListToolbarComponent implements OnInit {
|
|||
}
|
||||
|
||||
searchBasket() {
|
||||
this.toolbarState = false;
|
||||
if (this.workbaskets) {
|
||||
this.workbaskets.forEach(workbasket => {
|
||||
if (workbasket.name === this.result) {
|
||||
|
@ -60,7 +81,8 @@ export class TaskListToolbarComponent implements OnInit {
|
|||
}
|
||||
|
||||
getTasks(workbasketId: string) {
|
||||
this.taskService.findTasksWithWorkbasket(workbasketId).subscribe(
|
||||
this.taskService.findTasksWithWorkbasket(workbasketId, undefined, undefined,
|
||||
undefined, undefined, undefined, undefined).subscribe(
|
||||
tasks => {
|
||||
this.tasks.length = 0;
|
||||
if (!tasks || tasks._embedded === undefined) {
|
||||
|
@ -74,4 +96,8 @@ export class TaskListToolbarComponent implements OnInit {
|
|||
sorting(sort: SortingModel) {
|
||||
this.performSorting.emit(sort);
|
||||
}
|
||||
|
||||
filtering(filterBy: FilterModel) {
|
||||
this.performFilter.emit(filterBy);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
<div class="task-list-full-height">
|
||||
<taskana-tasklist-toolbar (tasksChanged)="loadTasks($event)" (basketChanged)="loadBasketID($event)"
|
||||
(performSorting)="performSorting($event)"></taskana-tasklist-toolbar>
|
||||
(performSorting)="performSorting($event)"
|
||||
(performFilter)="performFilter($event)">
|
||||
</taskana-tasklist-toolbar>
|
||||
<div *ngIf="!requestInProgress">
|
||||
<ul #taskList id="task-list-container" class="list-group">
|
||||
<li class="list-group-item" *ngIf="tasks === undefined || tasks.length === 0" type="text">
|
||||
|
@ -10,10 +12,8 @@
|
|||
type="text" (click)="selectTask(task.taskId)">
|
||||
<div class="row">
|
||||
<dl class="col-xs-10">
|
||||
<dt data-toggle="tooltip" title="{{task.name}}">{{task.name}},
|
||||
<i data-toggle="tooltip" title="{{task.taskId}}">{{task.taskId}} </i>
|
||||
</dt>
|
||||
<dd data-toggle="tooltip" title="{{task.due}}">Due: {{task.due}} </dd>
|
||||
<dt data-toggle="tooltip" title="{{task.name}}">{{task.name}}</dt>
|
||||
<dd data-toggle="tooltip" title="{{task.owner}}">Owner: {{task.owner}} </dd>
|
||||
<dd data-toggle="tooltip" title="{{task.priority}}">Priority: {{task.priority}} </dd>
|
||||
<dd data-toggle="tooltip" title="{{task.state}}">State: {{task.state}} </dd>
|
||||
</dl>
|
||||
|
|
|
@ -5,6 +5,7 @@ import {TaskService} from 'app/workplace/services/task.service';
|
|||
import {Subscription} from 'rxjs/Subscription';
|
||||
import {SortingModel} from 'app/models/sorting';
|
||||
import {Workbasket} from 'app/models/workbasket';
|
||||
import {FilterModel} from 'app/models/filter';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-task-list',
|
||||
|
@ -17,7 +18,16 @@ export class TasklistComponent implements OnInit, OnDestroy {
|
|||
|
||||
currentBasket: Workbasket;
|
||||
selectedId = '';
|
||||
sort: SortingModel = new SortingModel();
|
||||
sort: SortingModel = new SortingModel('priority');
|
||||
filterBy: FilterModel = new FilterModel({
|
||||
name: '',
|
||||
owner: '',
|
||||
priority: '',
|
||||
state: '',
|
||||
classificationKey: '',
|
||||
workbasketId: '',
|
||||
workbasketKey: ''
|
||||
});
|
||||
requestInProgress = false;
|
||||
|
||||
private taskChangeSubscription: Subscription;
|
||||
|
@ -63,13 +73,20 @@ export class TasklistComponent implements OnInit, OnDestroy {
|
|||
this.getTasks();
|
||||
}
|
||||
|
||||
performFilter(filterBy: FilterModel) {
|
||||
this.filterBy = filterBy;
|
||||
this.getTasks();
|
||||
}
|
||||
|
||||
getTasks(): void {
|
||||
this.requestInProgress = true;
|
||||
this.taskService.findTasksWithWorkbasket(this.currentBasket.workbasketId, this.sort.sortBy, this.sort.sortDirection)
|
||||
this.taskService.findTasksWithWorkbasket(this.currentBasket.workbasketId, this.sort.sortBy, this.sort.sortDirection,
|
||||
this.filterBy.filterParams.name, this.filterBy.filterParams.owner, this.filterBy.filterParams.priority,
|
||||
this.filterBy.filterParams.state)
|
||||
.subscribe(tasks => {
|
||||
this.requestInProgress = false;
|
||||
this.tasks = tasks._embedded ? tasks._embedded.tasks : this.tasks;
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
|
|
Loading…
Reference in New Issue