Skip to content

Commit 3857f75

Browse files
committed
feat: UI adjustments for the table lists
1 parent c0a086c commit 3857f75

5 files changed

Lines changed: 227 additions & 177 deletions

File tree

src/app/features/projects/components/project-list/project-list.component.html

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
1-
<p-toolbar styleClass="mb-4">
1+
<p-toolbar styleClass="mb-4 border-round border-1 surface-border" [style]="{'padding': '0.75rem'}">
22
<ng-template pTemplate="start">
3-
<p-button label="New" icon="pi pi-plus" severity="secondary" class="mr-2" />
4-
<p-button severity="secondary" label="Delete" icon="pi pi-trash" outlined />
3+
<button pButton pRipple label="New" icon="pi pi-plus" class="mr-2 p-button-outlined p-button-primary p-button-sm"></button>
4+
<button pButton pRipple label="Delete" icon="pi pi-trash" class="p-button-outlined p-button-secondary p-button-sm"></button>
55
</ng-template>
66

77
<ng-template pTemplate="end">
8-
<p-button label="Export" icon="pi pi-upload" severity="secondary" (onClick)="exportCSV(dt1)" />
8+
<button pButton pRipple label="Export" icon="pi pi-upload" class="p-button-outlined p-button-secondary p-button-sm"
9+
(onClick)="exportCSV(dt)"></button>
910
</ng-template>
1011
</p-toolbar>
11-
<p-table #dt1 [value]="projects" dataKey="id" [rows]="10" [rowsPerPageOptions]="[10, 25, 50]" [loading]="loading"
12-
[paginator]="true" [(selection)]="selectedProducts"
12+
13+
<p-table #dt [value]="projects" dataKey="id" [rows]="10" [rowsPerPageOptions]="[10, 25, 50]" [loading]="loading"
14+
[paginator]="true" [(selection)]="selectedProducts"
1315
[globalFilterFields]="['name', 'country.name', 'representative.name', 'status']">
1416
<ng-template pTemplate="caption">
1517
<div class="flex">
16-
<p-button label="Clear" [outlined]="true" icon="pi pi-filter-slash" (onClick)="clear(dt1)" />
18+
<p-button label="Clear" [outlined]="true" icon="pi pi-filter-slash" (onClick)="clear(dt)" />
1719
<span class="p-input-icon-left ml-auto">
1820
<i class="pi pi-search"></i>
19-
<input pInputText type="text" [(ngModel)]="searchValue" (input)="onGlobalFilter(dt1, $event)"
21+
<input pInputText type="text" [(ngModel)]="searchValue" (input)="onGlobalFilter(dt, $event)"
2022
placeholder="Search..." />
2123
</span>
2224
</div>
@@ -140,7 +142,7 @@
140142
<td>
141143
<p-button icon="pi pi-pencil" class="mr-2" [rounded]="true" [outlined]="true" />
142144
<p-button icon="pi pi-trash" severity="danger" [rounded]="true" [outlined]="true" />
143-
</td>
145+
</td>
144146
</tr>
145147
</ng-template>
146148
<ng-template pTemplate="emptymessage">
Lines changed: 185 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1,161 +1,198 @@
1-
<div class="grid">
2-
<div class="col-12">
3-
<p-card styleClass="project-tasks-card">
1+
<p-toolbar styleClass="mb-4 border-round border-1 surface-border" [style]="{'padding': '0.75rem'}">
2+
<ng-template pTemplate="left">
3+
<div class="flex flex-wrap gap-2 align-items-center">
4+
<p-dropdown id="projectSelect" [options]="projects" [(ngModel)]="selectedProject" optionLabel="name"
5+
placeholder="Select Project" [showClear]="false" (onChange)="onProjectChange()" [disabled]="isLoadingProjects"
6+
styleClass="p-dropdown-sm" [style]="{ minWidth: '180px' }">
7+
</p-dropdown>
8+
</div>
9+
</ng-template>
410

5-
<p-toolbar styleClass="mb-6 px-3 py-2 border-round border-1 surface-border crud-toolbar">
6-
<ng-template pTemplate="left">
7-
<div class="flex flex-wrap gap-2 align-items-center">
8-
<button pButton pRipple icon="pi pi-refresh" class="p-button-outlined p-button-sm" (click)="refreshTasks()"
9-
pTooltip="Refresh Task List" tooltipPosition="top"
10-
[disabled]="isLoadingTasks || !selectedProject"></button>
11-
</div>
12-
</ng-template>
13-
14-
<ng-template pTemplate="right">
15-
<div class="flex flex-wrap gap-3 align-items-center">
16-
<div class="flex align-items-center">
17-
<p-dropdown id="projectSelect" [options]="projects" [(ngModel)]="selectedProject" optionLabel="name"
18-
placeholder="Select Project" [showClear]="false" (onChange)="onProjectChange()"
19-
[disabled]="isLoadingProjects" styleClass="p-dropdown-sm" [style]="{ minWidth: '180px' }">
20-
</p-dropdown>
21-
<p-progressSpinner *ngIf="isLoadingProjects" styleClass="w-1.5rem h-1.5rem ml-2"
22-
strokeWidth="6"></p-progressSpinner>
23-
</div>
24-
<button pButton pRipple label="Export" icon="pi pi-upload"
25-
class="p-button-outlined p-button-secondary p-button-sm" tooltipPosition="top"
26-
pTooltip="Feature not implemented"></button>
27-
</div>
28-
</ng-template>
29-
</p-toolbar>
30-
31-
<div class="flex flex-wrap align-items-center justify-content-between gap-3 mb-3 px-2">
32-
<h4 class="m-0">{{ selectedProject ? selectedProject.name + ' Tasks' : 'Tasks' }}</h4>
33-
<span class="p-input-icon-left">
34-
<i class="pi pi-search"></i>
35-
<input pInputText type="text" #gbFilter (input)="applyFilterGlobal($event)" placeholder="Search..."
36-
[value]="globalFilterValue" class="w-full sm:w-auto p-inputtext-sm" />
37-
</span>
11+
<ng-template pTemplate="right">
12+
<div class="flex flex-wrap gap-3 align-items-center">
13+
<div class="flex align-items-center">
14+
<p-progressSpinner *ngIf="isLoadingProjects" styleClass="w-1.5rem h-1.5rem ml-2"
15+
strokeWidth="6"></p-progressSpinner>
3816
</div>
17+
<button pButton pRipple label="Export" icon="pi pi-upload"
18+
class="p-button-outlined p-button-secondary p-button-sm"
19+
(onClick)="exportCSV(dt)"></button>
20+
</div>
21+
</ng-template>
22+
</p-toolbar>
3923

40-
<p-table #dt [value]="tasks" dataKey="id" [loading]="isLoadingTasks" [rows]="10" [paginator]="true"
41-
[globalFilterFields]="['title', 'description', 'assignedUserName', 'statusName']"
42-
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} tasks" [showCurrentPageReport]="true"
43-
paginatorPosition="bottom" [rowsPerPageOptions]="[10, 25, 50]" [tableStyle]="{ 'min-width': '70rem' }">
44-
45-
<ng-template pTemplate="header">
46-
<tr>
47-
<th pSortableColumn="title" style="min-width:15rem; background-color: transparent;">Title <p-sortIcon
48-
field="title"></p-sortIcon></th>
49-
<th pSortableColumn="status" style="min-width:10rem; background-color: transparent;">Status <p-sortIcon
50-
field="status"></p-sortIcon></th>
51-
<th pSortableColumn="createdAt" style="min-width:8rem; background-color: transparent;">Created At<p-sortIcon
52-
field="createdAt"></p-sortIcon></th>
53-
<th pSortableColumn="dueDate" style="min-width:8rem; background-color: transparent;">Due Date <p-sortIcon
54-
field="dueDate"></p-sortIcon></th>
55-
<th pSortableColumn="assignedUserName" style="min-width:10rem; background-color: transparent;">Assigned To
56-
<p-sortIcon field="assignedUserName"></p-sortIcon></th>
57-
<th style="width: 8rem; background-color: transparent;" class="text-center">Actions</th>
58-
</tr>
59-
</ng-template>
60-
61-
<ng-template pTemplate="body" let-task let-rowIndex="rowIndex">
62-
<tr>
63-
<td>
64-
<span class="p-column-title">Title</span>
65-
<span class="font-medium block white-space-nowrap overflow-hidden text-overflow-ellipsis"
66-
[pTooltip]="task.title" tooltipPosition="top">{{ task.title }}</span>
67-
</td>
68-
69-
<td>
70-
<span class="p-column-title">Status</span>
71-
<p-tag *ngIf="!(showStatusDropdown && isAssignedToMe(task))"
72-
[value]="getStatusName(task.status)" [severity]="getTagSeverity(task.status)"
73-
styleClass="status-tag"
74-
[pTooltip]="isAssignedToMe(task) ? 'Click status to change' : (isUnassigned(task) ? 'Task is unassigned' : 'Assigned to ' + task.assignedUserName)"
75-
tooltipPosition="top" #tagElement (click)="isAssignedToMe(task) ? showStatusDropdown = !showStatusDropdown : null"
76-
[ngClass]="{'cursor-pointer hover:opacity-80': isAssignedToMe(task)}">
77-
</p-tag>
78-
79-
<p-dropdown *ngIf="showStatusDropdown && isAssignedToMe(task)" [options]="statusOptions" [(ngModel)]="task.status" optionLabel="label"
80-
optionValue="value" (onChange)="onStatusChange(task); showStatusDropdown = !showStatusDropdown" appendTo="body" [showClear]="false">
81-
<ng-template pTemplate="selectedItem">
82-
<p-tag [value]="getStatusName(task.status)" [severity]="getTagSeverity(task.status)"
83-
styleClass="status-tag-option"></p-tag>
84-
</ng-template>
24+
<p-table #dt [value]="tasks" dataKey="id" [loading]="isLoadingTasks" [rows]="10" [paginator]="true"
25+
[globalFilterFields]="['title', 'description', 'assignedUserName', 'statusName']"
26+
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} tasks" [showCurrentPageReport]="true"
27+
paginatorPosition="bottom" [rowsPerPageOptions]="[10, 25, 50]" [tableStyle]="{ 'min-width': '70rem' }">
28+
<ng-template pTemplate="caption">
29+
<div class="flex">
30+
<p-button label="Clear" [outlined]="true" icon="pi pi-filter-slash" (onClick)="clear(dt)" />
31+
<span class="p-input-icon-left ml-auto">
32+
<i class="pi pi-search"></i>
33+
<input pInputText type="text" [(ngModel)]="searchValue" (input)="onGlobalFilter(dt, $event)"
34+
placeholder="Search..." />
35+
</span>
36+
</div>
37+
</ng-template>
38+
<ng-template pTemplate="header">
39+
<tr>
40+
<th style="min-width:15rem">
41+
<div class="flex align-items-center">
42+
Title
43+
<p-columnFilter type="text" field="title" display="menu" />
44+
</div>
45+
</th>
46+
<th style="min-width:10rem">
47+
<div class="flex align-items-center">
48+
Status
49+
<p-columnFilter field="status" matchMode="equals" display="menu">
50+
<ng-template pTemplate="filter" let-value let-filter="filterCallback">
51+
<p-dropdown [ngModel]="value" [options]="statusOptions" (onChange)="filter($event.value)" placeholder="Any">
8552
<ng-template let-option pTemplate="item">
86-
<p-tag [value]="option.label" [severity]="getTagSeverity(option.value)"
87-
styleClass="status-tag-option"></p-tag>
53+
<p-tag [value]="option.label" [severity]="getTagSeverity(option.value)" />
8854
</ng-template>
8955
</p-dropdown>
90-
</td>
56+
</ng-template>
57+
</p-columnFilter>
58+
</div>
59+
</th>
60+
<th style="min-width:8rem">
61+
<div class="flex align-items-center">
62+
Created At
63+
<p-columnFilter type="date" field="createdAt" display="menu" />
64+
</div>
65+
</th>
66+
<th style="min-width:8rem">
67+
<div class="flex align-items-center">
68+
Due Date
69+
<p-columnFilter type="date" field="dueDate" display="menu" />
70+
</div>
71+
</th>
72+
<th style="min-width:10rem">
73+
<div class="flex align-items-center">
74+
Assigned To
75+
<p-columnFilter field="assignedUserName" matchMode="in" display="menu" [showMatchModes]="false"
76+
[showOperator]="false" [showAddButton]="false">
77+
<ng-template pTemplate="header">
78+
<div class="px-3 pt-3 pb-0">
79+
<span class="font-bold">User Filter</span>
80+
</div>
81+
</ng-template>
82+
<ng-template pTemplate="filter" let-value let-filter="filterCallback">
83+
<p-multiSelect [ngModel]="value" [options]="userOptions" placeholder="Any"
84+
(onChange)="filter($event.value)" optionLabel="name">
85+
<ng-template let-option pTemplate="item">
86+
<div class="inline-block vertical-align-middle">
87+
<p-avatar [label]="getInitials(option.name)" shape="circle"
88+
[styleClass]="'mr-2'"></p-avatar>
89+
<span class="ml-1 mt-1">{{ option.name }}</span>
90+
</div>
91+
</ng-template>
92+
</p-multiSelect>
93+
</ng-template>
94+
</p-columnFilter>
95+
</div>
96+
</th>
97+
<th style="width: 8rem" class="text-center"></th>
98+
</tr>
99+
</ng-template>
91100

92-
<td>
93-
<span class="p-column-title">Created At</span>
94-
{{ task.createdAt ? (task.createdAt | date:'MMM d, y') : '-' }}
95-
</td>
101+
<ng-template pTemplate="body" let-task let-rowIndex="rowIndex">
102+
<tr>
103+
<td>
104+
<span class="p-column-title">Title</span>
105+
<span class="font-medium block white-space-nowrap overflow-hidden text-overflow-ellipsis"
106+
[pTooltip]="task.title" tooltipPosition="top">{{ task.title }}</span>
107+
</td>
96108

97-
<td>
98-
<span class="p-column-title">Due Date</span>
99-
{{ task.dueDate ? (task.dueDate | date:'MMM d, y') : '-' }}
100-
</td>
109+
<td>
110+
<span class="p-column-title">Status</span>
111+
<p-tag *ngIf="!(showStatusDropdown && isAssignedToMe(task))" [value]="getStatusName(task.status)"
112+
[severity]="getTagSeverity(task.status)" styleClass="status-tag"
113+
[pTooltip]="isUnassigned(task) ? 'Task is unassigned' : 'Assigned to ' + task.assignedUserName"
114+
tooltipPosition="top" #tagElement
115+
[ngClass]="{'cursor-pointer hover:opacity-80': isAssignedToMe(task)}">
116+
</p-tag>
101117

102-
<td>
103-
<span class="p-column-title">Assigned To</span>
104-
<div *ngIf="!isUnassigned(task)" class="flex align-items-center gap-2">
105-
<p-avatar [label]="getInitials(task.assignedUserName)" shape="circle" size="normal"
106-
[styleClass]="'user-avatar ' + (isAssignedToMe(task) ? 'avatar-me' : 'avatar-other')"
107-
[pTooltip]="task.assignedUserName" tooltipPosition="top">
108-
</p-avatar>
109-
<span class="font-medium">{{ task.assignedUserName }}</span>
110-
</div>
111-
<span *ngIf="isUnassigned(task)" class="text-color-secondary text-sm font-italic">
112-
Unassigned
113-
</span>
114-
</td>
118+
<p-dropdown *ngIf="showStatusDropdown && isAssignedToMe(task)" [options]="statusOptions"
119+
[(ngModel)]="task.status" optionLabel="label" optionValue="value"
120+
(onChange)="onStatusChange(task); showStatusDropdown = !showStatusDropdown" appendTo="body"
121+
[showClear]="false">
122+
<ng-template pTemplate="selectedItem">
123+
<p-tag [value]="getStatusName(task.status)" [severity]="getTagSeverity(task.status)"
124+
styleClass="status-tag-option"></p-tag>
125+
</ng-template>
126+
<ng-template let-option pTemplate="item">
127+
<p-tag [value]="option.label" [severity]="getTagSeverity(option.value)"
128+
styleClass="status-tag-option"></p-tag>
129+
</ng-template>
130+
</p-dropdown>
131+
</td>
115132

116-
<td class="text-center">
117-
<span class="p-column-title">Actions</span>
118-
<div class="flex gap-2 justify-content-center">
119-
<button *ngIf="isUnassigned(task)" pButton pRipple icon="pi pi-user-plus" class="action-button"
120-
severity="success" [outlined]="true" [rounded]="true" (click)="assignToMe(task)"
121-
pTooltip="Assign to Me" tooltipPosition="top">
122-
</button>
123-
<button *ngIf="isAssignedToMe(task)" pButton pRipple icon="pi pi-user-minus" class="action-button"
124-
severity="warning" [outlined]="true" [rounded]="true" (click)="unassignTask(task)"
125-
pTooltip="Unassign Task" tooltipPosition="top">
126-
</button>
127-
<button *ngIf="!isUnassigned(task) && !isAssignedToMe(task)" pButton pRipple icon="pi pi-user"
128-
class="action-button" severity="secondary" [outlined]="true" [rounded]="true" tooltipPosition="top"
129-
disabled>
130-
</button>
131-
</div>
132-
</td>
133-
</tr>
134-
</ng-template>
133+
<td>
134+
<span class="p-column-title">Created At</span>
135+
{{ task.createdAt ? (task.createdAt | date:'MMM d, y') : '-' }}
136+
</td>
135137

136-
<ng-template pTemplate="emptymessage" let-columns>
137-
<tr>
138-
<td [attr.colspan]="columns?.length">
139-
<div class="text-center p-4">
140-
<i class="pi pi-inbox text-4xl text-color-secondary mb-3"></i>
141-
<p>{{ selectedProject ? 'No tasks found for this project.' : 'Please select a project.' }}</p>
142-
</div>
143-
</td>
144-
</tr>
145-
</ng-template>
138+
<td>
139+
<span class="p-column-title">Due Date</span>
140+
{{ task.dueDate ? (task.dueDate | date:'MMM d, y') : '-' }}
141+
</td>
142+
143+
<td>
144+
<span class="p-column-title">Assigned To</span>
145+
<div *ngIf="!isUnassigned(task)" class="flex align-items-center gap-2">
146+
<p-avatar [label]="getInitials(task.assignedUserName)" shape="circle" size="normal"
147+
[styleClass]="'user-avatar ' + (isAssignedToMe(task) ? 'avatar-me' : 'avatar-other')"
148+
[pTooltip]="task.assignedUserName" tooltipPosition="top">
149+
</p-avatar>
150+
<span class="font-medium">{{ task.assignedUserName }}</span>
151+
</div>
152+
<span *ngIf="isUnassigned(task)" class="text-color-secondary text-sm font-italic">
153+
Unassigned
154+
</span>
155+
</td>
156+
157+
<td class="text-center">
158+
<span class="p-column-title"></span>
159+
<div class="flex gap-2 justify-content-center">
160+
<button *ngIf="isUnassigned(task)" pButton pRipple icon="pi pi-user-plus" class="action-button"
161+
severity="success" [outlined]="true" [rounded]="true" (click)="assignToMe(task); showStatusDropdown = !showStatusDropdown" pTooltip="Assign to Me"
162+
tooltipPosition="top">
163+
</button>
164+
<button *ngIf="isAssignedToMe(task)" pButton pRipple icon="pi pi-user-minus" class="action-button"
165+
severity="warning" [outlined]="true" [rounded]="true" (click)="unassignTask(task); showStatusDropdown = !showStatusDropdown" pTooltip="Unassign Task"
166+
tooltipPosition="top">
167+
</button>
168+
<button *ngIf="!isUnassigned(task) && !isAssignedToMe(task)" pButton pRipple icon="pi pi-user"
169+
class="action-button" severity="secondary" [outlined]="true" [rounded]="true" tooltipPosition="top"
170+
disabled>
171+
</button>
172+
</div>
173+
</td>
174+
</tr>
175+
</ng-template>
146176

147-
<ng-template pTemplate="loadingbody" let-columns>
148-
<tr *ngFor="let item of [1,2,3,4,5,6]" class="p-datatable-loading-row">
149-
<td><p-skeleton height="1.5rem" styleClass="mb-2"></p-skeleton></td>
150-
<td><p-skeleton height="1.5rem" styleClass="mb-2"></p-skeleton></td>
151-
<td><p-skeleton height="1.5rem" styleClass="mb-2"></p-skeleton></td>
152-
<td><p-skeleton height="1.5rem" styleClass="mb-2"></p-skeleton></td>
153-
<td><p-skeleton height="1.5rem" styleClass="mb-2"></p-skeleton></td>
154-
<td><p-skeleton height="1.5rem" styleClass="mb-2"></p-skeleton></td>
155-
</tr>
156-
</ng-template>
177+
<ng-template pTemplate="emptymessage" let-columns>
178+
<tr>
179+
<td [attr.colspan]="6">
180+
<div class="text-center p-4">
181+
<i class="pi pi-inbox text-4xl text-color-secondary mb-3"></i>
182+
<p>{{ selectedProject ? 'No tasks found for this project.' : 'Please select a project.' }}</p>
183+
</div>
184+
</td>
185+
</tr>
186+
</ng-template>
157187

158-
</p-table>
159-
</p-card>
160-
</div>
161-
</div>
188+
<ng-template pTemplate="loadingbody" let-columns>
189+
<tr *ngFor="let item of [1,2,3]" class="p-datatable-loading-row">
190+
<td><p-skeleton height="1.5rem" styleClass="mb-2"></p-skeleton></td>
191+
<td><p-skeleton height="1.5rem" styleClass="mb-2"></p-skeleton></td>
192+
<td><p-skeleton height="1.5rem" styleClass="mb-2"></p-skeleton></td>
193+
<td><p-skeleton height="1.5rem" styleClass="mb-2"></p-skeleton></td>
194+
<td><p-skeleton height="1.5rem" styleClass="mb-2"></p-skeleton></td>
195+
<td><p-skeleton height="1.5rem" styleClass="mb-2"></p-skeleton></td>
196+
</tr>
197+
</ng-template>
198+
</p-table>

0 commit comments

Comments
 (0)