55 < div class ="search-header ">
66 < div class ="search-header__title ">
77 < h2 > Search & Filters</ h2 >
8- < p > Find users in projects , projects for a user, and user/unassigned tasks.</ p >
8+ < p > Find project members , projects for a selected user, and tasks across one or all projects .</ p >
99 < div class ="search-header__meta " *ngIf ="selectedProjectId ">
1010 < span class ="meta-pill ">
1111 < i class ="pi pi-folder "> </ i >
@@ -22,7 +22,7 @@ <h2>Search & Filters</h2>
2222
2323 < div class ="search-kpis ">
2424 < article class ="kpi-card "> < div class ="kpi-card__shell kpi-card__shell--info "> < div class ="kpi-card__head "> < span class ="kpi-card__label "> Users In Project</ span > < span class ="kpi-card__tag "> People</ span > </ div > < span class ="kpi-card__value "> {{ usersInProjectCount }}</ span > </ div > </ article >
25- < article class ="kpi-card "> < div class ="kpi-card__shell kpi-card__shell--neutral "> < div class ="kpi-card__head "> < span class ="kpi-card__label "> Projects For User </ span > < span class ="kpi-card__tag "> Scope</ span > </ div > < span class ="kpi-card__value "> {{ projectsForUserCount }}</ span > </ div > </ article >
25+ < article class ="kpi-card "> < div class ="kpi-card__shell kpi-card__shell--neutral "> < div class ="kpi-card__head "> < span class ="kpi-card__label "> Projects Matched </ span > < span class ="kpi-card__tag "> Scope</ span > </ div > < span class ="kpi-card__value "> {{ projectsForUserCount }}</ span > </ div > </ article >
2626 < article class ="kpi-card "> < div class ="kpi-card__shell kpi-card__shell--accent "> < div class ="kpi-card__head "> < span class ="kpi-card__label "> Filtered Tasks</ span > < span class ="kpi-card__tag "> Results</ span > </ div > < span class ="kpi-card__value "> {{ filteredTasks.length }}</ span > </ div > </ article >
2727 < article class ="kpi-card "> < div class ="kpi-card__shell kpi-card__shell--done "> < div class ="kpi-card__head "> < span class ="kpi-card__label "> Completed</ span > < span class ="kpi-card__tag "> Done</ span > </ div > < span class ="kpi-card__value "> {{ completedTasksCount }}</ span > </ div > </ article >
2828 < article class ="kpi-card "> < div class ="kpi-card__shell kpi-card__shell--warning "> < div class ="kpi-card__head "> < span class ="kpi-card__label "> Unassigned</ span > < span class ="kpi-card__tag "> Risk</ span > </ div > < span class ="kpi-card__value "> {{ unassignedTasksCount }}</ span > </ div > </ article >
@@ -35,22 +35,38 @@ <h2>Search & Filters</h2>
3535 < i class ="pi pi-sliders-h "> </ i >
3636 < span > Filter Workspace</ span >
3737 </ div >
38+ < button
39+ pButton
40+ type ="button "
41+ icon ="pi pi-filter-slash "
42+ label ="Reset All Filters "
43+ class ="p-button-text p-button-sm "
44+ (click) ="resetAllFilters() ">
45+ </ button >
3846 </ div >
3947
4048 < div class ="search-controls ">
4149 < section class ="control-section ">
4250 < h4 > People Context</ h4 >
4351 < div class ="control-section__grid ">
4452 < div class ="control-group ">
45- < label for ="projectId "> Project</ label >
53+ < label for ="projectId " class ="control-group__label-with-help ">
54+ < span > Project</ span >
55+ < i
56+ *ngIf ="projectFilterDisableReason as reason "
57+ class ="pi pi-question-circle control-group__help-icon "
58+ [pTooltip] ="reason "
59+ tooltipPosition ="top ">
60+ </ i >
61+ </ label >
4662 < p-dropdown
4763 inputId ="projectId "
48- [options] ="projects "
64+ [options] ="projectOptions "
4965 optionLabel ="name "
5066 optionValue ="id "
5167 [ngModel] ="selectedProjectId "
5268 [disabled] ="isLoading || projects.length === 0 "
53- placeholder ="Select project "
69+ placeholder ="All Projects "
5470 [filter] ="true "
5571 filterBy ="name "
5672 [appendTo] ="'body' "
@@ -72,15 +88,28 @@ <h4>People Context</h4>
7288 </ div >
7389
7490 < div class ="control-group ">
75- < label for ="userId "> User In Project</ label >
91+ < label for ="userId " class ="control-group__label-with-help ">
92+ < span > Find Projects For User</ span >
93+ < i
94+ class ="pi pi-info-circle control-group__help-icon "
95+ pTooltip ="Shows projects where the selected user is a member. "
96+ tooltipPosition ="top ">
97+ </ i >
98+ < i
99+ *ngIf ="memberContextDisableReason as reason "
100+ class ="pi pi-question-circle control-group__help-icon "
101+ [pTooltip] ="reason "
102+ tooltipPosition ="top ">
103+ </ i >
104+ </ label >
76105 < p-dropdown
77106 inputId ="userId "
78- [options] ="filteredProjectMembers "
107+ [options] ="memberContextOptions "
79108 optionLabel ="displayName "
80109 optionValue ="userId "
81110 [ngModel] ="selectedUserId "
82- [disabled] ="isLoading || filteredProjectMembers.length === 0 "
83- placeholder =" Select user "
111+ [disabled] ="isLoading || !isUserSelectionEnabled "
112+ [ placeholder] =" isUserSelectionEnabled ? ' Select user' : 'No users available' "
84113 [filter] ="true "
85114 filterBy ="displayName,email "
86115 [appendTo] ="'body' "
@@ -102,7 +131,32 @@ <h4>Task Filters</h4>
102131 optionValue ="value "
103132 [ngModel] ="taskOwnershipFilter "
104133 [appendTo] ="'body' "
105- (onChange) ="taskOwnershipFilter = $event.value; onTaskFiltersChanged() ">
134+ (onChange) ="onTaskOwnershipFilterChange($event.value) ">
135+ </ p-dropdown >
136+ </ div >
137+
138+ < div class ="control-group ">
139+ < label for ="taskAssignee " class ="control-group__label-with-help ">
140+ < span > Assigned User</ span >
141+ < i
142+ *ngIf ="taskAssigneeDisableReason as reason "
143+ class ="pi pi-question-circle control-group__help-icon "
144+ [pTooltip] ="reason "
145+ tooltipPosition ="top ">
146+ </ i >
147+ </ label >
148+ < p-dropdown
149+ inputId ="taskAssignee "
150+ [options] ="assigneeOptions "
151+ optionLabel ="label "
152+ optionValue ="value "
153+ [ngModel] ="taskAssigneeUserId "
154+ [disabled] ="!isTaskAssigneeSelectionEnabled || assigneeOptions.length === 0 "
155+ [placeholder] ="isTaskAssigneeSelectionEnabled ? 'Any assigned user' : 'Enable Assigned ownership' "
156+ [filter] ="true "
157+ filterBy ="label "
158+ [appendTo] ="'body' "
159+ (onChange) ="taskAssigneeUserId = $event.value; onTaskFiltersChanged() ">
106160 </ p-dropdown >
107161 </ div >
108162
@@ -120,13 +174,96 @@ <h4>Task Filters</h4>
120174 </ div >
121175
122176 < div class ="control-group ">
123- < label for ="search "> Task Search</ label >
177+ < label for ="taskCreatedBy "> Created By</ label >
178+ < p-dropdown
179+ inputId ="taskCreatedBy "
180+ [options] ="actorOptions "
181+ optionLabel ="label "
182+ optionValue ="value "
183+ [ngModel] ="taskCreatedByUserId "
184+ [showClear] ="true "
185+ placeholder ="All creators "
186+ [filter] ="true "
187+ filterBy ="label "
188+ [appendTo] ="'body' "
189+ (onChange) ="taskCreatedByUserId = $event.value; onTaskFiltersChanged() ">
190+ </ p-dropdown >
191+ </ div >
192+
193+ < div class ="control-group ">
194+ < label for ="taskUpdatedBy "> Last Updated By</ label >
195+ < p-dropdown
196+ inputId ="taskUpdatedBy "
197+ [options] ="actorOptions "
198+ optionLabel ="label "
199+ optionValue ="value "
200+ [ngModel] ="taskUpdatedByUserId "
201+ [showClear] ="true "
202+ placeholder ="All updaters "
203+ [filter] ="true "
204+ filterBy ="label "
205+ [appendTo] ="'body' "
206+ (onChange) ="taskUpdatedByUserId = $event.value; onTaskFiltersChanged() ">
207+ </ p-dropdown >
208+ </ div >
209+
210+ < div class ="control-group ">
211+ < label for ="search "> Task Title</ label >
124212 < input
125213 id ="search "
126214 pInputText
127- [ngModel] ="taskSearch "
128- (ngModelChange) ="taskSearch = $event; onTaskFiltersChanged() "
129- placeholder ="Title or description " />
215+ [ngModel] ="taskSearchTitle "
216+ (ngModelChange) ="taskSearchTitle = $event; onTaskFiltersChanged() "
217+ placeholder ="Search task title " />
218+ </ div >
219+ </ div >
220+ </ section >
221+
222+ < section class ="control-section ">
223+ < h4 > Project Filters</ h4 >
224+ < div class ="control-section__grid ">
225+ < div class ="control-group ">
226+ < label for ="projectCreatedBy "> Created By</ label >
227+ < p-dropdown
228+ inputId ="projectCreatedBy "
229+ [options] ="actorOptions "
230+ optionLabel ="label "
231+ optionValue ="value "
232+ [ngModel] ="projectCreatedByUserId "
233+ [showClear] ="true "
234+ placeholder ="All creators "
235+ [filter] ="true "
236+ filterBy ="label "
237+ [appendTo] ="'body' "
238+ (onChange) ="projectCreatedByUserId = $event.value; onProjectFiltersChanged() ">
239+ </ p-dropdown >
240+ </ div >
241+
242+ < div class ="control-group ">
243+ < label for ="projectUpdatedBy "> Last Updated By</ label >
244+ < p-dropdown
245+ inputId ="projectUpdatedBy "
246+ [options] ="actorOptions "
247+ optionLabel ="label "
248+ optionValue ="value "
249+ [ngModel] ="projectUpdatedByUserId "
250+ [showClear] ="true "
251+ placeholder ="All updaters "
252+ [filter] ="true "
253+ filterBy ="label "
254+ [appendTo] ="'body' "
255+ (onChange) ="projectUpdatedByUserId = $event.value; onProjectFiltersChanged() ">
256+ </ p-dropdown >
257+ </ div >
258+
259+ < div class ="control-group ">
260+ < label for ="projectSearchTitle "> Project Title</ label >
261+ < input
262+ id ="projectSearchTitle "
263+ pInputText
264+ [ngModel] ="projectSearchTitle "
265+ (ngModelChange) ="projectSearchTitle = $event; onProjectFiltersChanged() "
266+ placeholder ="Search project title " />
130267 </ div >
131268 </ div >
132269 </ section >
@@ -137,8 +274,8 @@ <h4>Task Filters</h4>
137274 < div class ="results-grid ">
138275 < p-card styleClass ="results-card ">
139276 < div class ="results-card__title ">
140- < h3 > Users In Project </ h3 >
141- < p > Members available in the selected project. </ p >
277+ < h3 > {{ usersResultTitle }} </ h3 >
278+ < p > {{ usersResultSubtitle }} </ p >
142279 </ div >
143280 < div class ="results-card__body ">
144281 < ul class ="simple-list ">
@@ -159,20 +296,30 @@ <h3>Users In Project</h3>
159296
160297 < p-card styleClass ="results-card ">
161298 < div class ="results-card__title ">
162- < h3 > Projects For User</ h3 >
163- < p *ngIf ="selectedUserId; else projectsHint "> Showing projects for {{ selectedUserName }}.</ p >
299+ < h3 > Projects For Selected User</ h3 >
300+ < p *ngIf ="selectedUserId; else projectsHint "> Showing projects where < strong > {{ selectedUserName }}</ strong > is a member .</ p >
164301 < ng-template #projectsHint >
165- < p > Select a user to list matching projects .</ p >
302+ < p > Select “Find Projects For User” to narrow this list by a specific member .</ p >
166303 </ ng-template >
167304 </ div >
168305 < div class ="results-card__body ">
169306 < ul class ="simple-list ">
170- < li *ngFor ="let project of userProjects " class ="project-list-item ">
171- < div class ="simple-list__meta simple-list__meta--top ">
172- < i class ="pi pi-folder text-color-secondary "> </ i >
173- < div class ="simple-list__text ">
174- < span > {{ project.name }}</ span >
307+ < li *ngFor ="let project of filteredProjectResults " class ="project-list-item ">
308+ < div class ="project-list-item__header ">
309+ < div class ="simple-list__meta simple-list__meta--top ">
310+ < i class ="pi pi-folder text-color-secondary "> </ i >
311+ < div class ="simple-list__text ">
312+ < span > {{ project.name }}</ span >
313+ </ div >
175314 </ div >
315+ < button
316+ pButton
317+ type ="button "
318+ icon ="pi pi-th-large "
319+ label ="Open Kanban "
320+ class ="p-button-sm p-button-outlined "
321+ (click) ="openProjectKanban(project.id) ">
322+ </ button >
176323 </ div >
177324 < div class ="project-meta-chips project-meta-chips--below-icon ">
178325 < span class ="project-meta-chip ">
@@ -183,18 +330,32 @@ <h3>Projects For User</h3>
183330 </ span >
184331 </ div >
185332 </ li >
186- < li *ngIf ="userProjects .length === 0 " class ="muted "> No matching projects.</ li >
333+ < li *ngIf ="filteredProjectResults .length === 0 " class ="muted "> No matching projects.</ li >
187334 </ ul >
188335 </ div >
189336 </ p-card >
190337 </ div >
191338
192- < p-card header ="Tasks ">
339+ < p-card styleClass ="tasks-results-card ">
340+ < div class ="results-card__title ">
341+ < h3 > Task Results</ h3 >
342+ < p > Review filtered tasks and jump directly to the project Kanban board.</ p >
343+ </ div >
193344 < div class ="tasks-meta ">
194- < span > {{ filteredTasks.length }} tasks</ span >
345+ < div class ="tasks-meta__summary ">
346+ < span class ="tasks-meta__summary-icon ">
347+ < i class ="pi pi-list-check "> </ i >
348+ </ span >
349+ < div class ="tasks-meta__summary-text ">
350+ < strong > {{ filteredTasks.length }} tasks</ strong >
351+ < small > matching current filters</ small >
352+ </ div >
353+ </ div >
195354 < div class ="pagination-controls ">
196355 < p-dropdown
197- [options] ="pageSizeOptions "
356+ [options] ="pageSizeSelectOptions "
357+ optionLabel ="label "
358+ optionValue ="value "
198359 [ngModel] ="pageSize "
199360 (onChange) ="pageSize = $event.value; page = 1 "
200361 appendTo ="body ">
@@ -209,12 +370,28 @@ <h3>Projects For User</h3>
209370 < article class ="task-item " *ngFor ="let task of pagedTasks ">
210371 < div class ="task-item__head ">
211372 < strong > {{ task.title }}</ strong >
212- < p-tag [value] ="getTaskStatusLabel(task.status) " [severity] ="getTaskStatusSeverity(task.status) "> </ p-tag >
373+ < div class ="task-item__head-actions ">
374+ < p-tag [value] ="getTaskStatusLabel(task.status) " [severity] ="getTaskStatusSeverity(task.status) "> </ p-tag >
375+ < button
376+ pButton
377+ type ="button "
378+ icon ="pi pi-th-large "
379+ label ="Open Kanban "
380+ class ="p-button-sm p-button-outlined "
381+ (click) ="openTaskKanban(task) ">
382+ </ button >
383+ </ div >
213384 </ div >
214- < p class ="task-item__desc "> {{ task.description || 'No description provided.' }}</ p >
385+ < app-expandable-text
386+ class ="task-item__desc "
387+ [text] ="task.description "
388+ [maxLength] ="140 ">
389+ </ app-expandable-text >
215390 < div class ="task-item__meta ">
216391 < span > < i class ="pi pi-user "> </ i > {{ task.assignedUserName || 'Unassigned' }}</ span >
217392 < span > < i class ="pi pi-folder "> </ i > {{ task.projectName }}</ span >
393+ < span > < i class ="pi pi-pencil "> </ i > Created {{ task.createdAt | date:'mediumDate' }} by {{ task.createdByUserName || 'Unknown' }}</ span >
394+ < span > < i class ="pi pi-history "> </ i > Updated {{ task.lastModifiedAt | date:'mediumDate' }} by {{ task.lastModifiedByUserName || 'Unknown' }}</ span >
218395 </ div >
219396 </ article >
220397
0 commit comments