TSK-736 Reimplement workplace module according to taskana UI

This commit is contained in:
Martin Rojas Miguel Angel 2018-10-31 16:41:58 +01:00 committed by Holger Hagen
parent 9c1fa6dfe2
commit cc675e324b
50 changed files with 1003 additions and 808 deletions

View File

@ -1,14 +1,13 @@
<div class="container-scrollable">
<taskana-spinner [isRunning]="requestInProgress" class="floating" (spinnerIsRunning)="spinnerRunning($event)"></taskana-spinner>
<div id="classification-details" *ngIf="classification && !spinnerIsRunning">
<ul class="nav nav-tabs" role="tablist">
<li *ngIf="showDetail" class="visible-xs visible-sm hidden">
<a (click)="backClicked()">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>Back</a>
</li>
</ul>
<div id="classification" class="panel panel-default classification">
<div class="panel-heading">
<div *ngIf="showDetail" class="pull-left btn-group align-header">
<button (click)="backClicked()" class="btn btn-default no-style blue visible-xs visible-sm hidden">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>Back
</button>
</div>
<div class="pull-right btn-group">
<button type="button" (click)="onSubmit()" class="btn btn-default btn-primary" data-toggle="tooltip" title="Save">
<span class="glyphicon glyphicon-floppy-save" aria-hidden="true"></span>
@ -18,6 +17,7 @@
</button>
<button type="button" (click)="removeClassification()" data-toggle="tooltip" title="Remove" class="btn btn-default remove">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
</button>
</div>
<h4 class="panel-header">{{classification.name}}&nbsp; [{{classification.type}}]
@ -29,24 +29,54 @@
<div class="col-md-6">
<div class="form-group required">
<label for="classification-key" class="control-label">Key</label>
<input type="text" required #key="ngModel" [disabled]="action!== 'CREATE'? true : false" class="form-control" id="classification-key"
placeholder="Key" [(ngModel)]="classification.key" name="classification.key">
<taskana-field-error-display *ngIf="action === 'CREATE'" [displayError]="!isFieldValid('classification.key')" [validationTrigger]="this.toogleValidationMap.get('classification.key')"
errorMessage="* Key is required">
<input type="text" required #key="ngModel" [disabled]="action!== 'CREATE'? true : false" class="form-control"
id="classification-key" placeholder="Key" [(ngModel)]="classification.key" name="classification.key">
<taskana-field-error-display *ngIf="action === 'CREATE'" [displayError]="!isFieldValid('classification.key')"
[validationTrigger]="this.toogleValidationMap.get('classification.key')" errorMessage="* Key is required">
</taskana-field-error-display>
</div>
<div class="form-group required">
<label for="classification-name" class="control-label">Name</label>
<input type="text" required #name="ngModel" class="form-control" id="classification-name" placeholder="Name" [(ngModel)]="classification.name"
name="classification.name">
<input type="text" required #name="ngModel" class="form-control" id="classification-name" placeholder="Name"
[(ngModel)]="classification.name" name="classification.name">
<taskana-field-error-display [displayError]="!isFieldValid('classification.name')" [validationTrigger]="this.toogleValidationMap.get('classification.name')"
errorMessage="* Name is required">
</taskana-field-error-display>
</div>
<div class="form-group">
<div class="row">
<div class="form-group col-xs-6 required">
<label for="classification-category" class="control-label">Category</label>
<div class="input-group">
<div class="input-group-btn">
<button class="btn btn-default vertical-align" type="button" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="true">
<span class="text-top ">
<svg-icon class="blue fa-fw" src="{{getCategoryIcon(classification.category).name}}"
data-toggle="tooltip" [title]="getCategoryIcon(classification.category).text"></svg-icon>
</span>
{{classification.category}}
<span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu " aria-labelledby="dropdownMenu">
<li>
<a *ngFor="let category of categories" (click)="selectCategory(category)">
<span class="text-top">
<svg-icon class="blue fa-fw" src="{{getCategoryIcon(category).name}}" data-toggle="tooltip"
[title]="getCategoryIcon(category).text"></svg-icon>
</span>
{{category}}
</a>
</li>
</ul>
</div>
</div>
</div>
<div class="form-group col-xs-6">
<label for="classification-domain" class="control-label">Domain</label>
<input type="text" disabled #domain="ngModel" class="form-control" id="classification-domain" placeholder="Domain" [(ngModel)]="classification.domain"
name="classification.domain">
<input type="text" disabled #domain="ngModel" class="form-control" id="classification-domain"
placeholder="Domain" [(ngModel)]="classification.domain" name="classification.domain">
<a *ngIf="!masterDomainSelected()" (click)="validChanged()">
<label>
@ -56,28 +86,6 @@
</label>
</a>
</div>
<div class="form-group required">
<label for="classification-category" class="control-label">Category</label>
<div class="dropdown clearfix btn-group">
<button class="btn btn-default" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<span class="text-top">
<svg-icon class="blue fa-fw" src="{{getCategoryIcon(classification.category).name}}" data-toggle="tooltip" [title]="getCategoryIcon(classification.category).text"></svg-icon>
</span>
{{classification.category}}
<span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu" aria-labelledby="dropdownMenu">
<li>
<a *ngFor="let category of categories" (click)="selectCategory(category)">
<span class="text-top">
<svg-icon class="blue fa-fw" src="{{getCategoryIcon(category).name}}" data-toggle="tooltip" [title]="getCategoryIcon(category).text"></svg-icon>
</span>
{{category}}
</a>
</li>
</ul>
</div>
</div>
<div class="form-group">
<label for="classification-priority" class="control-label">Priority</label>
@ -86,8 +94,8 @@
</div>
<div class="form-group">
<label for="classification-service-level" class="control-label">Service Level</label>
<input type="text" class="form-control" id="classification-service-level" placeholder="Service Level" [(ngModel)]="classification.serviceLevel"
name="classification.serviceLevel">
<input type="text" class="form-control" id="classification-service-level" placeholder="Service Level"
[(ngModel)]="classification.serviceLevel" name="classification.serviceLevel">
</div>
<div class="form-group">
<label for="classification-application-entry-point" class="control-label">Application entry point</label>
@ -96,50 +104,50 @@
</div>
<div class="form-group">
<label for="classification-description" class="control-label">Description</label>
<textarea class="form-control" rows="5" id="classification-description" placeholder="Description" [(ngModel)]="classification.description"
name="classification.description"></textarea>
<textarea class="form-control" rows="5" id="classification-description" placeholder="Description"
[(ngModel)]="classification.description" name="classification.description"></textarea>
</div>
</div>
<div class="col-md-6">
<div *ngIf="custom1Field.visible" class="form-group">
<label for="classification-custom-1" class="control-label">{{custom1Field.field}}</label>
<input type="text" class="form-control" id="classification-custom-1" placeholder="{{custom1Field.field}}" [(ngModel)]="classification.custom1"
name="classification.custom1">
<input type="text" class="form-control" id="classification-custom-1" placeholder="{{custom1Field.field}}"
[(ngModel)]="classification.custom1" name="classification.custom1">
</div>
<div *ngIf="custom2Field.visible" class="form-group">
<label for="classification-custom-2" class="control-label">{{custom2Field.field}}</label>
<input type="text" class="form-control" id="classification-custom-2" placeholder="{{custom2Field.field}}" [(ngModel)]="classification.custom2"
name="classification.custom2">
<input type="text" class="form-control" id="classification-custom-2" placeholder="{{custom2Field.field}}"
[(ngModel)]="classification.custom2" name="classification.custom2">
</div>
<div *ngIf="custom3Field.visible" class="form-group">
<label for="classification-custom-3" class="control-label">{{custom3Field.field}}</label>
<input type="text" class="form-control" id="classification-custom-3" placeholder="{{custom3Field.field}}" [(ngModel)]="classification.custom3"
name="classification.custom3">
<input type="text" class="form-control" id="classification-custom-3" placeholder="{{custom3Field.field}}"
[(ngModel)]="classification.custom3" name="classification.custom3">
</div>
<div *ngIf="custom4Field.visible" class="form-group">
<label for="classification-custom-4" class="control-label">{{custom4Field.field}}</label>
<input type="text" class="form-control" id="classification-custom-4" placeholder="{{custom4Field.field}}" [(ngModel)]="classification.custom4"
name="classification.custom4">
<input type="text" class="form-control" id="classification-custom-4" placeholder="{{custom4Field.field}}"
[(ngModel)]="classification.custom4" name="classification.custom4">
</div>
<div *ngIf="custom5Field.visible" class="form-group">
<label for="classification-custom-5" class="control-label">{{custom5Field.field}}</label>
<input type="text" class="form-control" id="classification-custom-5" placeholder="{{custom5Field.field}}" [(ngModel)]="classification.custom5"
name="classification.custom5">
<input type="text" class="form-control" id="classification-custom-5" placeholder="{{custom5Field.field}}"
[(ngModel)]="classification.custom5" name="classification.custom5">
</div>
<div *ngIf="custom6Field.visible" class="form-group">
<label for="classification-custom-6" class="control-label">{{custom6Field.field}}</label>
<input type="text" class="form-control" id="classification-custom-6" placeholder="{{custom6Field.field}}" [(ngModel)]="classification.custom6"
name="classification.custom6">
<input type="text" class="form-control" id="classification-custom-6" placeholder="{{custom6Field.field}}"
[(ngModel)]="classification.custom6" name="classification.custom6">
</div>
<div *ngIf="custom7Field.visible" class="form-group">
<label for="classification-custom-7" class="control-label">{{custom7Field.field}}</label>
<input type="text" class="form-control" id="classification-custom-7" placeholder="{{custom7Field.field}}" [(ngModel)]="classification.custom7"
name="classification.custom7">
<input type="text" class="form-control" id="classification-custom-7" placeholder="{{custom7Field.field}}"
[(ngModel)]="classification.custom7" name="classification.custom7">
</div>
<div *ngIf="custom8Field.visible" class="form-group">
<label for="classification-custom-8" class="control-label">{{custom8Field.field}}</label>
<input type="text" class="form-control" id="classification-custom-8" placeholder="{{custom8Field.field}}" [(ngModel)]="classification.custom8"
name="classification.custom8">
<input type="text" class="form-control" id="classification-custom-8" placeholder="{{custom8Field.field}}"
[(ngModel)]="classification.custom8" name="classification.custom8">
</div>
</div>
</form>

View File

@ -34,7 +34,7 @@
</li>
</ul>
</div>
<div class="col-xs-9">
<div class="col-xs-8">
<input class="filter-input" [ngModel]="inputValue" (ngModelChange)="inputValue = $event" placeholder="Filter classifications">
</div>
<div class="col-xs-12 horizontal-bottom-divider">

View File

@ -10,6 +10,7 @@
.tab-align{
margin-bottom: 0px;
border-bottom: 1px dotted #ddd;
padding: 8px 12px 8px 4px;
&>div{
margin: 6px 0px;
}

View File

@ -55,14 +55,11 @@
</taskana-field-error-display>
</ng-template>
</div>
<div class="form-group ">
<label for="wb-domain" class="control-label">Domain</label>
<input type="text" #domain="ngModel" class="form-control" disabled id="wb-domain" placeholder="Domain"
[(ngModel)]="workbasket.domain" name="workbasket.domain">
</div>
<div class="form-group">
<div class="row">
<div class="form-group col-xs-6">
<label for="wb-type" class="control-label">Type</label>
<div class="dropdown clearfix btn-group">
<div class="input-group">
<div class="input-group-btn">
<button class="btn btn-default" type="button" id="dropdownMenu24" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="true">
<taskana-icon-type class="vertical-align" [type]='workbasket.type'></taskana-icon-type>
@ -78,9 +75,16 @@
</ul>
</div>
</div>
</div>
<div class="form-group col-xs-6">
<label for="wb-domain" class="control-label">Domain</label>
<input type="text" #domain="ngModel" class="form-control" disabled id="wb-domain" placeholder="Domain"
[(ngModel)]="workbasket.domain" name="workbasket.domain">
</div>
</div>
<div class="form-group">
<label for="wb-description" class="control-label">Description</label>
<textarea class="form-control" rows="5" id="wb-description" placeholder="Description" [(ngModel)]="workbasket.description"
<textarea class="form-control" rows="7" id="wb-description" placeholder="Description" [(ngModel)]="workbasket.description"
name="workbasket.description"></textarea>
</div>
</div>

View File

@ -1,6 +1,6 @@
<li id="wb-action-toolbar" class="list-group-item tab-align">
<div class="row">
<div class="col-xs-9">
<div class="col-xs-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>

View File

@ -4,6 +4,7 @@
}
.tab-align{
padding: 8px 12px 8px 4px;
margin-bottom: 0px;
&>div{

View File

@ -1,5 +1,4 @@
<div class="workbasket-list-full-height">
<div class="footer-space-workbasket">
<div class="footer-space-pagination-list">
<div #wbToolbar>
<taskana-workbasket-list-toolbar [workbaskets]="workbaskets" (performFilter)="performFilter($event)"
(performSorting)="performSorting($event)" (importSucessful)="refreshWorkbasketList()"></taskana-workbasket-list-toolbar>
@ -38,5 +37,5 @@
</div>
</ng-template>
</div>
<taskana-pagination [(page)]="workbasketsResource !== undefined ? workbasketsResource.page : workbasketsResource" [type]="type" (changePage)="changePage($event)"></taskana-pagination>
</div>
<taskana-pagination [(page)]="workbasketsResource !== undefined ? workbasketsResource.page : workbasketsResource"
[type]="type" (changePage)="changePage($event)"></taskana-pagination>

View File

@ -28,7 +28,7 @@ li > div.row > dl {
margin-bottom: 0px;
}
li > div.row > dl:first-child {
margin-left: 10px;
margin-left: 15px;
}
.no-space {

View File

@ -3,7 +3,7 @@
<div class="row ">
<router-outlet></router-outlet>
<taskana-general-message-modal *ngIf="modalErrorMessage" [(message)]="modalErrorMessage" [title]="modalTitle" error="true"></taskana-general-message-modal>
<taskana-spinner [isRunning]="requestInProgress" isModal="true"></taskana-spinner>
<taskana-spinner [isRunning]="requestInProgress" isModal=true></taskana-spinner>
<taskana-alert></taskana-alert>
<taskana-remove-confirmation></taskana-remove-confirmation>
</div>

View File

@ -35,8 +35,6 @@ import { TaskanaEngineService } from 'app/services/taskana-engine/taskana-engine
import { RemoveConfirmationService } from './services/remove-confirmation/remove-confirmation.service';
import { FormsValidatorService } from './shared/services/forms/forms-validator.service';
/**
* Components
*/

View File

@ -1,66 +1,74 @@
<div class="list-group-search">
<div class="row">
<div *ngIf="filterTypeIsWorkbasket(); else tasktype">
<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">
<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">
<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 class="row">
<div class="col-xs-8 col-xs-offset-2">
<input type="text" [(ngModel)]="filter.filterParams.description" (keyup.enter)="search()" class="form-control"
id="display-name-description" placeholder="Filter description">
</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 class="row">
<div class="col-xs-8 col-xs-offset-2">
<input type="text" [(ngModel)]="filter.filterParams.owner" (keyup.enter)="search()" class="form-control" id="display-name-owner"
placeholder="Filter owner">
</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>
<ng-template #tasktype>
<div class="row">
<div class="col-xs-2">
<input type="text" [(ngModel)]="filter.filterParams.priority" (keyup.enter)="search()" data-toggle="tooltip" title="priority" class="form-control" id="display-priority-filter">
</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.owner" (keyup.enter)="search()" class="form-control" id="display-owner-filter"
placeholder="Filter owner">
</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">
<div class="col-xs-4 col-xs-offset-2">
<input type="text" [(ngModel)]="filter.filterParams.state" (keyup.enter)="search()" class="form-control" id="display-owner-state"
placeholder="Filter status">
</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>
</ng-template>
</div>

View File

@ -36,7 +36,7 @@ export class FilterComponent implements OnInit {
}
selectType(type: ICONTYPES) {
this.filter.filterParams.type = type;
this.filter.filterParams.type = (type === ICONTYPES.ALL) ? '' : type;
}
clear() {

View File

@ -17,7 +17,7 @@
</div>
<div *ngIf="currentRoute === 'tasks'" class="center-block no-detail">
<h3 class="grey">Select a Task</h3>
<span class="glyphicon glyphicon-object-align-bottom"></span>
<span class="glyphicon glyphicon-object-align-bottom empty-icon"></span>
</div>
</div>
</div>

View File

@ -0,0 +1,9 @@
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'numberToArray' })
export class NumberToArray implements PipeTransform {
transform(index: number): Array<number> {
return Array.from(Array(index), (x, i) => i)
};
}

View File

@ -15,9 +15,11 @@ export class FormsValidatorService {
private accessIdsService: AccessIdsService) {
}
public validateFormInformation(form: NgForm, toogleValidationMap: Map<any, boolean>): Promise<any> {
public async validateFormInformation(form: NgForm, toogleValidationMap: Map<any, boolean>): Promise<any> {
let validSync = true;
if (!form) {
return;
}
const forFieldsPromise = new Promise((resolve, reject) => {
for (const control in form.form.controls) {
if (control.indexOf('owner') === -1 && form.form.controls[control].invalid) {
@ -48,20 +50,19 @@ export class FormsValidatorService {
}
});
return Promise.all([forFieldsPromise, ownerPromise]).then(values => {
const values = await Promise.all([forFieldsPromise, ownerPromise]);
const responseOwner = new ResponseOwner(values[1]);
if (!(values[0] && responseOwner.valid)) {
if (!responseOwner.valid) {
this.alertService.triggerAlert(new AlertModel(AlertType.WARNING, 'The ' + responseOwner.field + ' introduced is not valid.'))
this.alertService.triggerAlert(new AlertModel(AlertType.WARNING, 'The ' + responseOwner.field + ' introduced is not valid.'));
} else {
this.alertService.triggerAlert(new AlertModel(AlertType.WARNING, 'There are some empty fields which are required.'))
this.alertService.triggerAlert(new AlertModel(AlertType.WARNING, 'There are some empty fields which are required.'));
}
}
return values[0] && responseOwner.valid;
});
}
public validateFormAccess(form: FormArray, toogleValidationAccessIdMap: Map<any, boolean>): Promise<boolean> {
public async validateFormAccess(form: FormArray, toogleValidationAccessIdMap: Map<any, boolean>): Promise<boolean> {
const ownerPromise: Array<Promise<boolean>> = new Array<Promise<boolean>>();
for (let i = 0; i < form.length; i++) {
@ -78,17 +79,16 @@ export class FormsValidatorService {
}
let result = true;
return Promise.all(ownerPromise).then(values => {
const values = await Promise.all(ownerPromise);
let responseOwner;
for (let i = 0; i < values.length; i++) {
responseOwner = new ResponseOwner(values[i]);
for (let i_1 = 0; i_1 < values.length; i_1++) {
responseOwner = new ResponseOwner(values[i_1]);
result = result && responseOwner.valid;
}
if (!result) {
this.alertService.triggerAlert(new AlertModel(AlertType.WARNING, 'The ' + responseOwner.field + ' introduced is not valid.'))
this.alertService.triggerAlert(new AlertModel(AlertType.WARNING, 'The ' + responseOwner.field + ' introduced is not valid.'));
}
return result;
});
}
public isFieldValid(ngForm: NgForm, field: string) {

View File

@ -3,10 +3,10 @@ import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { AngularSvgIconModule } from 'angular-svg-icon';
import { AlertModule } from 'ngx-bootstrap';
import { RouterModule } from '@angular/router';
import { TreeModule } from 'angular-tree-component';
import { TypeaheadModule } from 'ngx-bootstrap';
import { AlertModule, TypeaheadModule } from 'ngx-bootstrap';
import { AccordionModule } from 'ngx-bootstrap/accordion';
/**
* Components
@ -33,6 +33,7 @@ import { SelectWorkBasketPipe } from './pipes/selectedWorkbasket/seleted-workbas
import { SpreadNumberPipe } from './pipes/spreadNumber/spread-number';
import { OrderBy } from './pipes/orderBy/orderBy';
import { MapToIterable } from './pipes/mapToIterable/mapToIterable';
import { NumberToArray } from './pipes/numberToArray/numberToArray';
/**
* Services
@ -45,6 +46,7 @@ const MODULES = [
FormsModule,
AlertModule.forRoot(),
TypeaheadModule.forRoot(),
AccordionModule.forRoot(),
AngularSvgIconModule,
HttpClientModule,
RouterModule,
@ -62,6 +64,7 @@ const DECLARATIONS = [
RemoveNoneTypePipe,
SelectWorkBasketPipe,
SpreadNumberPipe,
NumberToArray,
OrderBy,
MapToIterable,
SortComponent,
@ -69,7 +72,7 @@ const DECLARATIONS = [
IconTypeComponent,
RemoveConfirmationComponent,
FieldErrorDisplayComponent,
PaginationComponent
PaginationComponent,
];
@NgModule({

View File

@ -13,8 +13,7 @@
<div class="sk-circle11 sk-child"></div>
<div class="sk-circle12 sk-child"></div>
</div>
<div #spinnerModal class="modal fade" id="spinner-modal" data-backdrop="static" data-keyboard="false" role="dialog">
<div class="modal-dialog">
<div #spinnerModal class="modal" id="spinner-modal" data-backdrop="static" data-keyboard="false" role="dialog">
<div class="modal-dialog {{positionClass? positionClass: 'spinner-centered'}}">
<div class="sk-circle">
<div class="sk-circle1 sk-child"></div>
@ -33,4 +32,3 @@
</div>
</div>
</div>
</div>

View File

@ -59,7 +59,7 @@ export class SpinnerComponent implements OnDestroy {
private runSpinner(value) {
this.currentTimeout = setTimeout(() => {
if (this.isModal) { $(this.modal.nativeElement).modal('toggle'); }
if (this.isModal) { $(this.modal.nativeElement).modal('show'); }
this.isDelayedRunning = value;
this.cancelTimeout();
this.requestTimeout = setTimeout(() => {
@ -73,7 +73,7 @@ export class SpinnerComponent implements OnDestroy {
}
private closeModal() {
if (this.showSpinner) {
$(this.modal.nativeElement).modal('toggle');
$(this.modal.nativeElement).modal('hide');
}
}

View File

@ -12,7 +12,8 @@
</div>
</ng-template>
<div [ngClass]="{'hidden': !dataSource.selected || typing,
'disable': disable}" class="wrapper-text" (click)="setTyping(true)">
'disable': disable}" class="wrapper-text"
(click)="setTyping(true)">
<span>
<label>
{{dataSource.selected?.name}}
@ -29,11 +30,13 @@
</label>
</span>
<div class="input-group">
<input #inputTypeAhead class=" form-control input-text" [ngClass]="{'invalid': dataSource.length == null}" (blur)="typeaheadOnSelect({'item':dataSource.selected})" name="accessItem-{{index}}"
required #accessItemName="ngModel" [(ngModel)]="value" [typeahead]="dataSource" typeaheadOptionField="name" [typeaheadItemTemplate]="customItemTemplate"
(typeaheadOnSelect)="typeaheadOnSelect($event, index)" [typeaheadScrollable]="true" [typeaheadOptionsInScrollableView]="typeaheadOptionsInScrollableView"
[typeaheadMinLength]="typeaheadMinLength" [typeaheadWaitMs]="typeaheadWaitMs" (typeaheadLoading)="changeTypeaheadLoading($event)"
placeholder="{{displayError? placeHolderMessage: ''}}" [@validation]="validationValue" >
<input #inputTypeAhead class="form-control input-text" [ngClass]="{'invalid': !dataSource.length && isRequired}" (blur)="typeaheadOnSelect({'item':dataSource.selected})"
name="accessItem-{{index}}" [required]="isRequired ? 'required' : null" #accessItemName="ngModel" [(ngModel)]="value"
[typeahead]="dataSource" typeaheadOptionField="name" [typeaheadItemTemplate]="customItemTemplate"
(typeaheadOnSelect)="typeaheadOnSelect($event, index)" [typeaheadScrollable]="true"
[typeaheadOptionsInScrollableView]="typeaheadOptionsInScrollableView" [typeaheadMinLength]="typeaheadMinLength"
[typeaheadWaitMs]="typeaheadWaitMs" (typeaheadLoading)="changeTypeaheadLoading($event)" placeholder="{{displayError? placeHolderMessage: ''}}"
[@validation]="validationValue">
<button *ngIf="!typeaheadLoading" type="button" title="search" class="btn rounded blue">
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
</button>

View File

@ -11,8 +11,8 @@
}
&> div{
&> div {
border-bottom: 1px solid $light-grey;
margin-top:3px;
border-bottom: 1px solid $pallete-blue;
margin-top: 2px;
padding-left: 12px;
min-width: 175px;
}
@ -26,7 +26,8 @@
}
.custom-form-control {
height: 50px;
margin-top: -5px;
height: 40px;
& .input-group{
width: 100%;
}
@ -40,7 +41,7 @@
border-radius: 0px;
min-width: 150px;
height: 28px;
border-bottom: 1px solid $light-grey;
border-bottom: 1px solid $pallete-blue;
&:focus{
border-bottom: 1px solid $aquamarine;
}
@ -56,6 +57,9 @@
box-sizing: content-box;
overflow: hidden;
pointer-events: none;
label{
margin-bottom: 1px;
}
}
.form-control:focus {
@ -93,5 +97,5 @@
}
.invalid {
color: $invalid;
border-bottom: 1px solid $invalid;
}

View File

@ -41,6 +41,9 @@ export class TypeAheadComponent implements OnInit, ControlValueAccessor {
@Input()
disable;
@Input()
isRequired = true;
@Output()
onSelect = new EventEmitter<AccessIdDefinition>();

View File

@ -1,5 +1,3 @@
import { Direction } from 'app/models/sorting';
export class TaskanaQueryParameters {
// Sorting
static SORTBY = 'sort-by';
@ -16,7 +14,7 @@ export class TaskanaQueryParameters {
static WORKBASKET_KEY = 'workbasket-key';
static KEYLIKE = 'key-like';
static PRIORITY = 'priority';
static STATE = 'state';
static STATELIKE = 'state-like';
static WORKBASKET_ID = 'workbasket-id';
// Access
@ -54,7 +52,7 @@ export class TaskanaQueryParameters {
workbasketKeyLike: string = undefined,
basketId: string = undefined,
priority: string = undefined,
state: string = undefined,
stateLike: string = undefined,
): string {
let query = '?';
query += sortBy ? `${this.SORTBY}=${sortBy}&` : '';
@ -66,7 +64,7 @@ export class TaskanaQueryParameters {
query += ownerLike ? `${this.OWNERLIKE}=${ownerLike}&` : '';
query += basketId ? `${this.WORKBASKET_ID}=${basketId}&` : '';
query += priority ? `${this.PRIORITY}=${priority}&` : '';
query += state ? `${this.STATE}=${state}&` : '';
query += stateLike ? `${this.STATELIKE}=${stateLike}&` : '';
query += type ? `${this.TYPE}=${type}&` : '';
query += key ? `${this.KEY}=${key}&` : '';
query += keyLike ? `${this.KEYLIKE}=${keyLike}&` : '';

View File

@ -5,6 +5,7 @@ export class TaskanaDate {
const dateFormat = 'yyyy-MM-ddTHH:mm:ss.sss';
const dateLocale = 'en-US';
const datePipe = new DatePipe(dateLocale);
return datePipe.transform(Date.now(), dateFormat) + 'Z';
}
@ -14,4 +15,16 @@ export class TaskanaDate {
const datePipe = new DatePipe(dateLocale);
return datePipe.transform(date, dateFormat);
}
public static getDateToDisplay(date: string): string {
const dateFormat = 'yyyy-MM-dd HH:mm:ss';
const dateLocale = 'en-US';
const datePipe = new DatePipe(dateLocale);
return datePipe.transform(date, dateFormat);
}
public static convertToBrowserTimeZone(date: Date): string {
return date.toLocaleString('en-US', { timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone })
}
}

View File

@ -53,21 +53,21 @@ export class TaskService {
* @param {string} basketId the id of workbasket
* @param {string} sortBy name of field, that the tasks should be sorted by, default is priority
* @param {string} sortDirection ASC or DESC
* @param {string} name the name of the task
* @param {string} owner the owner of the task
* @param {string} nameLike the name of the task
* @param {string} ownerLike the owner of the task
* @param {string} priority the priority of the task
* @param {string} state the state of the task
*/
findTasksWithWorkbasket(basketId: string,
sortBy = 'priority',
sortDirection: string = Direction.ASC,
name: string,
owner: string,
nameLike: string,
ownerLike: string,
priority: string,
state: string,
allPages: boolean = false): Observable<TaskResource> {
const url = `${this.url}${TaskanaQueryParameters.getQueryParameters(
sortBy, sortDirection, name, undefined, undefined, owner, undefined, undefined, undefined, undefined, undefined,
sortBy, sortDirection, undefined, nameLike, undefined, undefined, ownerLike, undefined, undefined, undefined, undefined,
!allPages ? TaskanaQueryParameters.page : undefined, !allPages ? TaskanaQueryParameters.pageSize : undefined,
undefined, undefined, undefined, undefined, basketId, priority, state)}`;
return this.httpClient.get<TaskResource>(url);

View File

@ -1,18 +1,16 @@
<taskana-spinner [isRunning]="requestInProgress"></taskana-spinner>
<div class="panel panel-default">
<div class="panel-heading">
<div class="pull-right">
<button type="button" (click)="navigateBack()" class="btn btn-default"><span title="Cancel and return to task detail"
class="glyphicon glyphicon-arrow-left text-muted"></span>
<div class="pull-left btn-group align-header">
<button (click)="navigateBack()" class="btn btn-default no-style blue " title="Cancel and return to task detail">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>Back
</button>
</div>
<div class="pull-right">
<div class="dropdown" style="display: inline">
<button type="button" data-toggle="dropdown" aria-expanded="true" class="btn btn-default dropdown-toggle">
<span
title="Transfer task to another workbasket"
class="glyphicon glyphicon-transfer text-muted"></span>
<span title="Transfer task to another workbasket" class="glyphicon glyphicon-transfer text-muted"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right">
<li *ngFor="let workbasket of workbaskets">
<a class="dropdown-item" (click)="transferTask(workbasket)">
@ -21,42 +19,42 @@
</li>
</ul>
</div>
<button type="button" (click)="completeTask()" class="btn btn-default"><span
title="Complete task and return to task list"
<button type="button" (click)="completeTask()" class="btn btn-default"><span title="Complete task and return to task list"
class="glyphicon glyphicon-ok blue text-success"></span>
</button>
</div>
<div class="panel-header"><h4><b>{{task?.name}}</b></h4></div>
<div class="panel-header">
<h4><b>{{task?.name}}</b></h4>
</div>
</div>
<div class="panel-body" *ngIf="task">
<div class="row">
<form #TaskForm="ngForm">
<div class="col-md-6">
<div class="form-group">
<label for="task-description" class="control-label">Description</label>
<textarea class="form-control" disabled rows="5" id="task-description" placeholder="Description"
[(ngModel)]="task.description"
name="task.description"></textarea>
[(ngModel)]="task.description" name="task.description"></textarea>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="task-note" class="control-label">Note</label>
<input type="text" disabled class="form-control" id="task-note" placeholder="Task has no Note"
[(ngModel)]="task.note"
<input type="text" disabled 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-due" class="control-label">Due Date</label>
<input type="text" disabled class="form-control" id="task-due" placeholder="No deadline set"
[(ngModel)]="task.due"
<input type="text" disabled class="form-control" id="task-due" placeholder="No deadline set" [(ngModel)]="task.due"
name="task.due">
</div>
</div>
</form>
</div>
<div class="row">
<iframe class="col-xs-12" [src]="link"></iframe>
</div>
<iframe [src]="link"></iframe>
</div>
</div>

View File

@ -1,9 +1,4 @@
iframe {
position: absolute;
margin: 0;
padding: 0;
height: 600px;
width: 98%;
overflow: auto;
height: calc(100vh - 290px);
}

View File

@ -0,0 +1,45 @@
<ng-container *ngIf="task">
<div class="col-md-6">
<div *ngIf="task.taskId" class="form-group">
<label for="task-modified" class="control-label">Modification date</label>
<input type="text" disabled class="form-control" id="task-modified" placeholder="Modified" [(ngModel)]="task.modified"
name="task.modified">
</div>
<div *ngIf="task.taskId" class="form-group">
<label for="task-completed" class="control-label">Completion date</label>
<input type="text" disabled class="form-control" id="task-completed" placeholder="Complete date" [(ngModel)]="task.completed"
name="task.completed">
</div>
<div *ngIf="task.taskId" class="form-group">
<label for="task-state" class="control-label">State</label>
<input type="text" disabled class="form-control" id="task-state" placeholder="State" [(ngModel)]="task.state"
name="task.state">
</div>
<div *ngIf="task.taskId" class="form-group">
<label for="task-read" class="control-label">Task read</label>
<input type="text" disabled class="form-control" id="task-read" placeholder="Read" [(ngModel)]="task.read" name="task.read">
</div>
</div>
<div class="col-md-6">
<div *ngIf="task.taskId" class="form-group">
<label for="task-claimed" class="control-label">Claim date</label>
<input type="text" disabled class="form-control" id="task-claimed" placeholder="Claimed date" [(ngModel)]="task.claimed"
name="task.claimed">
</div>
<div *ngIf="task.taskId" class="form-group">
<label for="task-planned" class="control-label">Planned date</label>
<input type="text" disabled class="form-control" id="task-planned" placeholder="Planned date" [(ngModel)]="task.planned"
name="task.planned">
</div>
<div *ngIf="task.taskId" class="form-group">
<label for="task-created" class="control-label">Creation date</label>
<input type="text" disabled class="form-control" id="task-created" placeholder="Created" [(ngModel)]="task.created"
name="task.created">
</div>
<div *ngIf="task.taskId" class="form-group">
<label for="task-transferred" class="control-label">Transferred</label>
<input type="text" disabled class="form-control" id="task-transferred" placeholder="Transferred" [(ngModel)]="task.transferred"
name="task.transferred">
</div>
</div>
</ng-container>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { GeneralFieldsExtensionComponent } from './general-fields-extension.component';
xdescribe('GeneralFieldsExtensionComponent', () => {
let component: GeneralFieldsExtensionComponent;
let fixture: ComponentFixture<GeneralFieldsExtensionComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ GeneralFieldsExtensionComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(GeneralFieldsExtensionComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,19 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { Task } from 'app/workplace/models/task';
@Component({
selector: 'taskana-general-fields-extension',
templateUrl: './general-fields-extension.component.html',
styleUrls: ['./general-fields-extension.component.scss']
})
export class GeneralFieldsExtensionComponent implements OnInit {
@Input() task: Task;
@Output() taskChange: EventEmitter<Task> = new EventEmitter<Task>();
constructor() { }
ngOnInit() {
}
}

View File

@ -1,111 +1,70 @@
<ng-container *ngIf="task && !requestInProgress">
<div class="col-md-12">
<div class="form-group">
<label for="task-description" class="control-label">Description</label>
<textarea class="form-control" id="task-description"
placeholder="Task has no description"
[(ngModel)]="task.description"
name="task.description"></textarea>
<form #TaskForm="ngForm">
<div class="col-md-6">
<div class="row">
<div class="form-group col-xs-6 required">
<label for="task-name" class="control-label">Name</label>
<input type="text" class="form-control" id="task-name" placeholder="Name" [(ngModel)]="task.name" name="task.name">
<taskana-field-error-display [displayError]="!isFieldValid('task.name')" [validationTrigger]="this.toogleValidationMap.get('task.name')"
errorMessage="* Name is required">
</taskana-field-error-display>
</div>
<div class="form-group col-xs-6 required">
<label for="task.primaryObjRef.company" class="control-label">Company</label>
<input type="text" class="form-control" id="task.primaryObjRef.company" required placeholder="Company description"
[(ngModel)]="task.primaryObjRef.company" name="task.primaryObjRef.company">
<taskana-field-error-display [displayError]="!isFieldValid('task.primaryObjRef.company')" [validationTrigger]="this.toogleValidationMap.get('task.primaryObjRef.company')"
errorMessage="* Company is required">
</taskana-field-error-display>
</div>
<div class="col-md-6">
<div class="form-group required">
<label for="task-objectRef-company" class="control-label">Reference Company</label>
<input type="text" class="form-control" id="task-objectRef-company" required
placeholder="Company description not provided"
[(ngModel)]="task.primaryObjRef.company"
name="task-objectRef-company">
</div>
<div class="form-group required">
<label for="task-objectRef-system" class="control-label">Reference System</label>
<input type="text" class="form-control" id="task-objectRef-system" required
placeholder="System description not provided"
[(ngModel)]="task.primaryObjRef.system"
name="task-objectRef-system">
<div class="row">
<div class="form-group col-xs-6 required">
<label for="task.primaryObjRef.system" class="control-label">System</label>
<input type="text" class="form-control" id="task.primaryObjRef.system" required placeholder="System description"
[(ngModel)]="task.primaryObjRef.system" name="task.primaryObjRef.system">
<taskana-field-error-display [displayError]="!isFieldValid('task.primaryObjRef.system')" [validationTrigger]="this.toogleValidationMap.get('task.primaryObjRef.system')"
errorMessage="* System is required">
</taskana-field-error-display>
</div>
<div class="form-group required">
<label for="task-objectRef-system-instance" class="control-label">Reference System Instance</label>
<input type="text" class="form-control" id="task-objectRef-system-instance" required
placeholder="System Instance description not provided"
[(ngModel)]="task.primaryObjRef.systemInstance"
name="task-objectRef-system-instance">
</div>
<div class="form-group">
<label for="task-owner" class="control-label">Owner</label>
<input type="text" class="form-control" id="task-owner"
placeholder="Task has no 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="Task has no priority"
[(ngModel)]="task.priority"
name="task.priority">
</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 *ngIf="task.taskId" class="form-group">
<label for="task-modified" class="control-label">Modification Date</label>
<input type="text" disabled class="form-control" id="task-modified"
placeholder="Task has not been modified"
[(ngModel)]="task.modified"
name="task.modified">
</div>
<div *ngIf="task.taskId" class="form-group">
<label for="task-completed" class="control-label">Completion Date</label>
<input type="text" disabled class="form-control" id="task-completed"
placeholder="Task has not been completed"
[(ngModel)]="task.completed"
name="task.completed">
</div>
<div *ngIf="task.taskId" 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 *ngIf="task.taskId" class="form-group">
<label for="task-read" class="control-label">Task Read?</label>
<input type="text" disabled class="form-control" id="task-read"
placeholder="Task not been read"
[(ngModel)]="task.read"
name="task.read">
<div class="form-group col-xs-6 required">
<label for="task.primaryObjRef.systemInstance" class="control-label">System instance</label>
<input type="text" class="form-control" id="task.primaryObjRef.systemInstance" required placeholder="System Instance description"
[(ngModel)]="task.primaryObjRef.systemInstance" name="task.primaryObjRef.systemInstance">
<taskana-field-error-display [displayError]="!isFieldValid('task.primaryObjRef.systemInstance')"
[validationTrigger]="this.toogleValidationMap.get('task.primaryObjRef.systemInstance')" errorMessage="* System instance is required">
</taskana-field-error-display>
</div>
</div>
<div class="col-md-6">
<div class="form-group required">
<label for="task-objectRef-type" class="control-label">Reference Type</label>
<input type="text" class="form-control" id="task-objectRef-type" required
placeholder="Reference Type is not provided"
[(ngModel)]="task.primaryObjRef.type"
name="task-objectRef-type">
<div class="row">
<div class="form-group col-xs-6 required">
<label for="task.primaryObjRef.type" class="control-label">Reference type</label>
<input type="text" class="form-control" id="task.primaryObjRef.type" required placeholder="Reference type"
[(ngModel)]="task.primaryObjRef.type" name="task.primaryObjRef.type">
<taskana-field-error-display [displayError]="!isFieldValid('task.primaryObjRef.type')" [validationTrigger]="this.toogleValidationMap.get('task.primaryObjRef.type')"
errorMessage="* Reference type is required">
</taskana-field-error-display>
</div>
<div class="form-group required">
<label for="task-objectRef-value" class="control-label">Reference Value</label>
<input type="text" class="form-control" id="task-objectRef-value" required
placeholder="Reference Value is not provided"
[(ngModel)]="task.primaryObjRef.value"
name="task-objectRef-value">
<div class="form-group col-xs-6 required">
<label for="task.primaryObjRef.value" class="control-label">Reference value</label>
<input type="text" class="form-control" id="task.primaryObjRef.value" required placeholder="Reference value"
[(ngModel)]="task.primaryObjRef.value" name="task.primaryObjRef.value">
<taskana-field-error-display [displayError]="!isFieldValid('task.primaryObjRef.value')" [validationTrigger]="this.toogleValidationMap.get('task.primaryObjRef.value')"
errorMessage="* Reference value is required">
</taskana-field-error-display>
</div>
<div class="form-group required">
<div class="dropdown clearfix btn-group">
<label for="classificationDropdownMenu" class="control-label">Classification</label><br>
<button class="btn btn-default" type="button" id="classificationDropdownMenu" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="true">
{{task.classificationSummaryResource ? selectedClassification.name :
'Task does not belong to a Classification'}}
</div>
<div class="row">
<div class="form-group col-xs-6 required">
<label for="wb-type" class="control-label">Classification</label>
<div class="input-group" dropdown>
<button class="btn btn-default" type="button" dropdownToggle id="task.classificationSummaryResource"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="true" name="">
{{task.classificationSummaryResource?.name }}
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu">
<ul class="dropdown-menu" *dropdownMenu>
<li>
<a *ngFor="let classification of classifications" (click)="selectClassification(classification)">
{{classification.name}}
@ -114,54 +73,45 @@
</ul>
</div>
</div>
<div class="form-group col-xs-6">
<label for="task-priority" disabled class="control-label">Priority</label>
<input type="text" class="form-control" id="task-priority" placeholder="Priority" [(ngModel)]="task.priority"
name="task.priority">
</div>
</div>
<div class="row">
<div class="form-group col-xs-12">
<div class="form-group">
<label for="task-parent-business-p-id" class="control-label">Parent Business Process ID</label>
<input type="text" class="form-control" id="task-parent-business-p-id"
placeholder="Task has no Parent Business Process ID"
[(ngModel)]="task.parentBusinessProcessId"
name="task.parentBusinessProcessId">
<label for="task-note" class="control-label">Note</label>
<textarea class="form-control" rows="2" id="task-note" placeholder="Note" [(ngModel)]="task.note" name="task.note"></textarea>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label for="task-due" class="control-label">Due date</label>
<input type="text" class="form-control" id="task-due" placeholder="Due date" [(ngModel)]="task.due" name="task.due">
</div>
<div class="input-group form-group col-xs-12">
<label for="wb-owner" class="control-label ">Owner</label>
<taskana-type-ahead *ngIf="ownerField?.lookupField else ownerInput" #owner="ngModel" name="task.owner"
[(ngModel)]="task.owner" width="100%" [isRequired]="false"></taskana-type-ahead>
<ng-template #ownerInput>
<input type="text" #task.owner="ngModel" class="form-control" id="ts-owner" placeholder="Owner" [(ngModel)]="task.owner"
name="task.owner">
</ng-template>
</div>
<div class="form-group">
<label for="task-business-p-id" class="control-label">Business Process ID</label>
<input type="text" class="form-control" id="task-business-p-id"
placeholder="Task has no Business Process ID"
[(ngModel)]="task.businessProcessId"
<label for="task-parent-business-p-id" class="control-label">Parent business process id</label>
<input type="text" class="form-control" id="task-parent-business-p-id" placeholder="Parent business process iD"
[(ngModel)]="task.parentBusinessProcessId" name="task.parentBusinessProcessId">
</div>
<div class="form-group">
<label for="task-business-p-id" class="control-label">Business process iD</label>
<input type="text" class="form-control" id="task-business-p-id" placeholder="Business process id" [(ngModel)]="task.businessProcessId"
name="task.businessProcessId">
</div>
<div class="form-group">
<label for="task-due" class="control-label">Due Date</label>
<input type="text" class="form-control" id="task-due"
placeholder="Task has no deadline"
[(ngModel)]="task.due"
name="task.due">
</div>
<div *ngIf="task.taskId" class="form-group">
<label for="task-claimed" class="control-label">Claim Date</label>
<input type="text" disabled class="form-control" id="task-claimed"
placeholder="Task has not been claimed"
[(ngModel)]="task.claimed"
name="task.claimed">
</div>
<div *ngIf="task.taskId" class="form-group">
<label for="task-planned" class="control-label">Planned Date</label>
<input type="text" disabled class="form-control" id="task-planned"
placeholder="Task has no planned date set"
[(ngModel)]="task.planned"
name="task.planned">
</div>
<div *ngIf="task.taskId" class="form-group">
<label for="task-created" class="control-label">Creation Date</label>
<input type="text" disabled class="form-control" id="task-created"
placeholder="Task has not been created"
[(ngModel)]="task.created"
name="task.created">
</div>
<div *ngIf="task.taskId" class="form-group">
<label for="task-transferred" class="control-label">Task Transferred?</label>
<input type="text" disabled class="form-control" id="task-transferred"
placeholder="Task not been transferred"
[(ngModel)]="task.transferred"
name="task.transferred">
</div>
</div>
</form>
</ng-container>

View File

@ -1,25 +1,50 @@
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import { Component, EventEmitter, Input, OnInit, Output, ViewChild, SimpleChanges, OnChanges } from '@angular/core';
import { Task } from 'app/workplace/models/task';
import { Classification } from '../../../models/classification';
import { ClassificationsService } from '../../../services/classifications/classifications.service';
import { CustomFieldsService } from 'app/services/custom-fields/custom-fields.service';
import { FormsValidatorService } from 'app/shared/services/forms/forms-validator.service';
import { NgForm } from '@angular/forms';
@Component({
selector: 'taskana-task-details-general-fields',
templateUrl: './general-fields.component.html',
styleUrls: ['./general-fields.component.scss']
})
export class TaskdetailsGeneralFieldsComponent implements OnInit {
export class TaskdetailsGeneralFieldsComponent implements OnInit, OnChanges {
@Input()
task: Task;
@Output() taskChange: EventEmitter<Task> = new EventEmitter<Task>();
@Input()
saveToggleTriggered: boolean;
@Output() formValid: EventEmitter<boolean> = new EventEmitter<boolean>();
@Output() classificationsReceived: EventEmitter<Classification[]> = new EventEmitter<Classification[]>();
@ViewChild('TaskForm')
taskForm: NgForm;
toogleValidationMap = new Map<string, boolean>();
requestInProgress = false;
selectedClassification: Classification = new Classification();
classifications: Classification[] = undefined;
constructor(private classificationService: ClassificationsService) {
ownerField = this.customFieldsService.getCustomField(
'Owner',
'tasks.information.owner'
);
constructor(
private classificationService: ClassificationsService,
private customFieldsService: CustomFieldsService,
private formsValidatorService: FormsValidatorService) {
}
ngOnChanges(changes: SimpleChanges): void {
if (changes.saveToggleTriggered && changes.saveToggleTriggered.currentValue !== changes.saveToggleTriggered.previousValue) {
this.validate();
}
}
ngOnInit() {
@ -27,18 +52,28 @@ export class TaskdetailsGeneralFieldsComponent implements OnInit {
this.classificationService.getClassifications().subscribe(classificationList => {
this.requestInProgress = false;
this.classifications = classificationList;
if (classificationList.length > 0) { this.task.classificationSummaryResource = classificationList[0]; }
this.classificationsReceived.emit(this.classifications);
});
}
@Input()
set _task(task: Task) {
this.task = task;
this.selectedClassification = task.classificationSummaryResource;
}
selectClassification(classification: Classification) {
this.selectedClassification = classification;
this.task.classificationSummaryResource = classification;
}
validate() {
this.formsValidatorService.formSubmitAttempt = true;
this.formsValidatorService
.validateFormInformation(this.taskForm, this.toogleValidationMap)
.then(value => {
if (value) {
this.formValid.emit(true);
}
});
}
isFieldValid(field: string): boolean {
return this.formsValidatorService.isFieldValid(this.taskForm, field);
}
}

View File

@ -1,50 +1,25 @@
<taskana-spinner [isRunning]="requestInProgress"></taskana-spinner>
<ul class="nav nav-tabs" role="tablist" *ngIf="task && !requestInProgress">
<li class="visible-xs visible-sm hidden">
<a (click)="backClicked()">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>Back</a>
</li>
<li role="presentation" (click)="selectTab('general')" [ngClass]="{'active':tabSelected === 'general'}">
<a role="tab" aria-expanded="true">
General Fields
</a>
</li>
<li role="presentation" (click)="selectTab('custom')" [ngClass]="{'active':tabSelected === 'custom'}">
<a role="tab" aria-expanded="true">
Custom Fields
</a>
</li>
<li role="presentation" (click)="selectTab('custom-attributes')"
[ngClass]="{'active':tabSelected === 'custom-attributes'}">
<a role="tab" aria-expanded="true">
Custom Attributes
</a>
</li>
<li role="presentation" (click)="selectTab('callback-info')"
[ngClass]="{'active':tabSelected === 'callback-info'}">
<a role="tab" aria-expanded="true">
Callback Information
</a>
</li>
</ul>
<div class="panel panel-default" *ngIf="task && !requestInProgress">
<div class="panel-heading">
<div *ngIf="showDetail" class="pull-left btn-group align-header">
<button (click)="backClicked()" class="btn btn-default no-style blue visible-xs visible-sm hidden">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>Back
</button>
</div>
<div class="pull-right btn-group">
<button type="button" (click)="onSave()" class="btn btn-default btn-primary" data-toggle="tooltip"
title="Save">
<button type="button" (click)="toggleFormValidation = !toggleFormValidation" class="btn btn-default btn-primary"
data-toggle="tooltip" title="Save">
<span class="glyphicon glyphicon-floppy-save" aria-hidden="true"></span>
</button>
<ng-container *ngIf="currentId != 'new-task'">
<button type="button" title="Open task to work on it" class="btn btn-default" aria-label="Left Align"
[disabled]="workOnTaskDisabled()" (click)="openTask()">
<span class="glyphicon glyphicon-new-window" aria-hidden="true"></span>
<span class="glyphicon glyphicon-new-window blue" aria-hidden="true"></span>
</button>
<button type="button" (click)="resetTask()" class="btn btn-default" data-toggle="tooltip" title="Undo Changes">
<span class="glyphicon glyphicon-repeat blue" aria-hidden="true"></span>
</button>
<button type="button" title="Delete Task" class="btn btn-default remove"
(click)="deleteTask()">
<button type="button" title="Delete Task" class="btn btn-default remove" (click)="deleteTask()">
<span class="glyphicon glyphicon-remove"></span>
</button>
</ng-container>
@ -53,25 +28,53 @@
<span *ngIf="!task.taskId" class="badge warning"> {{'Creating Task'}}</span>
</h4>
</div>
<div class="panel-body">
<form #TaskForm="ngForm">
<div class="tab-content">
<div role="tabpanel" class="tab-pane" [ngClass]="{'active':tabSelected === 'general'}">
<taskana-task-details-general-fields [_task]="task"></taskana-task-details-general-fields>
</div>
<div role="tabpanel" class="tab-pane" [ngClass]="{'active':tabSelected === 'custom'}">
<accordion *ngIf="task && !requestInProgress">
<accordion-group panelClass="customClass" isOpen="true" (isOpenChange)="accordion1State = $event" >
<button class="btn btn-block clearfix" accordion-heading>
<div class="pull-left float-left">1 - Information</div>
<span class="float-right pull-right glyphicon blue" [ngClass]="{
'glyphicon-chevron-up': !accordion1State,
'glyphicon-chevron-down': accordion1State}"></span>
</button>
<taskana-task-details-general-fields [task]="task" [saveToggleTriggered]="toggleFormValidation" (formValid)="onSubmit()"></taskana-task-details-general-fields>
</accordion-group>
<accordion-group panelClass="customClass" (isOpenChange)="accordion2State = $event">
<button class="btn btn-block clearfix" accordion-heading>
<div class="pull-left float-left">2 - Status details</div>
<span class="float-right pull-right glyphicon blue" [ngClass]="{
'glyphicon-chevron-up': !accordion2State,
'glyphicon-chevron-down': accordion2State}"></span>
</button>
<taskana-general-fields-extension [task]="task"></taskana-general-fields-extension>
</accordion-group>
<accordion-group panelClass="customClass" (isOpenChange)="accordion3State = $event">
<button class="btn btn-block clearfix" accordion-heading>
<div class="pull-left float-left">3 - Custom fields</div>
<span class="float-right pull-right glyphicon blue" [ngClass]="{
'glyphicon-chevron-up': !accordion3State,
'glyphicon-chevron-down': accordion3State}"></span>
</button>
<taskana-task-details-custom-fields [task]="task"></taskana-task-details-custom-fields>
</div>
<div role="tabpanel" class="tab-pane" [ngClass]="{'active':tabSelected === 'custom-attributes'}">
</accordion-group>
<accordion-group panelClass="customClass" (isOpenChange)="accordion4State = $event">
<button class="btn btn-block clearfix" accordion-heading>
<div class="pull-left float-left">4 - Custom attributes</div>
<span class="float-right pull-right glyphicon blue" [ngClass]="{
'glyphicon-chevron-up': !accordion4State,
'glyphicon-chevron-down': accordion4State}"></span>
</button>
<taskana-task-details-attributes [attributes]="task.customAttributes"></taskana-task-details-attributes>
</div>
<div role="tabpanel" class="tab-pane" [ngClass]="{'active':tabSelected === 'callback-info'}">
<taskana-task-details-attributes [attributes]="task.callbackInfo"
[callbackInfo]="true"></taskana-task-details-attributes>
</div>
</div>
</form>
</accordion-group>
<accordion-group panelClass="customClass" (isOpenChange)="accordion5State = $event">
<button class="btn btn-block clearfix" accordion-heading>
<div class="pull-left float-left">5 - Callback information</div>
<span class="float-right pull-right glyphicon blue" [ngClass]="{
'glyphicon-chevron-up': !accordion5State,
'glyphicon-chevron-down': accordion5State}"></span>
</button>
<taskana-task-details-attributes [attributes]="task.callbackInfo" [callbackInfo]="true"></taskana-task-details-attributes>
</accordion-group>
</accordion>
</div>
</div>

View File

@ -1,3 +1,29 @@
.panel > .panel-body {
max-height: calc(100vh - 150px);
@import './src/assets/_colors';
::ng-deep .btn-block {
background-color: whitesmoke;
font-size: 16px;
font-weight: 700;
}
::ng-deep .panel-group .panel-heading + .panel-collapse > .panel-body, .panel-group .panel-heading + .panel-collapse > .list-group {
border: none;
}
::ng-deep .collapse {
-webkit-transition: max-height 0.5s ease;
-moz-transition: max-height 0.5s ease;
-o-transition: max-height 0.5s ease;
-ms-transition: max-height 0.5s ease;
transition: max-height 0.5s ease;
display: block!important;
overflow: hidden!important;
visibility: visible!important;
max-height: 0;
&.in {
max-height: 2000px;
overflow: visible!important;
}
}

View File

@ -15,6 +15,7 @@ import {TaskanaDate} from 'app/shared/util/taskana.date';
import { ObjectReference } from 'app/workplace/models/object-reference';
import { Workbasket } from 'app/models/workbasket';
import { WorkplaceService } from 'app/workplace/services/workplace.service';
import { MasterAndDetailService } from 'app/services/masterAndDetail/master-and-detail.service';
@Component({
selector: 'taskana-task-details',
@ -28,9 +29,11 @@ export class TaskdetailsComponent implements OnInit, OnDestroy {
tabSelected = 'general';
currentWorkbasket: Workbasket = undefined;
currentId: string = undefined;
showDetail = false;
private routeSubscription: Subscription;
private workbasketSubscription: Subscription;
private masterAndDetailSubscription: Subscription;
constructor(private route: ActivatedRoute,
private taskService: TaskService,
@ -39,7 +42,8 @@ export class TaskdetailsComponent implements OnInit, OnDestroy {
private removeConfirmationService: RemoveConfirmationService,
private requestInProgressService: RequestInProgressService,
private alertService: AlertService,
private errorModalService: ErrorModalService) {
private errorModalService: ErrorModalService,
private masterAndDetailService: MasterAndDetailService) {
}
ngOnInit() {
@ -55,6 +59,9 @@ export class TaskdetailsComponent implements OnInit, OnDestroy {
}
this.getTask();
});
this.masterAndDetailSubscription = this.masterAndDetailService.getShowDetail().subscribe(showDetail => {
this.showDetail = showDetail;
});
}
resetTask(): void {
@ -83,40 +90,10 @@ export class TaskdetailsComponent implements OnInit, OnDestroy {
}
}
onSave() {
this.requestInProgressService.setRequestInProgress(true);
this.currentId === 'new-task' ? this.createTask() : this.updateTask();
onSubmit() {
this.onSave();
}
updateTask() {
this.taskService.updateTask(this.task).subscribe(task => {
this.requestInProgressService.setRequestInProgress(false);
this.task = task;
this.cloneTask();
this.taskService.publishUpdatedTask(task);
this.alertService.triggerAlert(new AlertModel(AlertType.SUCCESS, 'Update successful!'))
}, err => {
this.alertService.triggerAlert(new AlertModel(AlertType.DANGER, 'Update not successful!'))
});
}
createTask() {
this.addDateToTask();
this.taskService.createTask(this.task).subscribe(task => {
this.requestInProgressService.setRequestInProgress(false);
this.alertService.triggerAlert(new AlertModel(AlertType.SUCCESS, `Task ${this.currentId} was created successfully`));
this.task = task;
this.taskService.selectTask(this.task);
this.taskService.publishAddedTask(task);
this.router.navigate(['../' + task.taskId], {relativeTo: this.route});
});
}
private addDateToTask() {
const date = TaskanaDate.getDate();
this.task.created = date;
this.task.modified = date;
}
openTask() {
this.router.navigate([{ outlets: { detail: `task/${this.currentId}` } }], { relativeTo: this.route.parent });
@ -142,16 +119,51 @@ export class TaskdetailsComponent implements OnInit, OnDestroy {
this.tabSelected = tab;
}
backClicked(): void {
this.task = undefined;
this.taskService.selectTask(this.task);
this.router.navigate(['./'], { relativeTo: this.route.parent });
}
ngOnDestroy(): void {
if (this.routeSubscription) {
this.routeSubscription.unsubscribe();
private onSave() {
this.currentId === 'new-task' ? this.createTask() : this.updateTask();
}
private updateTask() {
this.requestInProgressService.setRequestInProgress(true);
this.taskService.updateTask(this.task).subscribe(task => {
this.requestInProgressService.setRequestInProgress(false);
this.task = task;
this.cloneTask();
this.taskService.publishUpdatedTask(task);
this.alertService.triggerAlert(new AlertModel(AlertType.SUCCESS, 'Updating was successful.'))
}, err => {
this.requestInProgressService.setRequestInProgress(false);
this.alertService.triggerAlert(new AlertModel(AlertType.DANGER, 'There was an error while updating.'))
});
}
private createTask() {
this.requestInProgressService.setRequestInProgress(true);
this.addDateToTask();
this.taskService.createTask(this.task).subscribe(task => {
this.requestInProgressService.setRequestInProgress(false);
this.alertService.triggerAlert(new AlertModel(AlertType.SUCCESS, `Task ${this.currentId} was created successfully.`));
this.task = task;
this.taskService.selectTask(this.task);
this.taskService.publishAddedTask(task);
this.router.navigate(['../' + task.taskId], { relativeTo: this.route });
}, err => {
this.requestInProgressService.setRequestInProgress(false);
this.alertService.triggerAlert(new AlertModel(AlertType.DANGER, 'There was an error while creating a new task.'))
});
}
private addDateToTask() {
const date = TaskanaDate.getDate();
this.task.created = date;
this.task.modified = date;
}
private cloneTask() {
@ -160,4 +172,16 @@ export class TaskdetailsComponent implements OnInit, OnDestroy {
this.taskClone.callbackInfo = this.task.callbackInfo.slice(0);
this.taskClone.primaryObjRef = { ...this.task.primaryObjRef };
}
ngOnDestroy(): void {
if (this.routeSubscription) {
this.routeSubscription.unsubscribe();
if (this.workbasketSubscription) {
this.workbasketSubscription.unsubscribe();
}
if (this.masterAndDetailSubscription) {
this.masterAndDetailSubscription.unsubscribe();
}
}
}
}

View File

@ -1,35 +1,23 @@
<li id="tasklist-action-toolbar" class="list-group-item tab-align">
<div class="row">
<div *ngIf="currentBasket" class="col-xs-2">
<button (click)="createTask()" type="button"
class="btn btn-default pull-left green-blue"
title="Add Task to current Workbasket">
<button (click)="createTask()" type="button" class="btn btn-default pull-left green-blue" title="Add Task to current Workbasket">
<span class="glyphicon glyphicon-plus"></span>
</button>
</div>
<div class="col-xs-7">
<input [(ngModel)]="resultName" [typeahead]="workbasketNames" class="form-control"
(typeaheadOnSelect)="searchBasket()" (typeaheadNoResults)="workbasketSelected = false"
placeholder="Search for Workbasket ..."/>
<div class="col-xs-6">
<input [(ngModel)]="resultName" [typeahead]="workbasketNames" class="form-control" (typeaheadOnSelect)="searchBasket()"
(typeaheadNoResults)="workbasketSelected = false" placeholder="Search for Workbasket ..." />
</div>
<div class="pull-right margin-right">
<taskana-sort
[sortingFields]="sortingFields"
(performSorting)="sorting($event)"></taskana-sort>
<button class="btn btn-default collapsed" type="button"
id="collapsedMenufilterWb" aria-expanded="false"
(click)="toolbarState=!toolbarState">
<div *ngIf="currentBasket" class="pull-right margin-right">
<button class="btn btn-default collapsed" type="button" id="collapsedMenufilterWb" aria-expanded="false" (click)="toolbarState=!toolbarState">
<span class="glyphicon glyphicon-filter blue"></span>
</button>
<taskana-sort [sortingFields]="sortingFields" (performSorting)="sorting($event)" class="btn-group"></taskana-sort>
</div>
</div>
<div [@toggleDown]="toolbarState" class="row no-overflow">
<taskana-filter
[filterParams]="filterParams"
[filterType]="filterType"
(performFilter)="filtering($event)">
<taskana-filter [filterParams]="filterParams" [filterType]="filterType" (performFilter)="filtering($event)">
</taskana-filter>
</div>
</li>

View File

@ -4,6 +4,7 @@
}
.tab-align{
padding: 8px 12px 8px 0px;
margin-bottom: 0px;
&>div{

View File

@ -1,20 +1,37 @@
<div class="taskana-task-list">
<div class="footer-space-pagination-list">
<div #wbToolbar>
<taskana-tasklist-toolbar (performSorting)="performSorting($event)" (performFilter)="performFilter($event)" (importSucessful)="refreshWorkbasketList()">
<taskana-tasklist-toolbar (performSorting)="performSorting($event)" (performFilter)="performFilter($event)"
(importSucessful)="refreshWorkbasketList()">
</taskana-tasklist-toolbar>
</div>
<div *ngIf="!requestInProgress" class="footer-space-task">
<div *ngIf="!requestInProgress">
<div *ngIf="(tasks && tasks.length > 0); else empty_list">
<ul #taskList id="task-list-container" class="list-group">
<li class="list-group-item" *ngFor="let task of tasks" [class.active]="task.taskId == selectedId" type="text"
(click)="selectTask(task.taskId)">
<div class="row">
<dl class="col-xs-10">
<dt data-toggle="tooltip" title="{{task.name}}">{{task.name}}</dt>
<dd data-toggle="tooltip" title="{{task.owner}}">Owner: {{task.owner}} &nbsp;</dd>
<dd data-toggle="tooltip" title="{{task.priority}}">Priority: {{task.priority}} &nbsp;</dd>
<dd data-toggle="tooltip" title="{{task.state}}">State: {{task.state}} &nbsp;</dd>
<dl class="col-xs-2">
<span data-toggle="tooltip" class="badge" [ngClass]="{
'badge-red': task.priority <=5,
'badge-orange': (task.priority > 5 && task.priority <=15),
'badge-green': task.priority > 15}"
title="{{task.priority}}">{{task.priority}}</span>
</dl>
<dl class="col-xs-8">
<dt>
<span data-toggle="tooltip" title="{{task.name}}">{{task.name}}</span>
<i *ngIf="task.owner" data-toggle="tooltip" title="{{task.owner}}">, {{task.owner}}</i>
</dt>
</dl>
</div>
<div class="row">
<dl class="col-xs-3 col-xs-offset-2">
<dd data-toggle="tooltip" title="{{task.state}}">{{task.state}}</dd>
</dl>
<dl class="pull-right padding-right">
<i data-toggle="tooltip" title="{{task.due}}">Due: {{displayDate(task.due)}}</i>
</dl>
</div>
</li>
</ul>
@ -26,6 +43,6 @@
</div>
</ng-template>
</div>
<taskana-pagination *ngIf="tasks && tasks.length > 0" [(page)]="page" [type]="type" (changePage)="changePage($event)"></taskana-pagination>
</div>
<taskana-pagination *ngIf="tasks && tasks.length > 0" [(page)]="tasksPageInformation" [type]="type" (changePage)="changePage($event)"></taskana-pagination>
<taskana-code></taskana-code>

View File

@ -2,44 +2,15 @@
cursor: pointer;
}
.row.list-group {
margin-left: 2px;
}
.list-group > li {
border-left: none;
border-right: none;
}
ul {
max-height: 90vh;
margin-bottom: 10px;
overflow-y: auto;
}
a > label {
height: 2em;
width: 100%;
}
dd, dt {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
dt > i {
font-weight: normal;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
}
li > div.row > dl {
margin-bottom: 0px;
}
.no-space {
border-top: none;
padding: 0px
.list-group-item>div>dl>span.badge{
margin-left: 8px;
}

View File

@ -10,9 +10,10 @@ import {AlertService} from 'app/services/alert/alert.service';
import { AlertModel, AlertType } from 'app/models/alert';
import { WorkplaceService } from 'app/workplace/services/workplace.service';
import { TaskanaQueryParameters } from 'app/shared/util/query-parameters';
import { Page } from 'app/models/page';
import { OrientationService } from 'app/services/orientation/orientation.service';
import { Orientation } from 'app/models/orientation';
import { Page } from 'app/models/page';
import { TaskanaDate } from 'app/shared/util/taskana.date';
@Component({
selector: 'taskana-task-list',
@ -22,10 +23,7 @@ import { Orientation } from 'app/models/orientation';
export class TasklistComponent implements OnInit, OnDestroy {
tasks: Task[];
page: Page;
pageSelected = 1;
pageSize = 6;
tasksPageInformation: Page;
type = 'tasks';
currentBasket: Workbasket;
selectedId = '';
@ -91,8 +89,6 @@ export class TasklistComponent implements OnInit, OnDestroy {
this.selectedId = undefined;
}
});
TaskanaQueryParameters.page = this.pageSelected;
TaskanaQueryParameters.pageSize = this.pageSize;
this.orientationSubscription = this.orientationService.getOrientation().subscribe((orientation: Orientation) => {
this.refreshWorkbasketList();
})
@ -126,7 +122,7 @@ export class TasklistComponent implements OnInit, OnDestroy {
calculateHeightCard() {
if (this.toolbarElement && this.currentBasket) {
const toolbarSize = this.toolbarElement.nativeElement.offsetHeight;
const cardHeight = 95;
const cardHeight = 53;
const unusedHeight = 140;
const totalHeight = window.innerHeight;
const cards = Math.round((totalHeight - (unusedHeight + toolbarSize)) / cardHeight);
@ -152,13 +148,15 @@ export class TasklistComponent implements OnInit, OnDestroy {
this.tasks = [];
this.alertService.triggerAlert(new AlertModel(AlertType.INFO, 'The selected Workbasket is empty!'));
}
if (tasks.page) {
this.page = tasks.page;
}
this.tasksPageInformation = tasks.page;
});
}
}
displayDate(date: string): string {
return TaskanaDate.getDateToDisplay(date);
}
ngOnDestroy(): void {
this.taskChangeSubscription.unsubscribe();
this.taskDeletedSubscription.unsubscribe();

View File

@ -14,7 +14,9 @@ import {TaskdetailsCustomFieldsComponent} from './taskdetails/custom/custom-fiel
import { TaskdetailsAttributeComponent } from './taskdetails/attribute/attribute.component';
import { TaskComponent } from './task/task.component';
import { CodeComponent } from './components/code/code.component';
import { GeneralFieldsExtensionComponent } from './taskdetails/general-fields-extension/general-fields-extension.component';
import { AccordionModule } from 'ngx-bootstrap/accordion';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
import { OrderTasksByPipe } from './util/orderTasksBy.pipe';
@ -29,6 +31,8 @@ import {WorkplaceService} from './services/workplace.service';
const MODULES = [
TypeaheadModule.forRoot(),
AccordionModule.forRoot(),
BsDropdownModule.forRoot(),
CommonModule,
FormsModule,
HttpClientModule,
@ -47,6 +51,7 @@ const DECLARATIONS = [
TaskdetailsAttributeComponent,
TaskComponent,
CodeComponent,
GeneralFieldsExtensionComponent,
OrderTasksByPipe
];

View File

@ -3,10 +3,12 @@ $blue: #2e9eca;
$green: #246972;
$dark-green: #175263;
$grey: grey;
$light-grey: #ddd;
$light-grey: #f5f5f5;
$brown: #f0ad4e;
$invalid: #d82626;
$aquamarine: #22a39f;
$pallete-blue: #36bcee;
$pallete-green: #5fbca1;
$transparent-grey: rgba(192, 192, 192, 0.65);

View File

@ -8,3 +8,4 @@
@import 'checkboxes';
@import 'tabs';
@import 'bootstrap-3-backward-compatibility';
@import 'mixin/colors';

View File

@ -17,7 +17,6 @@
border-radius: 0px;
}
/*
* Base structure
*/
@ -154,16 +153,9 @@ svg-icon.fa-fw > svg {
min-width: 0px;
}
.footer-space-workbasket {
max-height: calc(100vh - 140px);
height: calc(100vh - 140px);
overflow-y: auto;
overflow-x: hidden;
}
.footer-space-task {
max-height: calc(100vh - 182px);
height: calc(100vh - 150px);
.footer-space-pagination-list {
max-height: calc(100vh - 130px);
height: calc(100vh - 130px);
overflow-y: auto;
overflow-x: hidden;
}
@ -286,8 +278,8 @@ body{
}
}
taskana-workbasket-information,taskana-task-details, taskana-workbasket-access-items, taskana-workbaskets-distribution-targets, taskana-monitor-tasks,
taskana-monitor-workbaskets, taskana-monitor-classification-tasks, taskana-access-items-management, taskana-classification-details,taskana-workbasket-details {
taskana-workbasket-information, taskana-workbasket-access-items, taskana-workbaskets-distribution-targets, taskana-workbasket-details, taskana-monitor-tasks,
taskana-monitor-workbaskets, taskana-monitor-classification-tasks {
& .panel{
border: none;
box-shadow: none;
@ -300,8 +292,17 @@ taskana-monitor-workbaskets, taskana-monitor-classification-tasks, taskana-acces
}
}
.taskana-workbasket-list, .taskana-task-list {
height: calc(100vh - 55px);
taskana-task-details, taskana-classification-details, taskana-access-items-management, taskana-task {
& .panel{
border: none;
box-shadow: none;
margin-bottom: 0px;
&> .panel-body {
height: calc(100vh - 100px);
max-height: calc(100vh - 100px);
overflow-y: auto;
}
}
}
taskana-monitor-tasks, taskana-monitor-workbaskets, taskana-monitor-classification-tasks, taskana-access-items-management {
@ -330,6 +331,7 @@ li.list-group-item:hover {
.vertical-right-divider {
border-right: 1px solid #ccc;
height: calc(100vh - 55px);
}
.horizontal-bottom-divider {
border-bottom: 1px solid #ccc;
@ -340,12 +342,21 @@ li.list-group-item:hover {
width: 150px;
height: 150px;
fill: grey;
color: grey;
margin: 20px auto;
font-size: 100px;
}
.btn.no-style{
border: none;
background-color: transparent;
}
.align-header{
margin-top: 3px;
}
.container-no-items {
top: 20vh;
height: 60vh;
height: 40vh;
}
.center-block {
@ -367,3 +378,6 @@ li.list-group-item:hover {
.modal-backdrop.show {
background-color: $transparent-grey;
}
.padding-right.pull-right {
padding-right: 15px;
}

View File

@ -1,5 +1,9 @@
.dropdown-menu.show {
.dropdown-menu.show, .modal-backdrop.show, .fade.show {
display: block;
opacity: 1;
visibility: visible;
}
.modal.fade .modal-dialog {
transform: translate(0,0);
}

View File

@ -0,0 +1,17 @@
@mixin colors {
&-red {
background-color: $invalid;
}
&-green {
background-color: $pallete-green;
}
&-orange {
background-color: $brown;
}
}
.badge{
@include colors;
}

View File

@ -57,6 +57,13 @@
"AUTOMATIC": "assets/icons/categories/automatic.svg",
"PROCESS": "assets/icons/categories/process.svg"
}
},
"tasks": {
"information": {
"owner": {
"lookupField": true
}
}
}
}
}