TSK-289 Create select types component and refactor when it is used.

This commit is contained in:
Martin Rojas Miguel Angel 2018-02-21 12:01:31 +01:00 committed by Holger Hagen
parent da53c87a68
commit cdb9f0b44e
19 changed files with 148 additions and 48 deletions

View File

@ -27,6 +27,7 @@ import { WorkbasketInformationComponent } from './workbasket/details/information
import { NoAccessComponent } from './workbasket/noAccess/no-access.component';
import { SpinnerComponent } from './shared/spinner/spinner.component';
import { FilterComponent } from './shared/filter/filter.component';
import { IconTypeComponent } from './shared/type-icon/icon-type.component';
//Shared
import { MasterAndDetailComponent} from './shared/masterAndDetail/master-and-detail.component';
@ -44,7 +45,7 @@ import { HTTP_INTERCEPTORS } from '@angular/common/http';
* Pipes
*/
import { MapValuesPipe } from './pipes/map-values.pipe';
import { RemoveNoneTypePipe } from './pipes/remove-none-type';
const MODULES = [
BrowserModule,
@ -72,7 +73,9 @@ const DECLARATIONS = [
NoAccessComponent,
SpinnerComponent,
FilterComponent,
MapValuesPipe
IconTypeComponent,
MapValuesPipe,
RemoveNoneTypePipe
];
@NgModule({

View File

@ -0,0 +1,16 @@
import {Pipe, PipeTransform} from '@angular/core';
@Pipe({name: 'removeNoneType'})
export class RemoveNoneTypePipe implements PipeTransform {
transform(value: any): Object[] {
let returnArray = [];
value.forEach((entry) => {
if(entry.key !== 'NONE')
returnArray.push({
key: entry.key,
value: entry.value
});
});
return returnArray;
}
}

View File

@ -1,24 +1,16 @@
<div type="text" id="{{target}}" class="list-group-seach collapse">
<div class="row">
<div class="dropdown col-xs-2">
<button class="btn btn-default {{!filter.type? 'glyphicon glyphicon-asterisk blue' : '' }}" type="button" id="dropdownMenufilter" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<svg-icon *ngIf="filter.type" class="small blue" src="./assets/icons/{{(filter.type === 'PERSONAL')? 'user.svg': (filter.type === 'GROUP')? 'users.svg' :''}}"></svg-icon>
<button class="btn btn-default" 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>
<button type="button" (click)="selectType(-1)" placeholder="individual" class="btn btn-default glyphicon glyphicon-asterisk btn-users-list blue" data-toggle="tooltip" title="all">
<li *ngFor ="let type of allTypes | mapValues">
<button type="button" (click)="selectType(type.key)" class="btn btn-default btn-users-list" data-toggle="tooltip" [title]="type.value">
<taskana-icon-type class="vertical-align" [type] ='type.key'></taskana-icon-type>
</button>
</li>
<li>
<button type="button" (click)="selectType(0)" placeholder="individual" class="btn btn-default btn-users-list" data-toggle="tooltip" title="individual">
<svg-icon class="small blue" src="./assets/icons/user.svg"></svg-icon>
</button>
</li>
<li>
<button type="button" (click)="selectType(1)" placeholder="group" data-toggle="tooltip" title="group" class="btn btn-default btn-users-list">
<svg-icon class="small blue" src="./assets/icons/users.svg"></svg-icon>
</button>
</li>
</ul>
</div>
<div class="col-xs-4">
@ -28,7 +20,7 @@
<input type="text" [(ngModel)]= "filter.key" (keyup.enter)="search()" class="form-control" id="wb-display-key-filter" placeholder="Filter key">
</div>
<button (click)="clear()" type="button"
class="btn btn-default glyphicon glyphicon-remove-circle blue pull-right margin-right" data-toggle="tooltip" title="Clear">
class="btn btn-default glyphicon glyphicon-ban-circle blue pull-right margin-right" data-toggle="tooltip" title="Clear">
</button>
</div>
<div class="row">
@ -47,5 +39,5 @@
<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>
</div>

View File

@ -1,4 +1,3 @@
.dropdown-menu-users {
&>li{
margin-bottom: 5px;

View File

@ -3,8 +3,9 @@ import { FormsModule } from '@angular/forms';
import { AngularSvgIconModule } from 'angular-svg-icon';
import { HttpClientModule } from '@angular/common/http';
import { HttpModule } from '@angular/http';
import { IconTypeComponent } from '../type-icon/icon-type.component';
import { FilterComponent, FilterModel } from './filter.component';
import { MapValuesPipe } from '../../pipes/map-values.pipe';
describe('FilterComponent', () => {
let component: FilterComponent,
@ -14,7 +15,7 @@ describe('FilterComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ FilterComponent ],
declarations: [ FilterComponent, IconTypeComponent, MapValuesPipe ],
imports: [AngularSvgIconModule, FormsModule, HttpClientModule, HttpModule ]
})
.compileComponents();

View File

@ -1,4 +1,5 @@
import { Component, Input, OnInit, Output, EventEmitter } from '@angular/core';
import { IconTypeComponent, ICONTYPES } from '../type-icon/icon-type.component'
export class FilterModel {
type:string;
@ -22,8 +23,10 @@ export class FilterModel {
})
export class FilterComponent{
constructor() { }
constructor() {
this.allTypes = IconTypeComponent.allTypes;
}
allTypes: Map<string, string>;
filter: FilterModel = new FilterModel();
@Input()
@ -32,8 +35,8 @@ export class FilterComponent{
@Output()
performFilter = new EventEmitter<FilterModel>();
selectType(type: number){
this.filter.type = type === 0 ? 'PERSONAL': type === 1? 'GROUP': '';
selectType(type: ICONTYPES){
this.filter.type = type;
}
clear(){

View File

@ -0,0 +1,2 @@
<svg-icon *ngIf="type !== 'NONE'" class="{{selected? 'white': 'blue' }} small" src="./assets/icons/{{type === 'PERSONAL'? 'user.svg': type === 'GROUP'? 'users.svg' : type === 'TOPIC'? 'topic.svg' : 'clearance.svg'}}"></svg-icon>
<div *ngIf="type === 'NONE'" class = "glyphicon glyphicon-asterisk blue"></div>

After

Width:  |  Height:  |  Size: 310 B

View File

@ -0,0 +1,28 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AngularSvgIconModule } from 'angular-svg-icon';
import { HttpClientModule } from '@angular/common/http';
import { HttpModule } from '@angular/http';
import { IconTypeComponent } from './icon-type.component';
describe('IconTypeComponent', () => {
let component: IconTypeComponent;
let fixture: ComponentFixture<IconTypeComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports:[AngularSvgIconModule,HttpClientModule, HttpModule],
declarations: [ IconTypeComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(IconTypeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,36 @@
import { Component, OnInit, Input } from '@angular/core';
export enum ICONTYPES {
NONE = 'NONE',
PERSONAL = 'PERSONAL',
GROUP = 'GROUP',
CLEARANCE = 'CLEARANCE',
TOPIC = 'TOPIC'
}
@Component({
selector: 'taskana-icon-type',
templateUrl: './icon-type.component.html',
styleUrls: ['./icon-type.component.scss']
})
export class IconTypeComponent implements OnInit {
public static get allTypes(): Map<string, string> { return new Map([['NONE', 'None'], ['PERSONAL', 'Personal'], ['GROUP', 'Group'], ['CLEARANCE', 'Clearance'], ['TOPIC', 'Topic']])};
constructor() { }
@Input()
type: ICONTYPES = ICONTYPES.PERSONAL;
@Input()
selected: boolean = false;
@Input()
tooltip: boolean = false;
ngOnInit() {
}
}

View File

@ -20,14 +20,16 @@
<label for="wb-type" class="control-label">Type</label>
<div class="dropdown clearfix btn-group">
<button class="btn btn-default" type="button" id="dropdownMenu24" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<svg-icon class="small blue" src="./assets/icons/{{workbasket.type === 'PERSONAL'? 'user.svg': 'users.svg'}}"></svg-icon>
{{workbasket.type === 'PERSONAL'? 'Individual': 'Multiple'}}
<taskana-icon-type class="vertical-align" [type] ='workbasket.type'></taskana-icon-type>
{{allTypes.get(workbasket.type)}}
<span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu" aria-labelledby="dropdownMenu1">
<li>
<a (click)="selectType(0)"> <svg-icon class="small blue" src="./assets/icons/user.svg"></svg-icon> Individual </a>
<a (click)="selectType(1)"> <svg-icon class="small blue" src="./assets/icons/users.svg"></svg-icon> Multiple </a>
<a *ngFor="let type of allTypes | mapValues | removeNoneType" (click)="selectType(type.key)">
<taskana-icon-type class="vertical-align" [type] ='type.key'></taskana-icon-type>
{{type.value}}
</a>
</li>
</ul>
</div>

View File

@ -6,28 +6,29 @@ import { AngularSvgIconModule } from 'angular-svg-icon';
import { HttpClientModule } from '@angular/common/http';
import { HttpModule, JsonpModule } from '@angular/http';
import { Workbasket } from 'app/model/workbasket';
import { ICONTYPES, IconTypeComponent } from '../../../shared/type-icon/icon-type.component';
import { MapValuesPipe } from '../../../pipes/map-values.pipe';
import { RemoveNoneTypePipe } from '../../../pipes/remove-none-type';
describe('InformationComponent', () => {
let component: WorkbasketInformationComponent;
let fixture: ComponentFixture<WorkbasketInformationComponent>;
let debugElement;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ WorkbasketInformationComponent ],
declarations: [ WorkbasketInformationComponent, IconTypeComponent, MapValuesPipe, RemoveNoneTypePipe],
imports:[FormsModule, AngularSvgIconModule, HttpClientModule, HttpModule],
providers:[WorkbasketService]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(WorkbasketInformationComponent);
component = fixture.componentInstance;
debugElement = fixture.debugElement.nativeElement;
});
}));
afterEach(() =>{
document.body.removeChild(debugElement);
@ -49,13 +50,13 @@ describe('InformationComponent', () => {
}));
it('selectType should set workbasket.type to personal with 0 and multiple in other case', () => {
it('selectType should set workbasket.type to personal with 0 and group in other case', () => {
component.workbasket = new Workbasket(null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null);
expect(component.workbasket.type).toEqual(null);
component.selectType(0);
component.selectType(ICONTYPES.PERSONAL);
expect(component.workbasket.type).toEqual('PERSONAL');
component.selectType(1);
expect(component.workbasket.type).toEqual('MULTIPLE');
component.selectType(ICONTYPES.GROUP);
expect(component.workbasket.type).toEqual('GROUP');
});
});

View File

@ -1,6 +1,7 @@
import { Component, OnInit, Input, Output } from '@angular/core';
import { Workbasket } from '../../../model/workbasket';
import { WorkbasketService } from '../../../services/workbasketservice.service';
import { IconTypeComponent, ICONTYPES } from '../../../shared/type-icon/icon-type.component';
@Component({
selector: 'workbasket-information',
@ -11,13 +12,15 @@ export class WorkbasketInformationComponent implements OnInit {
@Input()
workbasket: Workbasket;
constructor(private service: WorkbasketService) { }
allTypes: Map<string, string>;
constructor(private service: WorkbasketService) {
this.allTypes = IconTypeComponent.allTypes;
}
ngOnInit() {
}
selectType(type: number){
this.workbasket.type = type === 0 ? 'PERSONAL': 'MULTIPLE';
selectType(type: ICONTYPES){
this.workbasket.type = type;
}
}

View File

@ -5,6 +5,9 @@ import { WorkbasketInformationComponent } from './information/workbasket-informa
import { Workbasket } from 'app/model/workbasket';
import { Observable } from 'rxjs/Observable';
import { SpinnerComponent } from '../../shared/spinner/spinner.component';
import { ICONTYPES, IconTypeComponent } from '../../shared/type-icon/icon-type.component';
import { MapValuesPipe } from '../../pipes/map-values.pipe';
import { RemoveNoneTypePipe } from '../../pipes/remove-none-type';
import { WorkbasketService } from '../../services/workbasketservice.service';
import { MasterAndDetailService } from '../../services/master-and-detail.service';
@ -26,7 +29,7 @@ describe('WorkbasketDetailsComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports:[RouterTestingModule, FormsModule, AngularSvgIconModule, HttpClientModule, HttpModule],
declarations: [ WorkbasketDetailsComponent, NoAccessComponent, WorkbasketInformationComponent, SpinnerComponent ],
declarations: [ WorkbasketDetailsComponent, NoAccessComponent, WorkbasketInformationComponent, SpinnerComponent, IconTypeComponent, MapValuesPipe, RemoveNoneTypePipe ],
providers:[WorkbasketService, MasterAndDetailService, PermissionService]
})
.compileComponents();

View File

@ -63,7 +63,9 @@
<li class="list-group-item" *ngFor= "let workbasket of workbaskets" [class.active]="workbasket.workbasketId == selectedId" type="text" (click) ="selectWorkbasket(workbasket.workbasketId)" [routerLink]="[ {outlets: { detail: [workbasket.workbasketId] } }]">
<div class="row">
<dl class="col-xs-1">
<dt><svg-icon class="{{workbasket.workbasketId === selectedId? 'white': 'blue' }} small" src="./assets/icons/{{workbasket.type === 'PERSONAL'? 'user.svg': 'users.svg'}}"></svg-icon></dt>
<dt>
<taskana-icon-type class="vertical-align" [type] ="workbasket.type" [selected] = "workbasket.workbasketId === selectedId" ></taskana-icon-type>
</dt>
</dl>
<dl class="col-xs-10">
<dt>{{workbasket.name}} ({{workbasket.key}}) </dt>

View File

@ -10,8 +10,11 @@ import { Router, Routes } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { Observable } from 'rxjs/Observable';
import { SpinnerComponent } from '../../shared/spinner/spinner.component';
import { MapValuesPipe } from '../../pipes/map-values.pipe';
import { FilterModel } from '../../shared/filter/filter.component';
import { IconTypeComponent } from '../../shared/type-icon/icon-type.component';
import { RemoveNoneTypePipe } from '../../pipes/remove-none-type';
import { MapValuesPipe } from '../../pipes/map-values.pipe';
@Component({
selector: 'dummy-detail',
@ -30,7 +33,7 @@ export class FilterComponent {
}
const workbasketSummary: WorkbasketSummary[] = [ new WorkbasketSummary("1", "key1", "NAME1", "description 1", "owner 1", "", "", "PERSONAL", "", "", "", ""),
new WorkbasketSummary("2", "key2", "NAME2", "description 2", "owner 2", "", "", "MULTIPLE", "", "", "", "")
new WorkbasketSummary("2", "key2", "NAME2", "description 2", "owner 2", "", "", "GROUP", "", "", "", "")
];
@ -47,7 +50,7 @@ describe('WorkbasketListComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ WorkbasketListComponent, DummyDetailComponent, MapValuesPipe, SpinnerComponent, FilterComponent],
declarations: [ WorkbasketListComponent, DummyDetailComponent, MapValuesPipe, SpinnerComponent, FilterComponent, RemoveNoneTypePipe, IconTypeComponent],
imports:[
AngularSvgIconModule,
HttpModule,

View File

@ -247,3 +247,7 @@ li > div.row > dl {
taskana-spinner.centered-horizontally > div {
margin-top: calc(50vh - 250px);
}
.vertical-align{
vertical-align: middle;
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M6.873 15.967a8.737 8.737 0 0 1-3.447-1.37c-.655-.445-1.546-1.336-1.99-1.992C.93 11.86.416 10.723.213 9.901c-.238-.966-.257-2.67-.04-3.609A8.135 8.135 0 0 1 6.286.178C7.23-.039 8.933-.02 9.894.217a8.404 8.404 0 0 1 3.781 2.137 8.418 8.418 0 0 1 2.137 3.782c.254 1.022.254 2.743 0 3.765a8.418 8.418 0 0 1-2.137 3.782c-.996.997-2.41 1.8-3.74 2.124-.776.19-2.358.272-3.062.16zm2.86-1.158c2.766-.762 4.74-2.932 5.187-5.702.12-.743.06-2.141-.122-2.81-.746-2.754-2.93-4.742-5.698-5.188-.743-.12-2.14-.06-2.809.122-2.753.746-4.74 2.93-5.187 5.7-.12.742-.06 2.14.122 2.809.72 2.656 2.736 4.57 5.421 5.147.682.147 2.43.102 3.086-.078zm-2.444-2.856v-.883h1.686v1.766H7.29zm.014-2.432c.045-1.035.244-1.373 1.428-2.426.497-.441.957-.908 1.024-1.036.195-.375.104-1.038-.184-1.342-.31-.326-.568-.453-1.054-.517-.88-.117-1.774.419-2.03 1.216-.055.173-.123.34-.15.37-.028.031-.421.016-.874-.033l-.823-.09V5.44c0-.767.824-1.88 1.714-2.318.68-.334 1.61-.465 2.443-.344.938.137 1.476.37 2.024.878.636.589.906 1.14.91 1.859.005.942-.334 1.484-1.643 2.627-.437.38-.851.804-.922.94-.07.137-.147.46-.17.717l-.043.469H7.27z"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M13.327.011H2.68A2.666 2.666 0 0 0 .017 2.674v7.989a2.665 2.665 0 0 0 2.662 2.662h2.386l2.467 2.469a.662.662 0 0 0 .942 0l2.467-2.469h2.386a2.665 2.665 0 0 0 2.662-2.662v-7.99A2.666 2.666 0 0 0 13.327.012zm1.33 10.652c0 .733-.596 1.332-1.331 1.332h-2.66l-.034.001h-.01l-.023.002-.016.002-.016.001-.02.004-.013.001-.02.005c-.003.002-.008.002-.011.003l-.02.005c-.003.002-.008.002-.01.004-.007.001-.014.003-.019.006l-.013.005-.016.006-.015.005-.015.007-.014.006-.013.007-.017.008-.013.007a.143.143 0 0 1-.016.01l-.013.008-.015.01-.013.01-.013.009a.114.114 0 0 0-.016.013l-.01.008-.023.02-.001.001c-.01.008-.018.017-.026.025l-2.189 2.188-2.19-2.19-.026-.024-.002-.002-.023-.02-.01-.006c-.004-.005-.011-.008-.016-.013l-.013-.01-.013-.01-.015-.01-.013-.008a.051.051 0 0 0-.016-.008c-.005-.001-.008-.005-.013-.006-.005-.004-.01-.005-.016-.008l-.013-.007-.015-.006-.015-.007-.013-.005-.016-.006-.013-.005-.018-.007c-.003-.001-.008-.001-.011-.003l-.02-.005c-.003-.002-.008-.002-.011-.003l-.02-.005c-.005-.002-.008-.002-.013-.002l-.02-.003-.016-.002L5.407 12l-.023-.002h-.01l-.034-.002H2.68a1.333 1.333 0 0 1-1.332-1.332V2.675c0-.733.597-1.332 1.332-1.332h10.647c.733 0 1.331.597 1.331 1.332z"/><path d="M11.996 3.34H4.01a.665.665 0 1 0 0 1.331h7.986a.666.666 0 0 0 0-1.33zM4.01 7.335h4.658a.666.666 0 0 0 0-1.33H4.01a.665.665 0 1 0 0 1.33zM10.664 8.666H4.01a.665.665 0 1 0 0 1.33h6.654a.666.666 0 0 0 0-1.33z"/></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB