TSK-1592: Renamed and refactored task-details component with Material (#1552)

* TSK-1592: Renamed and refactored task-details component with Material

* TSK-1592: fix task name overflowing

* TSK-1592: Using grid for workplace overview instead of flex

Co-authored-by: Chi Nguyen <c.nguyen.prog@gmail.com>
This commit is contained in:
Sofie Hofmann 2021-04-20 12:03:08 +02:00 committed by GitHub
parent b54a7e8216
commit 9247e70092
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 223 additions and 145 deletions

View File

@ -5,7 +5,7 @@
<router-outlet name="master"> </router-outlet>
</div>
<div class="vertical-right-divider"></div>
<div class="vertical-right-divider workplace-overview__divider"></div>
<!-- TASK DETAILS-->
<div *ngIf="showDetail" class="workplace-overview__task-details">

View File

@ -1,21 +1,25 @@
@import 'src/theme/_colors.scss';
.workplace-overview {
display: flex;
display: grid;
grid-template-rows: 1fr;
grid-template-columns: 500px 1px 1fr;
&__task-list {
width: 500px;
min-width: 500px;
max-width: 500px;
grid-area: 1/1;
}
&__divider {
grid-area: 1/2;
}
&__task-details {
display: flex;
flex-grow: 1;
grid-area: 1/3;
}
&__empty-page {
flex-grow: 1;
grid-area: 1/3;
display: flex;
flex-direction: column;
justify-content: center;

View File

@ -117,7 +117,7 @@ export const notifications = new Map<NOTIFICATION_TYPES, Pair<string, string>>([
\n The uploaded file probably exceeded the maximum file size of 10 MB.`
}
],
// taskdetails.component
// task-details.component
[NOTIFICATION_TYPES.FETCH_ERR_3, { left: '', right: 'An error occurred while fetching the task' }],
// workbasket-details.component
[NOTIFICATION_TYPES.FETCH_ERR_4, { left: '', right: 'An error occurred while fetching the workbasket' }],
@ -176,9 +176,9 @@ export const notifications = new Map<NOTIFICATION_TYPES, Pair<string, string>>([
right: 'Request time exceeded'
}
],
// taskdetails.component
// task-details.component
[NOTIFICATION_TYPES.FETCH_ERR_7, { left: 'An error occurred while fetching the task', right: '' }],
// taskdetails.component
// task-details.component
[NOTIFICATION_TYPES.DELETE_ERR_2, { left: 'An error occurred while deleting the task', right: '' }],
// ALERTS
@ -199,7 +199,7 @@ export const notifications = new Map<NOTIFICATION_TYPES, Pair<string, string>>([
// access-items.component
// workbasket.distribution-targets.component
// workbasket-information.component
// taskdetails.component
// task-details.component
[NOTIFICATION_TYPES.INFO_ALERT, { left: '', right: 'Information restored' }],
// classification-details.component
[
@ -238,13 +238,13 @@ export const notifications = new Map<NOTIFICATION_TYPES, Pair<string, string>>([
[NOTIFICATION_TYPES.WARNING_ALERT, { left: '', right: 'There are some empty fields which are required.' }],
// forms-validator.service x2
[NOTIFICATION_TYPES.WARNING_ALERT_2, { left: '', right: 'The {owner} introduced is not valid.' }],
// taskdetails.component
// task-details.component
[NOTIFICATION_TYPES.DANGER_ALERT, { left: '', right: 'There was an error while updating.' }],
// taskdetails.component
// task-details.component
[NOTIFICATION_TYPES.SUCCESS_ALERT_13, { left: '', right: 'Task {taskId} was created successfully.' }],
// taskdetails.component
// task-details.component
[NOTIFICATION_TYPES.SUCCESS_ALERT_14, { left: '', right: 'Updating was successful.' }],
// taskdetails.component
// task-details.component
[NOTIFICATION_TYPES.DANGER_ALERT_2, { left: '', right: 'There was an error while creating a new task.' }],
// task-master.component
[NOTIFICATION_TYPES.INFO_ALERT_2, { left: '', right: 'The selected Workbasket is empty!' }],

View File

@ -0,0 +1,93 @@
<div class="task-details" *ngIf="task && !requestInProgress">
<div class="task-details__header">
<!-- ACTION BUTTONS -->
<div class="task-details__action-buttons">
<!-- BADGE MESSAGE -->
<div style="max-width: calc(100% - 312px); margin-right: 4px;">
<span *ngIf="!task.taskId" class="task-details__badge-message"> &nbsp; Creating Task &nbsp; </span>
</div>
<div>
<button mat-stroked-button class="task-details__button--primary" matTooltip="Save Task" (click)="toggleFormValidation = !toggleFormValidation">
<span> Save </span>
<mat-icon>save</mat-icon>
</button>
<!-- TODO: delete ngIf when introducing workbasket store -->
<button mat-stroked-button class="task-details__button--secondary" *ngIf="currentId != 'new-task'"
matTooltip="Undo changes" (click)="resetTask()">
<mat-icon class="task-details__icon--aquamarine">undo</mat-icon>
<span> Undo changes </span>
</button>
<button mat-stroked-button [matMenuTriggerFor]="buttonMenu" style="height: 37px; top: 1px;"
matTooltip="More actions" class="task-details__button--secondary">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #buttonMenu="matMenu">
<button mat-menu-item class="task-details__button--secondary" *ngIf="currentId != 'new-task'"
matTooltip="Open Task to work on it" (click)="openTask()">
<mat-icon class="task-details__icon--aquamarine">open_in_new</mat-icon>
<span> Open </span>
</button>
<button mat-menu-item class="task-details__button--secondary" *ngIf="currentId != 'new-task'"
matTooltip="Save Task" (click)="deleteTask()">
<mat-icon class="task-details__icon--red">delete</mat-icon>
<span> Delete </span>
</button>
<button mat-menu-item class="task-details__button--secondary" matTooltip="Close Task" (click)="backClicked()">
<mat-icon>close</mat-icon>
<span> Close </span>
</button>
</mat-menu>
</div>
</div>
<!-- TITLE -->
<h4 class="task-details__task-name"> {{task.name}} </h4>
</div>
<!-- TABS -->
<div class="task-details__tab-group-wrapper">
<mat-tab-group animationDuration="0ms">
<mat-tab label="Information">
<div class="task-details__tab-wrapper">
<taskana-task-information [task]="task" [saveToggleTriggered]="toggleFormValidation"
(formValid)="onSave()"></taskana-task-information>
</div>
</mat-tab>
<mat-tab label="Status Details">
<div class="task-details__tab-wrapper">
<taskana-task-status-details [task]="task"></taskana-task-status-details>
</div>
</mat-tab>
<mat-tab label="Custom Fields">
<div class="task-details__tab-wrapper">
<taskana-task-custom-fields [task]="task"></taskana-task-custom-fields>
</div>
</mat-tab>
<mat-tab label="Custom Attributes">
<div class="task-details__tab-wrapper">
<taskana-task-attribute-value [attributes]="task.customAttributes"></taskana-task-attribute-value>
</div>
</mat-tab>
<mat-tab label="Callback Information">
<div class="task-details__tab-wrapper">
<taskana-task-attribute-value [attributes]="task.callbackInfo" [callbackInfo]="true"></taskana-task-attribute-value>
</div>
</mat-tab>
</mat-tab-group>
</div>
</div>

View File

@ -0,0 +1,95 @@
@import '../../../../theme/colors';
:host {
flex-grow: 1;
}
.task-details {
&__header {
padding: 8px 8px 0 8px;
height: 88px;
width: 100%;
display: grid;
grid-template-rows: 1fr 1fr;
grid-template-columns: 1fr ;
}
&__badge-message {
font-size: 1.1rem;
background-color: $transparent-grey;
border-radius: 4px;
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
position: relative;
top: 4px;
}
&__action-buttons {
grid-area: 1/1;
display: flex;
flex-direction: row;
justify-content: space-between;
}
&__button--primary {
background-color: $aquamarine;
color: white;
margin-right: 4px;
min-width: 1%;
}
&__button--secondary {
margin-right: 4px;
min-width: 1%;
color: #555;
}
&__icon--aquamarine {
color: $aquamarine;
}
&__icon--red {
color: $invalid;
}
&__task-name {
font-size: 1.5rem;
padding: 0 0.5rem 0.5rem 0.5rem;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
grid-area: 2/1;
grid-column-start: 1;
grid-column-end: 2;
}
&__tab-group-wrapper {
width: 100%;
height: 100%;
}
&__tab-wrapper {
padding: 12px;
}
}
::ng-deep .mat-tab-body-wrapper {
height: 100%;
max-height: calc(100vh - 182px);
}
::ng-deep
.task-details__tab-group-wrapper
> .mat-tab-group
> .mat-tab-header
> .mat-tab-label-container
> .mat-tab-list
> .mat-tab-labels
> .mat-tab-label {
min-width: 0 !important;
height: 36px !important;
}

View File

@ -12,7 +12,7 @@ import { TaskService } from '../../services/task.service';
import { TaskAttributeValueComponent } from '../task-attribute-value/task-attribute-value.component';
import { TaskCustomFieldsComponent } from '../task-custom-fields/task-custom-fields.component';
import { TaskInformationComponent } from '../task-information/task-information.component';
import { TaskdetailsComponent } from './taskdetails.component';
import { TaskDetailsComponent } from './task-details.component';
import { NotificationService } from '../../../shared/services/notifications/notification.service';
@Component({
@ -24,14 +24,14 @@ class DummyDetailComponent {}
const routes: Routes = [{ path: 'workplace/taskdetail/:id', component: DummyDetailComponent }];
// TODO: test pending to test. Failing random
xdescribe('TaskdetailsComponent', () => {
let component: TaskdetailsComponent;
let fixture: ComponentFixture<TaskdetailsComponent>;
xdescribe('TaskDetailsComponent', () => {
let component: TaskDetailsComponent;
let fixture: ComponentFixture<TaskDetailsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
TaskdetailsComponent,
TaskDetailsComponent,
SpinnerComponent,
TaskAttributeValueComponent,
TaskCustomFieldsComponent,
@ -44,7 +44,7 @@ xdescribe('TaskdetailsComponent', () => {
}));
beforeEach(() => {
fixture = TestBed.createComponent(TaskdetailsComponent);
fixture = TestBed.createComponent(TaskDetailsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

View File

@ -16,10 +16,10 @@ import { takeUntil } from 'rxjs/operators';
@Component({
selector: 'taskana-task-details',
templateUrl: './taskdetails.component.html',
styleUrls: ['./taskdetails.component.scss']
templateUrl: './task-details.component.html',
styleUrls: ['./task-details.component.scss']
})
export class TaskdetailsComponent implements OnInit, OnDestroy {
export class TaskDetailsComponent implements OnInit, OnDestroy {
task: Task;
taskClone: Task;
requestInProgress = false;
@ -157,7 +157,7 @@ export class TaskdetailsComponent implements OnInit, OnDestroy {
this.destroy$.complete();
}
private onSave() {
onSave() {
this.currentId === 'new-task' ? this.createTask() : this.updateTask();
}

View File

@ -21,7 +21,6 @@ import { Classification } from '../../../shared/models/classification';
import { TasksCustomisation } from '../../../shared/models/customisation';
import { takeUntil } from 'rxjs/operators';
import { AccessIdDefinition } from '../../../shared/models/access-id';
import { TaskanaDate } from '../../../shared/util/taskana.date';
@Component({
selector: 'taskana-task-information',

View File

@ -39,7 +39,7 @@
}
}
::ng-deep .mat-tab-labels {
::ng-deep .task-list-toolbar > .mat-tab-group > .mat-tab-header > .mat-tab-label-container > .mat-tab-list > .mat-tab-labels {
background-color: $light-grey;
}

View File

@ -16,7 +16,7 @@
<!-- TASK INFORMATION -->
<div class="task-list__task-info">
<p> <b>{{task.name}}</b>, <i *ngIf="task.owner">{{task.owner}} </i> </p>
<p> <b>{{task.name}}</b>,&nbsp;<i *ngIf="task.owner">{{task.owner}} </i> </p>
<p> State: {{task.state}} </p>
<p> Due: {{task.due | dateTimeZone }} </p>
</div>

View File

@ -1,83 +0,0 @@
<div class="panel panel-default" *ngIf="task && !requestInProgress">
<!--Buttonbar-->
<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="material-icons md-20 blue">arrow_back</span>
</button>
</div>
<div class="pull-right btn-group">
<button type="button" (click)="toggleFormValidation = !toggleFormValidation" class="btn btn-default btn-primary"
data-toggle="tooltip" title="Save">
<span class="material-icons md-20 white">save</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="material-icons md-20 blue">open_in_new</span>
</button>
<button type="button" (click)="resetTask()" class="btn btn-default" data-toggle="tooltip" title="Undo Changes">
<span class="material-icons md-20 blue">undo</span>
</button>
<button type="button" title="Delete Task" class="btn btn-default remove" (click)="deleteTask()">
<span class="material-icons md-20 red">delete</span>
</button>
</ng-container>
</div>
<h4 class="panel-header">{{task.name}}&nbsp;
<span *ngIf="!task.taskId" class="badge warning"> {{'Creating Task'}}</span>
</h4>
</div>
<!--Accordion Fields for Sectioned View of Data-->
<div class="panel-body">
<accordion *ngIf="task && !requestInProgress">
<!--Information-->
<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 material-icons md-20 blue">{{accordion1State ?
'expand_more' : 'expand_less'}}</span>
</button>
<taskana-task-information [task]="task" [saveToggleTriggered]="toggleFormValidation"
(formValid)="onSave()"></taskana-task-information>
</accordion-group>
<!--Status Details-->
<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 material-icons md-20 blue">{{accordion2State ?
'expand_more' : 'expand_less'}}</span>
</button>
<taskana-task-status-details [task]="task"></taskana-task-status-details>
</accordion-group>
<!--Custom Fields-->
<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 material-icons md-20 blue">{{accordion3State ?
'expand_more' : 'expand_less'}}</span>
</button>
<taskana-task-custom-fields [task]="task"></taskana-task-custom-fields>
</accordion-group>
<!--Custom Attributes-->
<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 material-icons md-20 blue">{{accordion4State ?
'expand_more' : 'expand_less'}}</span>
</button>
<taskana-task-attribute-value [attributes]="task.customAttributes"></taskana-task-attribute-value>
</accordion-group>
<!--Callback Information-->
<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 material-icons md-20 blue">{{accordion5State ?
'expand_more' : 'expand_less'}}</span>
</button>
<taskana-task-attribute-value [attributes]="task.callbackInfo"
[callbackInfo]="true"></taskana-task-attribute-value>
</accordion-group>
</accordion>
</div>
</div>

View File

@ -1,30 +0,0 @@
@import '../../../../theme/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

@ -2,7 +2,7 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { MasterAndDetailComponent } from '../shared/components/master-and-detail/master-and-detail.component';
import { TaskProcessingComponent } from './components/task-processing/task-processing.component';
import { TaskdetailsComponent } from './components/taskdetails/taskdetails.component';
import { TaskDetailsComponent } from './components/task-details/task-details.component';
import { TaskMasterComponent } from './components/task-master/task-master.component';
const routes: Routes = [
@ -17,7 +17,7 @@ const routes: Routes = [
},
{
path: 'taskdetail/:id',
component: TaskdetailsComponent,
component: TaskDetailsComponent,
outlet: 'detail'
},
{

View File

@ -12,7 +12,7 @@ import { WorkplaceRoutingModule } from './workplace-routing.module';
import { TaskListToolbarComponent } from './components/task-list-toolbar/task-list-toolbar.component';
import { TaskMasterComponent } from './components/task-master/task-master.component';
import { TaskdetailsComponent } from './components/taskdetails/taskdetails.component';
import { TaskDetailsComponent } from './components/task-details/task-details.component';
import { TaskAttributeValueComponent } from './components/task-attribute-value/task-attribute-value.component';
import { TaskCustomFieldsComponent } from './components/task-custom-fields/task-custom-fields.component';
import { TaskInformationComponent } from './components/task-information/task-information.component';
@ -57,7 +57,7 @@ const MODULES = [
const DECLARATIONS = [
TaskListToolbarComponent,
TaskMasterComponent,
TaskdetailsComponent,
TaskDetailsComponent,
TaskInformationComponent,
TaskAttributeValueComponent,
TaskCustomFieldsComponent,