TSK-1477: Update workbasket information layout (#1364)

* TSK-1477: Update workbasket information layout

* TSK-1477: rearrange error message for description field

Co-authored-by: Chi Nguyen <c.nguyen.prog@gmail.com>
This commit is contained in:
Sofie Hofmann 2020-12-08 16:37:21 +01:00 committed by GitHub
parent 900343b722
commit ecfe7c3046
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 198 additions and 151 deletions

View File

@ -1,3 +1,3 @@
<svg-icon class="{{selected? 'white': 'grayIcon' }} {{size}}" src="./assets/icons/{{getIconPath(type)}}"
<svg-icon class="{{selected? 'white': 'gray' }} {{size}}" src="./assets/icons/{{getIconPath(type)}}"
[title]="!type? 'All' : type"></svg-icon>
{{text}}

Before

Width:  |  Height:  |  Size: 160 B

After

Width:  |  Height:  |  Size: 156 B

View File

@ -3,6 +3,8 @@
width: 24px;
}
.grayIcon {
fill: #555;
.gray {
fill: #555;
top: -3px;
}

View File

@ -18,7 +18,6 @@ import {
} from '../../../shared/store/workbasket-store/workbasket.actions';
import { ButtonAction } from '../../models/button-action';
import { RequestInProgressService } from '../../../shared/services/request-in-progress/request-in-progress.service';
import { WorkbasketComponent } from '../../models/workbasket-component';
@Component({
selector: 'taskana-administration-workbasket-details',

View File

@ -33,156 +33,167 @@
<div class="workbasket-information-wrapper">
<ng-form #WorkbasketForm="ngForm">
<div class="form">
<!-- GENERAL FIELDS -->
<div class="workbasket-information">
<!-- GENERAL FIELDS -->
<h6 class="subheading"> General </h6>
<mat-divider class="horizontal-line"> </mat-divider>
<h6 class="workbasket-information__subheading"> General </h6>
<mat-divider class="workbasket-information__horizontal-line"> </mat-divider>
<!-- GENERAL -->
<div class="general">
<!-- KEY -->
<mat-form-field appearance="outline">
<mat-label>Key</mat-label>
<label for="workbasket-key"></label>
<input matInput required type="text" #key="ngModel" maxlength="64" [disabled]="action == 0 || action == 3"
id="workbasket-key" placeholder="Key" [(ngModel)]="workbasket.key" name="workbasket.key"
(input)="validateInputOverflow(key, 64, $event)">
</mat-form-field>
<div *ngIf="inputOverflowMap.get(key.name)" class="error">{{lengthError}}</div>
<taskana-shared-field-error-display [displayError]="!isFieldValid('workbasket.key')"
[validationTrigger]="this.toggleValidationMap.get('workbasket.key')" errorMessage="* Key is required">
</taskana-shared-field-error-display>
<!-- GENERAL LEFT COLUMN -->
<div class="general__left-column">
<!-- NAME -->
<mat-form-field appearance="outline">
<mat-label>Name</mat-label>
<label for="workbasket-name"></label>
<input matInput type="text" required maxlength="255" #name="ngModel" id="workbasket-name" placeholder="Name"
[(ngModel)]="workbasket.name" name="workbasket.name" (input)="validateInputOverflow(name, 255)">
</mat-form-field>
<div *ngIf="inputOverflowMap.get(name.name)" class="error">{{lengthError}}</div>
<taskana-shared-field-error-display [displayError]="!isFieldValid('workbasket.name')"
[validationTrigger]="this.toggleValidationMap.get('workbasket.name')" errorMessage="* Name is required">
</taskana-shared-field-error-display>
<!-- KEY -->
<mat-form-field appearance="outline">
<mat-label>Key</mat-label>
<label for="workbasket-key"></label>
<input matInput required type="text" #key="ngModel" maxlength="64" [disabled]="action == 0 || action == 3"
id="workbasket-key" placeholder="Key" [(ngModel)]="workbasket.key" name="workbasket.key"
(input)="validateInputOverflow(key, 64, $event)">
</mat-form-field>
<div *ngIf="inputOverflowMap.get(key.name)" class="error">{{lengthError}}</div>
<taskana-shared-field-error-display [displayError]="!isFieldValid('workbasket.key')"
[validationTrigger]="this.toggleValidationMap.get('workbasket.key')" errorMessage="* Key is required">
</taskana-shared-field-error-display>
<!-- NAME -->
<mat-form-field appearance="outline">
<mat-label>Name</mat-label>
<label for="workbasket-name"></label>
<input matInput type="text" required maxlength="255" #name="ngModel" id="workbasket-name" placeholder="Name"
[(ngModel)]="workbasket.name" name="workbasket.name" (input)="validateInputOverflow(name, 255)">
</mat-form-field>
<div *ngIf="inputOverflowMap.get(name.name)" class="error">{{lengthError}}</div>
<taskana-shared-field-error-display [displayError]="!isFieldValid('workbasket.name')"
[validationTrigger]="this.toggleValidationMap.get('workbasket.name')" errorMessage="* Name is required">
</taskana-shared-field-error-display>
<!-- OWNER -->
<taskana-shared-type-ahead *ngIf="lookupField else ownerInput" isRequired="true" maxlength="128"
#owner="ngModel" name="workbasket.owner" [(ngModel)]="workbasket.owner" placeHolderMessage="Owner"
[validationValue]="this.toggleValidationMap.get('workbasket.owner') "
[displayError]="!isFieldValid('workbasket.owner')" width="100%" (input)="validateInputOverflow(owner, 128)">
<div *ngIf="inputOverflowMap.get(owner.name)" class="error">{{lengthError}}</div>
</taskana-shared-type-ahead>
<div class="workbasket-information__domain-and-type">
<ng-template #ownerInput>
<input type="text" required maxlength="128" #owner="ngModel" class="form-control" id="wb-owner"
placeholder="Owner" [(ngModel)]="workbasket.owner" name="workbasket.owner"
(input)="validateInputOverflow(owner, 128)">
<div *ngIf="inputOverflowMap.get(owner.name)" class="error">{{lengthError}}</div>
<taskana-shared-field-error-display [displayError]="!isFieldValid('workbasket.owner')"
[validationTrigger]="this.toggleValidationMap.get('workbasket.owner')" errorMessage="* Owner is required">
</taskana-shared-field-error-display>
</ng-template>
<!-- DOMAIN -->
<mat-form-field class="workbasket-information__mat-form-field" appearance="outline">
<mat-label>Domain</mat-label>
<label for="workbasket-domain"></label>
<input matInput type="text" disabled id="workbasket-domain" placeholder="Domain"
[(ngModel)]="workbasket.domain" name="classification.domain">
</mat-form-field>
<!-- DESCRIPTION AND TYPE -->
<div class="general__description-and-type">
<!-- TYPE -->
<mat-form-field appearance="outline">
<mat-label>Type</mat-label>
<mat-select [(value)]="this.workbasket.type">
<mat-select-trigger>
<taskana-administration-icon-type [type]='workbasket.type'></taskana-administration-icon-type>
{{allTypes.get(workbasket.type)}}
</mat-select-trigger>
<mat-option *ngFor="let type of allTypes | mapValues | removeEmptyType" value="{{type.key}}">
<taskana-administration-icon-type [type]='type.key' [text]="type.value">
</taskana-administration-icon-type>
</mat-option>
</mat-select>
</mat-form-field>
<!-- TYPE -->
<mat-form-field appearance="outline" style="width: 28%">
<mat-label>Type</mat-label>
<mat-select [(value)]="this.workbasket.type">
<mat-select-trigger>
<taskana-administration-icon-type [type]='workbasket.type'></taskana-administration-icon-type>
{{allTypes.get(workbasket.type)}}
</mat-select-trigger>
<mat-option *ngFor="let type of allTypes | mapValues | removeEmptyType" value="{{type.key}}">
<taskana-administration-icon-type [type]='type.key' [text]="type.value">
</taskana-administration-icon-type>
</mat-option>
</mat-select>
</mat-form-field>
<!-- DESCRIPTION -->
<div style="display: block; width: 68%">
<mat-form-field appearance="outline" style="width: 100%">
<mat-label>Description</mat-label>
<label for="workbasket-description"></label>
<textarea matInput cdkTextareaAutosize cdkAutosizeMinRows="5" cdkAutosizeMaxRows="10" maxlength="255"
id="workbasket-description" placeholder="Description" [(ngModel)]="workbasket.description"
name="workbasket.description" #description="ngModel"
(input)="validateInputOverflow(description, 255)"></textarea>
</mat-form-field>
<mat-error *ngIf="inputOverflowMap.get(description.name)" class="error">{{lengthError}} </mat-error>
</div>
</div>
</div>
<!-- GENERAL SPACER -->
<div class="general__spacer"> </div>
<!-- GENERAL RIGHT COLUMN -->
<div class="general__right-column">
<!-- DOMAIN -->
<mat-form-field appearance="outline">
<mat-label>Domain</mat-label>
<label for="workbasket-domain"></label>
<input matInput type="text" disabled id="workbasket-domain" placeholder="Domain"
[(ngModel)]="workbasket.domain" name="classification.domain">
</mat-form-field>
<!-- ORGANISATIONAL LEVEL 1 -->
<mat-form-field appearance="outline">
<mat-label>OrgLevel 1</mat-label>
<input matInput type="text" #orgLevel1="ngModel" maxlength="255" placeholder="OrgLevel 1"
[(ngModel)]="workbasket.orgLevel1" name="workbasket.orgLevel1"
(input)="validateInputOverflow(orgLevel1, 255)">
</mat-form-field>
<div *ngIf="inputOverflowMap.get(orgLevel1.name)" class="error">{{lengthError}}</div>
<!-- ORGANISATIONAL LEVEL 2 -->
<mat-form-field appearance="outline">
<mat-label>OrgLevel 2</mat-label>
<input matInput type="text" #orgLevel2="ngModel" maxlength="255" placeholder="OrgLevel 2"
[(ngModel)]="workbasket.orgLevel2" name="workbasket.orgLevel2"
(input)="validateInputOverflow(orgLevel2, 255)">
</mat-form-field>
<div *ngIf="inputOverflowMap.get(orgLevel2.name)" class="error">{{lengthError}}</div>
<!-- ORGANISATIONAL LEVEL 3 -->
<mat-form-field appearance="outline">
<mat-label>OrgLevel 3</mat-label>
<input matInput type="text" #orgLevel3="ngModel" maxlength="255" placeholder="OrgLevel 3"
[(ngModel)]="workbasket.orgLevel3" name="workbasket.orgLevel3"
(input)="validateInputOverflow(orgLevel3, 255)">
</mat-form-field>
<div *ngIf="inputOverflowMap.get(orgLevel3.name)" class="error">{{lengthError}}</div>
<!-- ORGANISATIONAL LEVEL 4 -->
<mat-form-field appearance="outline">
<mat-label>OrgLevel 4</mat-label>
<input matInput type="text" #orgLevel4="ngModel" maxlength="255" placeholder="OrgLevel 4"
[(ngModel)]="workbasket.orgLevel4" name="workbasket.orgLevel4"
(input)="validateInputOverflow(orgLevel4, 255)">
</mat-form-field>
<div *ngIf="inputOverflowMap.get(orgLevel4.name)" class="error">{{lengthError}}</div>
</div>
</div>
<!-- DESCRIPTION -->
<mat-form-field appearance="outline">
<mat-label>Description</mat-label>
<label for="workbasket-description"></label>
<textarea matInput cdkTextareaAutosize cdkAutosizeMinRows="1" cdkAutosizeMaxRows="5" maxlength="255"
id="workbasket-description" placeholder="Description" [(ngModel)]="workbasket.description"
name="workbasket.description" #description="ngModel"
(input)="validateInputOverflow(description, 255)"></textarea>
</mat-form-field>
<div *ngIf="inputOverflowMap.get(description.name)" class="error">{{lengthError}}</div>
<!-- OWNER -->
<taskana-shared-type-ahead *ngIf="lookupField else ownerInput" isRequired="true" maxlength="128"
#owner="ngModel" name="workbasket.owner" [(ngModel)]="workbasket.owner" placeHolderMessage="Owner"
[validationValue]="this.toggleValidationMap.get('workbasket.owner') "
[displayError]="!isFieldValid('workbasket.owner')" width="100%" (input)="validateInputOverflow(owner, 128)">
<div *ngIf="inputOverflowMap.get(owner.name)" class="error">{{lengthError}}</div>
</taskana-shared-type-ahead>
<ng-template #ownerInput>
<input type="text" required maxlength="128" #owner="ngModel" class="form-control" id="wb-owner"
placeholder="Owner" [(ngModel)]="workbasket.owner" name="workbasket.owner"
(input)="validateInputOverflow(owner, 128)">
<div *ngIf="inputOverflowMap.get(owner.name)" class="error">{{lengthError}}</div>
<taskana-shared-field-error-display [displayError]="!isFieldValid('workbasket.owner')"
[validationTrigger]="this.toggleValidationMap.get('workbasket.owner')" errorMessage="* Owner is required">
</taskana-shared-field-error-display>
</ng-template>
<!-- ORGASATIONAL LEVELS -->
<h6 class="workbasket-information__subheading" style="margin-top: 65px;"> Organisational Levels </h6>
<mat-divider class="workbasket-information__horizontal-line"> </mat-divider>
<mat-form-field appearance="outline">
<mat-label>OrgLevel 1</mat-label>
<input matInput type="text" #orgLevel1="ngModel" maxlength="255" placeholder="OrgLevel 1"
[(ngModel)]="workbasket.orgLevel1" name="workbasket.orgLevel1"
(input)="validateInputOverflow(orgLevel1, 255)">
</mat-form-field>
<div *ngIf="inputOverflowMap.get(orgLevel1.name)" class="error">{{lengthError}}</div>
<mat-form-field appearance="outline">
<mat-label>OrgLevel 2</mat-label>
<input matInput type="text" #orgLevel2="ngModel" maxlength="255" placeholder="OrgLevel 2"
[(ngModel)]="workbasket.orgLevel2" name="workbasket.orgLevel2"
(input)="validateInputOverflow(orgLevel2, 255)">
</mat-form-field>
<div *ngIf="inputOverflowMap.get(orgLevel2.name)" class="error">{{lengthError}}</div>
<mat-form-field appearance="outline">
<mat-label>OrgLevel 3</mat-label>
<input matInput type="text" #orgLevel3="ngModel" maxlength="255" placeholder="OrgLevel 3"
[(ngModel)]="workbasket.orgLevel3" name="workbasket.orgLevel3"
(input)="validateInputOverflow(orgLevel3, 255)">
</mat-form-field>
<div *ngIf="inputOverflowMap.get(orgLevel3.name)" class="error">{{lengthError}}</div>
<mat-form-field appearance="outline">
<mat-label>OrgLevel 4</mat-label>
<input matInput type="text" #orgLevel4="ngModel" maxlength="255" placeholder="OrgLevel 4"
[(ngModel)]="workbasket.orgLevel4" name="workbasket.orgLevel4"
(input)="validateInputOverflow(orgLevel4, 255)">
</mat-form-field>
<div *ngIf="inputOverflowMap.get(orgLevel4.name)" class="error">{{lengthError}}</div>
<!-- CUSTOM FIELDS -->
<h6 class="workbasket-information__subheading" style="margin-top: 65px;"> Custom Fields </h6>
<mat-divider class="workbasket-information__horizontal-line"> </mat-divider>
<h6 class="subheading"> Custom Fields </h6>
<mat-divider class="horizontal-line"> </mat-divider>
<div *ngFor="let customField of customFields$ | async; let index = index">
<div *ngIf="customField.visible">
<mat-form-field appearance="outline" class="workbasket-information__custom-fields">
<mat-label>{{customField.field}}</mat-label>
<label for='wb-custom-{{index+1}}'></label>
<input matInput type="text" [placeholder]="customField.field"
[(ngModel)]="workbasket[getWorkbasketCustomProperty(index + 1)]" id="wb-custom-{{index+1}}"
name="workbasket[{{getWorkbasketCustomProperty(index + 1)}}]" maxlength="255" #custom="ngModel"
(input)="validateInputOverflow(custom, 255)">
</mat-form-field>
<div *ngIf="inputOverflowMap.get(custom.name)" class="error">{{lengthError}}</div>
<div class="custom-fields">
<div *ngFor="let customField of customFields$ | async; let index = index" class="custom-fields__input">
<mat-form-field appearance="outline" class="custom-fields__form-field">
<mat-label>{{customField.field}}</mat-label>
<label for='wb-custom-{{index+1}}'></label>
<input matInput type="text" [placeholder]="customField.field"
[(ngModel)]="workbasket[getWorkbasketCustomProperty(index + 1)]" id="wb-custom-{{index+1}}"
name="workbasket[{{getWorkbasketCustomProperty(index + 1)}}]" maxlength="255" #custom="ngModel"
(input)="validateInputOverflow(custom, 255)">
</mat-form-field>
<div *ngIf="inputOverflowMap.get(custom.name)" class="error">{{lengthError}}</div>
</div>
</div>
</div>
</ng-form>

View File

@ -2,37 +2,71 @@
height: calc(100vh - 213px);
overflow-y: auto;
}
.workbasket-information {
.form {
padding: 15px;
display: flex;
flex-direction: column;
}
.workbasket-information__subheading {
.subheading {
font-weight: bold;
padding-left: 15px;
margin-bottom: 0;
}
.workbasket-information__horizontal-line {
.horizontal-line {
margin: 5px 5px 25px 5px;
border-top-color: #555;
border-top-width: 1.35px;
}
.workbasket-information__domain-and-type {
.general {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-between;
margin-bottom: 15px;
&__left-column {
display: flex;
flex-direction: column;
flex-wrap: nowrap;
width: 50%;
}
&__right-column {
display: flex;
flex-direction: column;
width: 50%;
}
&__spacer {
display: block;
width: 20px;
}
&__description-and-type {
display: flex;
justify-content: space-between;
}
&__description {
width: 100%;
}
}
.workbasket-information__mat-form-field {
width: 100%;
margin-right: 10px;
}
.custom-fields {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
.dropdown-menu {
min-width: auto;
}
.workbasket-information__custom-fields {
width: 100%;
&__input {
flex: 0 49%;
}
&__form-field {
width: 100%;
}
}

View File

@ -158,7 +158,7 @@ describe('WorkbasketInformationComponent', () => {
});
it('should display custom fields correctly', () => {
const customFields = debugElement.nativeElement.getElementsByClassName('workbasket-information__custom-fields');
const customFields = debugElement.nativeElement.getElementsByClassName('custom-fields__form-field');
expect(customFields.length).toBe(3); //mock data has custom1->4 but engineConfig disables custom3 -> [1,2,4]
});

View File

@ -82,7 +82,8 @@ export class WorkbasketInformationComponent implements OnInit, OnChanges, OnDest
this.customFields$ = this.workbasketsCustomisation$.pipe(
map((customisation) => customisation.information),
getCustomFields(customFieldCount)
getCustomFields(customFieldCount),
map((customFields) => customFields.filter((customisation) => customisation.visible))
);
this.workbasketsCustomisation$.pipe(takeUntil(this.destroy$)).subscribe((workbasketsCustomization) => {
if (workbasketsCustomization.information.owner) {