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,54 +29,62 @@
<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">
<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">
<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">
<a *ngIf="!masterDomainSelected()" (click)="validChanged()">
<label>
<b>Valid in Domain:</b>
<span class="glyphicon {{classification.isValidInDomain ? 'glyphicon-check': 'glyphicon-unchecked'}} blue"
aria-hidden="true"></span>
</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>
<label>
<b>Valid in Domain:</b>
<span class="glyphicon {{classification.isValidInDomain ? 'glyphicon-check': 'glyphicon-unchecked'}} blue"
aria-hidden="true"></span>
</label>
</a>
</div>
</div>
<div class="form-group">
@ -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,32 +55,36 @@
</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">
<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">
<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="dropdownMenu">
<li>
<a *ngFor="let type of allTypes | mapValues | removeEmptyType" (click)="selectType(type.key)">
<taskana-icon-type class="vertical-align" [type]='type.key' [text]="type.value"></taskana-icon-type>
</a>
</li>
</ul>
<div class="row">
<div class="form-group col-xs-6">
<label for="wb-type" class="control-label">Type</label>
<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>
{{allTypes.get(workbasket.type)}}
<span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu" aria-labelledby="dropdownMenu">
<li>
<a *ngFor="let type of allTypes | mapValues | removeEmptyType" (click)="selectType(type.key)">
<taskana-icon-type class="vertical-align" [type]='type.key' [text]="type.value"></taskana-icon-type>
</a>
</li>
</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

@ -96,7 +96,7 @@ export class WorkbasketInformationComponent
]);
}
ngOnInit(): void {}
ngOnInit(): void { }
ngOnChanges(changes: SimpleChanges): void {
this.workbasketClone = { ...this.workbasket };
@ -138,7 +138,7 @@ export class WorkbasketInformationComponent
this.removeConfirmationService.setRemoveConfirmation(
this.onRemoveConfirmed.bind(this),
`You are going to delete workbasket: ${
this.workbasket.key
this.workbasket.key
}. Can you confirm this action?`
);
}
@ -162,7 +162,7 @@ export class WorkbasketInformationComponent
new AlertModel(
AlertType.SUCCESS,
`DistributionTarget for workbasketID: ${
this.workbasket.workbasketId
this.workbasket.workbasketId
} was removed successfully`
)
);
@ -171,7 +171,7 @@ export class WorkbasketInformationComponent
this.errorModalService.triggerError(
new ErrorModel(
`There was an error removing distribution target for ${
this.workbasket.workbasketId
this.workbasket.workbasketId
}.`,
error
)
@ -281,7 +281,7 @@ export class WorkbasketInformationComponent
if (response) {
this.errorModalService.triggerError(
new ErrorModel('There was an error marking workbasket for deletion',
'It not possible to mark the workbasket for deletion, It has been deleted.')
'It not possible to mark the workbasket for deletion, It has been deleted.')
);
} else {
this.alertService.triggerAlert(

View File

@ -1,12 +1,12 @@
<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>
<taskana-import-export-component (importSucessful)="importEvent()" [currentSelection]="selectionToImport"></taskana-import-export-component>
</div>
<div class="margin-right pull-right ">
<div class="margin-right pull-right ">
<button class="btn btn-default collapsed" type="button" id="collapsedMenufilterWb" aria-expanded="false" (click)="toolbarState=!toolbarState"
data-toggle="tooltip" title="Filter">
<span class="glyphicon glyphicon-filter blue"></span>

View File

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

View File

@ -1,42 +1,41 @@
<div class="workbasket-list-full-height">
<div class="footer-space-workbasket">
<div #wbToolbar>
<taskana-workbasket-list-toolbar [workbaskets]="workbaskets" (performFilter)="performFilter($event)"
(performSorting)="performSorting($event)" (importSucessful)="refreshWorkbasketList()"></taskana-workbasket-list-toolbar>
</div>
<div *ngIf="(workbaskets && workbaskets.length > 0) else empty_workbaskets">
<ul #wbList id="wb-list-container" class="list-group">
<li class="list-group-item no-space">
<div class="row"></div>
</li>
<li class="list-group-item" *ngFor="let workbasket of workbaskets" [class.active]="workbasket.workbasketId == selectedId"
type="text" (click)="selectWorkbasket(workbasket.workbasketId)">
<div class="row">
<dl class="col-xs-1">
<taskana-icon-type class="vertical-align" [type]="workbasket.type" tooltip="true" [selected]="workbasket.workbasketId === selectedId"></taskana-icon-type>
</dl>
<dl class="col-xs-10">
<dt data-toggle="tooltip" title="{{workbasket.name}}">{{workbasket.name}},
<i data-toggle="tooltip" title="{{workbasket.key}}">{{workbasket.key}} </i>
</dt>
<dd data-toggle="tooltip" title="{{workbasket.description}}">{{workbasket.description}} &nbsp;</dd>
<dd data-toggle="tooltip" title="{{workbasket.owner}}">{{workbasket.owner}} &nbsp;</dd>
</dl>
<dl *ngIf="workbasket.markedForDeletion">
<span class="{{workbasket.workbasketId === selectedId ? 'white': 'red' }} glyphicon glyphicon-exclamation-sign"
aria-hidden="true" data-toggle="tooltip" title="Marked for deletion"></span>
</dl>
</div>
</li>
</ul>
</div>
<taskana-spinner [isRunning]="requestInProgress"></taskana-spinner>
<ng-template #empty_workbaskets>
<div *ngIf="!requestInProgress" class="col-xs-12 container-no-items center-block">
<h3 class="grey">There are no workbaskets</h3>
<svg-icon class="img-responsive empty-icon" src="./assets/icons/wb-empty.svg"></svg-icon>
</div>
</ng-template>
<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>
</div>
<taskana-pagination [(page)]="workbasketsResource !== undefined ? workbasketsResource.page : workbasketsResource" [type]="type" (changePage)="changePage($event)"></taskana-pagination>
<div *ngIf="(workbaskets && workbaskets.length > 0) else empty_workbaskets">
<ul #wbList id="wb-list-container" class="list-group">
<li class="list-group-item no-space">
<div class="row"></div>
</li>
<li class="list-group-item" *ngFor="let workbasket of workbaskets" [class.active]="workbasket.workbasketId == selectedId"
type="text" (click)="selectWorkbasket(workbasket.workbasketId)">
<div class="row">
<dl class="col-xs-1">
<taskana-icon-type class="vertical-align" [type]="workbasket.type" tooltip="true" [selected]="workbasket.workbasketId === selectedId"></taskana-icon-type>
</dl>
<dl class="col-xs-10">
<dt data-toggle="tooltip" title="{{workbasket.name}}">{{workbasket.name}},
<i data-toggle="tooltip" title="{{workbasket.key}}">{{workbasket.key}} </i>
</dt>
<dd data-toggle="tooltip" title="{{workbasket.description}}">{{workbasket.description}} &nbsp;</dd>
<dd data-toggle="tooltip" title="{{workbasket.owner}}">{{workbasket.owner}} &nbsp;</dd>
</dl>
<dl *ngIf="workbasket.markedForDeletion">
<span class="{{workbasket.workbasketId === selectedId ? 'white': 'red' }} glyphicon glyphicon-exclamation-sign"
aria-hidden="true" data-toggle="tooltip" title="Marked for deletion"></span>
</dl>
</div>
</li>
</ul>
</div>
<taskana-spinner [isRunning]="requestInProgress"></taskana-spinner>
<ng-template #empty_workbaskets>
<div *ngIf="!requestInProgress" class="col-xs-12 container-no-items center-block">
<h3 class="grey">There are no workbaskets</h3>
<svg-icon class="img-responsive empty-icon" src="./assets/icons/wb-empty.svg"></svg-icon>
</div>
</ng-template>
</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

@ -2,16 +2,16 @@ import { trigger, style, transition, animate, keyframes, state } from '@angular/
export const expandDown =
trigger('toggleDown', [
state('true', style({ opacity: '1', display: 'initial' })),
state('false', style({ opacity: '0', display: 'none' })),
transition('false => true', animate('300ms ease-in', keyframes([
style({ opacity: 0, height: '0px' }),
style({ opacity: 0.5, height: '50px' }),
style({ opacity: 1, height: '*' })]))),
transition('true => false', animate('300ms ease-out', keyframes([
style({ opacity: 1, height: '*' }),
style({ opacity: 0.5, height: '50px' }),
style({ opacity: 0, height: '0px' })])))
state('true', style({ opacity: '1', display: 'initial' })),
state('false', style({ opacity: '0', display: 'none' })),
transition('false => true', animate('300ms ease-in', keyframes([
style({ opacity: 0, height: '0px' }),
style({ opacity: 0.5, height: '50px' }),
style({ opacity: 1, height: '*' })]))),
transition('true => false', animate('300ms ease-out', keyframes([
style({ opacity: 1, height: '*' }),
style({ opacity: 0.5, height: '50px' }),
style({ opacity: 0, height: '0px' })])))
]);
export const expandRight = trigger('toggleRight', [

View File

@ -1,66 +1,74 @@
<div class="list-group-search">
<div class="row">
<div *ngIf="filterTypeIsWorkbasket(); else tasktype">
<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>
<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>
<ng-template #tasktype>
<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>
<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>
<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>
<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>
</ng-template>
<button (click)="clear(); search()" type="button" class="btn btn-default glyphicon glyphicon-ban-circle blue pull-right margin-right"
data-toggle="tooltip" title="Clear">
</button>
</div>
<div class="filter-list">
<li class="" *ngFor="let filterType of getUnusedKeys()">
<div class="row padding">
<div class="col-xs-2">
</div>
<div class="col-xs-8">
<div *ngIf="checkUppercaseFilterType(filterType); else normalFilter">
<input type="text" [(ngModel)]="filter.filterParams[filterType]" (ngModelChange)="filter.filterParams[filterType] = $event.toLocaleUpperCase()"
(keyup.enter)="search()" class="form-control" id="display-{{filterType}}-filter" placeholder="Filter {{filterType}}">
</div>
<ng-template #normalFilter>
<input type="text" [(ngModel)]="filter.filterParams[filterType]" (keyup.enter)="search()" class="form-control" id="display-{{filterType}}-filter"
placeholder="Filter {{filterType}}">
</ng-template>
</div>
<div *ngIf="filterType === lastFilterKey" class="pull-right">
<button (click)="search()" type="button" class="btn btn-default glyphicon glyphicon-search blue pull-right margin-right"
data-toggle="tooltip" title="Search">
</button>
</div>
<div 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>
</li>
</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

@ -7,99 +7,99 @@ import { AccessIdsService } from 'app/shared/services/access-ids/access-ids.serv
@Injectable()
export class FormsValidatorService {
public formSubmitAttempt = false;
private workbasketOwner = 'workbasket.owner';
public formSubmitAttempt = false;
private workbasketOwner = 'workbasket.owner';
constructor(
private alertService: AlertService,
private accessIdsService: AccessIdsService) {
}
public validateFormInformation(form: NgForm, toogleValidationMap: Map<any, boolean>): Promise<any> {
let validSync = true;
const forFieldsPromise = new Promise((resolve, reject) => {
for (const control in form.form.controls) {
if (control.indexOf('owner') === -1 && form.form.controls[control].invalid) {
const validationState = toogleValidationMap.get(control);
validationState ? toogleValidationMap.set(control, !validationState) : toogleValidationMap.set(control, true);
validSync = false;
}
}
resolve(validSync);
});
const ownerPromise = new Promise((resolve, reject) => {
const ownerString = 'owner';
if (form.form.controls[this.workbasketOwner]) {
this.accessIdsService.getAccessItemsInformation(form.form.controls[this.workbasketOwner].value).subscribe(items => {
const validationState = toogleValidationMap.get(this.workbasketOwner);
validationState ? toogleValidationMap.set(this.workbasketOwner, !validationState) :
toogleValidationMap.set(this.workbasketOwner, true);
items.find(item => item.accessId === form.form.controls[this.workbasketOwner].value) ?
resolve(new ResponseOwner({valid: true, field: ownerString})) :
resolve(new ResponseOwner({valid: false, field: ownerString}));
});
} else {
const validationState = toogleValidationMap.get(form.form.controls[this.workbasketOwner]);
validationState ? toogleValidationMap.set(this.workbasketOwner, !validationState) :
toogleValidationMap.set(this.workbasketOwner, true);
resolve(new ResponseOwner({valid: true, field: ownerString}));
}
});
return Promise.all([forFieldsPromise, ownerPromise]).then(values => {
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.'))
} else {
this.alertService.triggerAlert(new AlertModel(AlertType.WARNING, 'There are some empty fields which are required.'))
}
}
return values[0] && responseOwner.valid;
});
constructor(
private alertService: AlertService,
private accessIdsService: AccessIdsService) {
}
public validateFormAccess(form: FormArray, toogleValidationAccessIdMap: Map<any, boolean>): Promise<boolean> {
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) {
const validationState = toogleValidationMap.get(control);
validationState ? toogleValidationMap.set(control, !validationState) : toogleValidationMap.set(control, true);
validSync = false;
}
}
resolve(validSync);
});
const ownerPromise = new Promise((resolve, reject) => {
const ownerString = 'owner';
if (form.form.controls[this.workbasketOwner]) {
this.accessIdsService.getAccessItemsInformation(form.form.controls[this.workbasketOwner].value).subscribe(items => {
const validationState = toogleValidationMap.get(this.workbasketOwner);
validationState ? toogleValidationMap.set(this.workbasketOwner, !validationState) :
toogleValidationMap.set(this.workbasketOwner, true);
items.find(item => item.accessId === form.form.controls[this.workbasketOwner].value) ?
resolve(new ResponseOwner({ valid: true, field: ownerString })) :
resolve(new ResponseOwner({ valid: false, field: ownerString }));
});
} else {
const validationState = toogleValidationMap.get(form.form.controls[this.workbasketOwner]);
validationState ? toogleValidationMap.set(this.workbasketOwner, !validationState) :
toogleValidationMap.set(this.workbasketOwner, true);
resolve(new ResponseOwner({ valid: true, field: ownerString }));
}
});
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.'));
} else {
this.alertService.triggerAlert(new AlertModel(AlertType.WARNING, 'There are some empty fields which are required.'));
}
}
return values[0] && responseOwner.valid;
}
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++) {
ownerPromise.push(new Promise((resolve, reject) => {
const validationState = toogleValidationAccessIdMap.get(i);
validationState ? toogleValidationAccessIdMap.set(i, !validationState) :
validationState ? toogleValidationAccessIdMap.set(i, !validationState) :
toogleValidationAccessIdMap.set(i, true);
this.accessIdsService.getAccessItemsInformation(form.controls[i].value['accessId']).subscribe(items => {
items.length > 0 ?
resolve(new ResponseOwner({valid: true, field: 'access id'})) :
resolve(new ResponseOwner({valid: false, field: 'access id'}));
resolve(new ResponseOwner({ valid: true, field: 'access id' })) :
resolve(new ResponseOwner({ valid: false, field: 'access id' }));
})
}));
}
let result = true;
return Promise.all(ownerPromise).then(values => {
let responseOwner;
for (let i = 0; i < values.length; i++) {
responseOwner = new ResponseOwner(values[i]);
result = result && responseOwner.valid;
}
if (!result) {
this.alertService.triggerAlert(new AlertModel(AlertType.WARNING, 'The ' + responseOwner.field + ' introduced is not valid.'))
}
return result;
});
const values = await Promise.all(ownerPromise);
let responseOwner;
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.'));
}
return result;
}
public isFieldValid(ngForm: NgForm, field: string) {
if (!ngForm || !ngForm.form.controls || !ngForm.form.controls[field]) {
return false;
}
if (!this.formSubmitAttempt) {
return true;
}
return (this.formSubmitAttempt && ngForm.form.controls[field].valid) ||
(ngForm.form.controls[field].touched && ngForm.form.controls[field].valid);
if (!ngForm || !ngForm.form.controls || !ngForm.form.controls[field]) {
return false;
}
if (!this.formSubmitAttempt) {
return true;
}
return (this.formSubmitAttempt && ngForm.form.controls[field].valid) ||
(ngForm.form.controls[field].touched && ngForm.form.controls[field].valid);
}
}

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

@ -1,5 +1,5 @@
<div [ngClass]="{'no-display':!showSpinner}">
<div *ngIf ="!isModal" class="sk-circle {{positionClass? positionClass: 'spinner-centered'}}">
<div *ngIf="!isModal" class="sk-circle {{positionClass? positionClass: 'spinner-centered'}}">
<div class="sk-circle1 sk-child"></div>
<div class="sk-circle2 sk-child"></div>
<div class="sk-circle3 sk-child"></div>
@ -13,23 +13,21 @@
<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 class="modal-dialog {{positionClass? positionClass: 'spinner-centered'}}">
<div class="sk-circle">
<div class="sk-circle1 sk-child"></div>
<div class="sk-circle2 sk-child"></div>
<div class="sk-circle3 sk-child"></div>
<div class="sk-circle4 sk-child"></div>
<div class="sk-circle5 sk-child"></div>
<div class="sk-circle6 sk-child"></div>
<div class="sk-circle7 sk-child"></div>
<div class="sk-circle8 sk-child"></div>
<div class="sk-circle9 sk-child"></div>
<div class="sk-circle10 sk-child"></div>
<div class="sk-circle11 sk-child"></div>
<div class="sk-circle12 sk-child"></div>
</div>
<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>
<div class="sk-circle2 sk-child"></div>
<div class="sk-circle3 sk-child"></div>
<div class="sk-circle4 sk-child"></div>
<div class="sk-circle5 sk-child"></div>
<div class="sk-circle6 sk-child"></div>
<div class="sk-circle7 sk-child"></div>
<div class="sk-circle8 sk-child"></div>
<div class="sk-circle9 sk-child"></div>
<div class="sk-circle10 sk-child"></div>
<div class="sk-circle11 sk-child"></div>
<div class="sk-circle12 sk-child"></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>
@ -42,4 +45,4 @@
</div>
</div>
</div>
</div>
</div>

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

@ -1,10 +1,11 @@
import {DatePipe} from '@angular/common';
import { DatePipe } from '@angular/common';
export class TaskanaDate {
public static getDate(): string {
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} statethe state 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"
class="glyphicon glyphicon-ok blue text-success"></span>
<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">
<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>
<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>
</div>
</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"
name="task.note">
<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"
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"
name="task.due">
</div>
</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"
name="task.due">
</div>
</div>
</form>
</form>
</div>
<div class="row">
<iframe class="col-xs-12" [src]="link"></iframe>
</div>
</div>
</div>
<iframe [src]="link"></iframe>
</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,167 +1,117 @@
<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>
</div>
</div>
<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>
<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>
</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>
<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>
<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'}}
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu">
<li>
<a *ngFor="let classification of classifications" (click)="selectClassification(classification)">
{{classification.name}}
</a>
</li>
</ul>
</div>
<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 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="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 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>
<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" *dropdownMenu>
<li>
<a *ngFor="let classification of classifications" (click)="selectClassification(classification)">
{{classification.name}}
</a>
</li>
</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-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="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">
<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-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>
<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"
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>
</ng-container>
</form>
</ng-container>

View File

@ -1,25 +1,50 @@
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {Task} from 'app/workplace/models/task';
import {Classification} from '../../../models/classification';
import {ClassificationsService} from '../../../services/classifications/classifications.service';
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>
[disabled]="workOnTaskDisabled()" (click)="openTask()">
<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'}">
<taskana-task-details-custom-fields [task]="task"></taskana-task-details-custom-fields>
</div>
<div role="tabpanel" class="tab-pane" [ngClass]="{'active':tabSelected === 'custom-attributes'}">
<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 *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>
</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>
</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>
</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

@ -1,20 +1,21 @@
import {Component, OnDestroy, OnInit} from '@angular/core';
import {Subscription} from 'rxjs';
import {ActivatedRoute, Router} from '@angular/router';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { ActivatedRoute, Router } from '@angular/router';
import {TaskService} from 'app/workplace/services/task.service';
import {RemoveConfirmationService} from 'app/services/remove-confirmation/remove-confirmation.service';
import { TaskService } from 'app/workplace/services/task.service';
import { RemoveConfirmationService } from 'app/services/remove-confirmation/remove-confirmation.service';
import {Task} from 'app/workplace/models/task';
import {ErrorModel} from 'app/models/modal-error';
import {ErrorModalService} from 'app/services/errorModal/error-modal.service';
import {RequestInProgressService} from 'app/services/requestInProgress/request-in-progress.service';
import {AlertService} from 'app/services/alert/alert.service';
import {AlertModel, AlertType} from 'app/models/alert';
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 { Task } from 'app/workplace/models/task';
import { ErrorModel } from 'app/models/modal-error';
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
import { RequestInProgressService } from 'app/services/requestInProgress/request-in-progress.service';
import { AlertService } from 'app/services/alert/alert.service';
import { AlertModel, AlertType } from 'app/models/alert';
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,18 +29,21 @@ 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,
private workplaceService: WorkplaceService,
private router: Router,
private removeConfirmationService: RemoveConfirmationService,
private requestInProgressService: RequestInProgressService,
private alertService: AlertService,
private errorModalService: ErrorModalService) {
private taskService: TaskService,
private workplaceService: WorkplaceService,
private router: Router,
private removeConfirmationService: RemoveConfirmationService,
private requestInProgressService: RequestInProgressService,
private alertService: AlertService,
private errorModalService: ErrorModalService,
private masterAndDetailService: MasterAndDetailService) {
}
ngOnInit() {
@ -55,13 +59,16 @@ export class TaskdetailsComponent implements OnInit, OnDestroy {
}
this.getTask();
});
this.masterAndDetailSubscription = this.masterAndDetailService.getShowDetail().subscribe(showDetail => {
this.showDetail = showDetail;
});
}
resetTask(): void {
this.task = {...this.taskClone};
this.task = { ...this.taskClone };
this.task.customAttributes = this.taskClone.customAttributes.slice(0);
this.task.callbackInfo = this.taskClone.callbackInfo.slice(0);
this.task.primaryObjRef = {...this.taskClone.primaryObjRef};
this.task.primaryObjRef = { ...this.taskClone.primaryObjRef };
this.alertService.triggerAlert(new AlertModel(AlertType.INFO, 'Reset edited fields'));
}
@ -83,43 +90,13 @@ 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});
this.router.navigate([{ outlets: { detail: `task/${this.currentId}` } }], { relativeTo: this.route.parent });
}
workOnTaskDisabled(): boolean {
@ -142,22 +119,69 @@ 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});
this.router.navigate(['./'], { relativeTo: this.route.parent });
}
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() {
this.taskClone = { ...this.task };
this.taskClone.customAttributes = this.task.customAttributes.slice(0);
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();
}
}
}
private cloneTask() {
this.taskClone = {...this.task};
this.taskClone.customAttributes = this.task.customAttributes.slice(0);
this.taskClone.callbackInfo = this.task.callbackInfo.slice(0);
this.taskClone.primaryObjRef = {...this.task.primaryObjRef};
}
}

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>
</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>
</li>

View File

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

View File

@ -1,14 +1,14 @@
import {Component, EventEmitter, OnInit, Output} from '@angular/core';
import {Task} from 'app/workplace/models/task';
import {Workbasket} from 'app/models/workbasket';
import {TaskService} from 'app/workplace/services/task.service';
import {WorkbasketService} from 'app/services/workbasket/workbasket.service';
import {SortingModel} from 'app/models/sorting';
import {FilterModel} from 'app/models/filter';
import {TaskanaType} from 'app/models/taskana-type';
import {expandDown} from 'app/shared/animations/expand.animation';
import {ActivatedRoute, Router} from '@angular/router';
import {WorkplaceService} from 'app/workplace/services/workplace.service';
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { Task } from 'app/workplace/models/task';
import { Workbasket } from 'app/models/workbasket';
import { TaskService } from 'app/workplace/services/task.service';
import { WorkbasketService } from 'app/services/workbasket/workbasket.service';
import { SortingModel } from 'app/models/sorting';
import { FilterModel } from 'app/models/filter';
import { TaskanaType } from 'app/models/taskana-type';
import { expandDown } from 'app/shared/animations/expand.animation';
import { ActivatedRoute, Router } from '@angular/router';
import { WorkplaceService } from 'app/workplace/services/workplace.service';
@Component({
selector: 'taskana-tasklist-toolbar',
@ -23,7 +23,7 @@ export class TaskListToolbarComponent implements OnInit {
sortingFields = new Map([['name', 'Name'], ['priority', 'Priority'], ['due', 'Due'], ['planned', 'Planned']]);
filterParams = {name: '', key: '', owner: '', priority: '', state: ''};
filterParams = { name: '', key: '', owner: '', priority: '', state: '' };
tasks: Task[] = [];
workbasketNames: string[] = [];
@ -36,10 +36,10 @@ export class TaskListToolbarComponent implements OnInit {
filterType = TaskanaType.TASKS;
constructor(private taskService: TaskService,
private workbasketService: WorkbasketService,
private workplaceService: WorkplaceService,
private router: Router,
private route: ActivatedRoute) {
private workbasketService: WorkbasketService,
private workplaceService: WorkplaceService,
private router: Router,
private route: ActivatedRoute) {
}
ngOnInit() {
@ -91,6 +91,6 @@ export class TaskListToolbarComponent implements OnInit {
createTask() {
this.taskService.selectTask(undefined);
this.router.navigate([{outlets: {detail: 'taskdetail/new-task'}}], {relativeTo: this.route});
this.router.navigate([{ outlets: { detail: 'taskdetail/new-task' } }], { relativeTo: this.route });
}
}

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-code></taskana-code>
<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

@ -1,18 +1,19 @@
import {Component, OnDestroy, OnInit, ViewChild, ElementRef} from '@angular/core';
import {Task} from 'app/workplace/models/task';
import {ActivatedRoute, Router} from '@angular/router';
import {TaskService} from 'app/workplace/services/task.service';
import {Subscription} from 'rxjs';
import {SortingModel} from 'app/models/sorting';
import {Workbasket} from 'app/models/workbasket';
import {FilterModel} from 'app/models/filter';
import {AlertService} from 'app/services/alert/alert.service';
import {AlertModel, AlertType} from 'app/models/alert';
import {WorkplaceService} from 'app/workplace/services/workplace.service';
import { Component, OnDestroy, OnInit, ViewChild, ElementRef } from '@angular/core';
import { Task } from 'app/workplace/models/task';
import { ActivatedRoute, Router } from '@angular/router';
import { TaskService } from 'app/workplace/services/task.service';
import { Subscription } from 'rxjs';
import { SortingModel } from 'app/models/sorting';
import { Workbasket } from 'app/models/workbasket';
import { FilterModel } from 'app/models/filter';
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 = '';
@ -50,11 +48,11 @@ export class TasklistComponent implements OnInit, OnDestroy {
private orientationSubscription: Subscription;
constructor(private router: Router,
private route: ActivatedRoute,
private taskService: TaskService,
private workplaceService: WorkplaceService,
private alertService: AlertService,
private orientationService: OrientationService) {
private route: ActivatedRoute,
private taskService: TaskService,
private workplaceService: WorkplaceService,
private alertService: AlertService,
private orientationService: OrientationService) {
this.taskChangeSubscription = this.taskService.taskChangedStream.subscribe(task => {
for (let i = 0; i < this.tasks.length; i++) {
if (this.tasks[i].taskId === task.taskId) {
@ -90,9 +88,7 @@ export class TasklistComponent implements OnInit, OnDestroy {
if (!task) {
this.selectedId = undefined;
}
});
TaskanaQueryParameters.page = this.pageSelected;
TaskanaQueryParameters.pageSize = this.pageSize;
});
this.orientationSubscription = this.orientationService.getOrientation().subscribe((orientation: Orientation) => {
this.refreshWorkbasketList();
})
@ -100,7 +96,7 @@ export class TasklistComponent implements OnInit, OnDestroy {
selectTask(taskId: string) {
this.selectedId = taskId;
this.router.navigate([{outlets: {detail: `taskdetail/${this.selectedId}`}}], {relativeTo: this.route});
this.router.navigate([{ outlets: { detail: `taskdetail/${this.selectedId}` } }], { relativeTo: this.route });
}
performSorting(sort: SortingModel) {
@ -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

@ -1,34 +1,38 @@
import {CommonModule} from '@angular/common';
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {HTTP_INTERCEPTORS, HttpClientModule} from '@angular/common/http';
import {AngularSvgIconModule} from 'angular-svg-icon';
import {WorkplaceRoutingModule} from './workplace-routing.module';
import {AlertModule, TypeaheadModule} from 'ngx-bootstrap';
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
import { AngularSvgIconModule } from 'angular-svg-icon';
import { WorkplaceRoutingModule } from './workplace-routing.module';
import { AlertModule, TypeaheadModule } from 'ngx-bootstrap';
import {TaskListToolbarComponent} from './tasklist/tasklist-toolbar/tasklist-toolbar.component';
import {TasklistComponent} from './tasklist/tasklist.component';
import {TaskdetailsComponent} from './taskdetails/taskdetails.component';
import {TaskdetailsGeneralFieldsComponent} from './taskdetails/general/general-fields.component';
import {TaskdetailsCustomFieldsComponent} from './taskdetails/custom/custom-fields.component';
import {TaskdetailsAttributeComponent} from './taskdetails/attribute/attribute.component';
import {TaskComponent} from './task/task.component';
import {CodeComponent} from './components/code/code.component';
import { TaskListToolbarComponent } from './tasklist/tasklist-toolbar/tasklist-toolbar.component';
import { TasklistComponent } from './tasklist/tasklist.component';
import { TaskdetailsComponent } from './taskdetails/taskdetails.component';
import { TaskdetailsGeneralFieldsComponent } from './taskdetails/general/general-fields.component';
import { TaskdetailsCustomFieldsComponent } from './taskdetails/custom/custom-fields.component';
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';
import {OrderTasksByPipe} from './util/orderTasksBy.pipe';
import {TaskService} from './services/task.service';
import {ClassificationsService} from 'app/services/classifications/classifications.service';
import {WorkbasketService} from 'app/services/workbasket/workbasket.service';
import {SharedModule} from 'app/shared/shared.module';
import {CustomHttpClientInterceptor} from './services/custom-http-interceptor/custom-http-interceptor.service';
import {ClassificationCategoriesService} from 'app/services/classifications/classification-categories.service';
import {WorkplaceService} from './services/workplace.service';
import { TaskService } from './services/task.service';
import { ClassificationsService } from 'app/services/classifications/classifications.service';
import { WorkbasketService } from 'app/services/workbasket/workbasket.service';
import { SharedModule } from 'app/shared/shared.module';
import { CustomHttpClientInterceptor } from './services/custom-http-interceptor/custom-http-interceptor.service';
import { ClassificationCategoriesService } from 'app/services/classifications/classification-categories.service';
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,20 +153,13 @@ svg-icon.fa-fw > svg {
min-width: 0px;
}
.footer-space-workbasket {
max-height: calc(100vh - 140px);
height: calc(100vh - 140px);
.footer-space-pagination-list {
max-height: calc(100vh - 130px);
height: calc(100vh - 130px);
overflow-y: auto;
overflow-x: hidden;
}
.footer-space-task {
max-height: calc(100vh - 182px);
height: calc(100vh - 150px);
overflow-y: auto;
overflow-x: hidden;
}
.margin-right {
margin-right: 2px;
}
@ -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
}
}
}
}
}
}