PluginProbe
Taskbuilder – Project Management & Task Management Tool With Kanban Board / 6.0.6
Taskbuilder – Project Management & Task Management Tool With Kanban Board v6.0.6
6.0.6 6.0.5 6.0.2 6.0.3 6.0.4 6.0.1 6.0.0 5.0.8 5.0.9 4.0.9 5.0.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 All 58 releases
← All changes | includes/admin/tasks/wppm_tasks_list.php +639 -96 5.0.66.0.6 View file →
@@ -9,12 +9,48 @@
9 9 $search_tag = isset($_POST['task_search']) ? sanitize_text_field(wp_unslash($_POST['task_search'])) : '';
10 10 $order = isset($_POST['order']) ? sanitize_text_field(wp_unslash($_POST['order'])) :"ASC";
11 11 $sort_by = isset($_POST['sort_by']) ? sanitize_text_field(wp_unslash($_POST['sort_by'])):"task_name";
12 12 $filter_by = isset($_POST['wppm_task_filter']) ? sanitize_text_field(wp_unslash($_POST['wppm_task_filter'])) : "all";
13 +if (isset($_POST['filters'])) {
14 + if (is_string($_POST['filters'])) {
15 + $advanced_filter = json_decode( stripslashes( sanitize_text_field( wp_unslash($_POST['filters']))),true );
16 + } elseif (is_array($_POST['filters'])) {
17 + $raw_filters = wp_unslash($_POST['filters']);
18 + $advanced_filter = [
19 + 'created_by' => array_map('absint', (array) ($raw_filters['created_by'] ?? [])),
20 + 'assigned' => array_map('absint', (array) ($raw_filters['assigned'] ?? [])),
21 + 'priority' => array_map('absint', (array) ($raw_filters['priority'] ?? [])),
22 + 'start_date' => sanitize_text_field($raw_filters['start_date'] ?? ''),
23 + 'end_date' => sanitize_text_field($raw_filters['end_date'] ?? ''),
24 + ];
25 + } else {
26 + $advanced_filter = [];
27 + }
28 +}else{
29 + $advanced_filter = [];
30 +}
31 +///$advanced_filter = isset($_POST['filters']) ? (($_POST['filters'])) : "array()";
13 32 $proj_filter = isset($_POST['wppm_proj_filter']) ? sanitize_text_field(wp_unslash($_POST['wppm_proj_filter'])) : "0";
14 33 $proj_attr = isset($_POST['wppm_project_attr']) ? sanitize_text_field(wp_unslash($_POST['wppm_project_attr'])):"";
15 34 $public_projects = isset($_POST['public_projects']) ? sanitize_text_field(wp_unslash($_POST['public_projects'])):"0";
35 +$tb_start_date = isset($_POST['tb_start_date']) ? sanitize_text_field($_POST['tb_start_date']) : '';
36 +$tb_end_date = isset($_POST['tb_end_date']) ? sanitize_text_field($_POST['tb_end_date']) : '';
37 +$tb_created_by = isset($_POST['tb_created_by']) ? sanitize_text_field($_POST['tb_created_by']) : '';
16 38 $page = isset($_POST['page']) ? sanitize_text_field(wp_unslash($_POST['page'])):"";
39 +$priorities = $wpdb->get_results("SELECT id, name FROM {$wpdb->prefix}wppm_task_priorities ORDER BY id ASC ");
40 +$users = get_users(array(
41 + 'orderby' => 'display_name',
42 + 'order' => 'ASC'
43 +));
44 +$assigned_users = $wpdb->get_col( " SELECT DISTINCT users FROM {$wpdb->prefix}wppm_task WHERE users != ''");
45 +$all_assigned = [];
46 +foreach ($assigned_users as $row) {
47 + $ids = explode(',', $row);
48 + foreach ($ids as $id) {
49 + $all_assigned[] = trim($id);
50 + }
51 +}
52 +$all_assigned = array_unique($all_assigned);
17 53 $wppm_current_user_capability = get_user_meta( $current_user->ID, 'wppm_capability', true );
18 54 $wppm_create_tasks_coworkers_permission = get_option('wppm_allow_coworkers_create_task');
19 55 $orderby_proj_sql = esc_sql(sanitize_sql_orderby( "project_name" ));
20 56 $wppm_date_setting = get_option('wppm_date_setting');
@@ -27,44 +63,84 @@
27 63 $wppm_hide_task_statuses_from_frontend = '';
28 64 }
29 65 $proj_attr = esc_sql($proj_attr);
30 66 $is_frontend = 0;
31 -if(!empty($proj_attr )){
32 - $wppm_proj_attr = ' AND (proj.project_name = "'.$proj_attr.'")';
33 -}else{
34 - $wppm_proj_attr = '';
67 +if ( ! empty( $proj_attr ) ) {
68 + $wppm_proj_attr = $wpdb->prepare(
69 + ' AND (proj.project_name = %s)',
70 + $proj_attr
71 + );
72 +} else {
73 + $wppm_proj_attr = '';
35 74 }
36 75 $current_date = wp_date('Y-m-d');
37 76 $current_date = esc_sql($current_date );
38 77 $cu_id = esc_sql($current_user->ID);
39 -$archived_where = "";
40 -if ( isset($page) && $page === 'wppm-archived-tasks' ) {
41 - $archived_where = " AND is_archived = 1";
78 +$archived_where = '';
79 +if ( isset( $page ) && $page === 'wppm-archived-tasks' ) {
80 + $archived_where = ' AND Task.is_archived = 1';
81 +} elseif ( isset( $page ) && $page === 'wppm-tasks' ) {
82 + $archived_where = ' AND Task.is_archived = 0';
42 83 }
43 -if( isset($page) && $page === 'wppm-tasks'){
44 - $archived_where = " AND is_archived = 0";
45 -}
46 84 $wppm_task_time = get_option('wppm_task_time');
47 -$query = ("SELECT proj.*
48 - FROM {$wpdb->prefix}wppm_project AS proj
49 - Left join {$wpdb->prefix}wppm_project_meta proj_meta ON proj.id = proj_meta.project_id");
50 -if($current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin'){
51 - if(!empty($proj_attr )){
52 - $where = " where project_name = '".$proj_attr."' Group by proj.id ORDER BY ".$orderby_proj_sql;
53 - }else{
54 - if(!empty($public_projects)){
55 - $where = " where proj.id = proj_meta.project_id AND proj_meta.meta_key='public_project' AND proj_meta.meta_value=1 Group by proj.id ORDER BY ".$orderby_proj_sql;
56 - }else{
57 - $where = " Group by proj.id ORDER BY ".$orderby_proj_sql;
85 +$query = "SELECT proj.*
86 +FROM {$wpdb->prefix}wppm_project AS proj
87 +LEFT JOIN {$wpdb->prefix}wppm_project_meta AS proj_meta ON proj.id = proj_meta.project_id";
88 +if ( $current_user->has_cap( 'manage_options' ) || $wppm_current_user_capability === 'wppm_admin' ) {
89 + if ( ! empty( $proj_attr ) ) {
90 + $where = $wpdb->prepare(
91 + " WHERE proj.project_name = %s
92 + GROUP BY proj.id
93 + ORDER BY $orderby_proj_sql",
94 + $proj_attr
95 + );
96 + } else {
97 + if ( ! empty( $public_projects ) ) {
98 + $where = $wpdb->prepare(
99 + " WHERE proj_meta.meta_key = %s
100 + AND proj_meta.meta_value = %d
101 + GROUP BY proj.id
102 + ORDER BY $orderby_proj_sql",
103 + 'public_project',
104 + 1
105 + );
106 + } else {
107 + $where = " GROUP BY proj.id ORDER BY $orderby_proj_sql";
108 + }
58 109 }
59 - }
60 -}else{
61 - if(!empty($public_projects)){
62 - $where = " where (proj.id = proj_meta.project_id AND proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) $wppm_proj_attr Group by proj.id ORDER BY $orderby_proj_sql";
63 - }
64 - else{
65 - $where = " where ((FIND_IN_SET('$current_user->ID',proj.users)) OR (proj.id = proj_meta.project_id AND proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) OR ( proj.created_by='$cu_id')) $wppm_proj_attr Group by proj.id ORDER BY $orderby_proj_sql";
66 - }
110 +} else {
111 + if ( ! empty( $public_projects ) ) {
112 + $where = $wpdb->prepare(
113 + " WHERE (
114 + proj_meta.meta_key = %s
115 + AND proj_meta.meta_value = %d
116 + )
117 + $wppm_proj_attr
118 + GROUP BY proj.id
119 + ORDER BY $orderby_proj_sql",
120 + 'public_project',
121 + 1
122 + );
123 +
124 + } else {
125 + $where = $wpdb->prepare(
126 + " WHERE (
127 + FIND_IN_SET(%d, proj.users)
128 + OR (
129 + proj_meta.meta_key = %s
130 + AND proj_meta.meta_value = %d
131 + )
132 + OR proj.created_by = %d
133 + )
134 + $wppm_proj_attr
135 + GROUP BY proj.id
136 + ORDER BY $orderby_proj_sql",
137 + $current_user->ID,
138 + 'public_project',
139 + 1,
140 + $cu_id
141 + );
142 + }
67 143 }
68 144 $where = apply_filters('wppm_project_filter_in_task_list_where',$where);
69 145 $query.= $where;
70 146 $projects = $wpdb->get_results($query);
@@ -76,8 +152,20 @@
76 152 'filter'=>$filter_by,
77 153 'proj_filter' =>$proj_filter
78 154 );
79 155 $tl_filters = isset( $_COOKIE['wppm_filters'] ) ? sanitize_text_field( wp_unslash( $_COOKIE['wppm_filters'] ) ) : $filters;
156 +$tl_advanced_filters = [];
157 +if ( !empty($_COOKIE['tb_list_filters']) ) {
158 + $tl_advanced_filters = json_decode(
159 + stripslashes($_COOKIE['tb_list_filters']),
160 + true
161 + );
162 + if ( ! is_array($tl_advanced_filters) ) {
163 + $tl_advanced_filters = [];
164 + }
165 +}
166 +//$tl_advanced_filters = isset( $_COOKIE['wppm_advanced_filters'] ) ? sanitize_text_field( wp_unslash( $_COOKIE['wppm_advanced_filters'] ) ) : $tl_advanced_filters;
167 +
80 168 if(!is_array($tl_filters)){
81 169 $tl_filters = json_decode($tl_filters);
82 170 $tl_filters_arr = (array) $tl_filters;
83 171 } else{
@@ -100,9 +188,9 @@
100 188 'filter'=>$filter_by,
101 189 'proj_filter'=>$proj_filter
102 190 );
103 191 setcookie('wppm_filters',wp_json_encode( $filters ),time() + 3600);
104 -
192 +//setcookie('wppm_advanced_filters',wp_json_encode( $tl_advanced_filters ),time() + 3600);
105 193 // Allowed sort columns
106 194 $allowed_sort_by = [
107 195 'project' => 'proj.project_name',
108 196 'status' => 'task_statuses.name',
@@ -116,10 +204,9 @@
116 204 $sort_key = isset($_POST['sort_by'])
117 205 ? sanitize_text_field(wp_unslash($_POST['sort_by']))
118 206 : ($tl_filters_arr['sort_by'] ?? 'task_name');
119 207
120 -$sort_by = $allowed_sort_by[$sort_key] ?? 'task_name';
121 -
208 +$sort_by = $allowed_sort_by[$sort_key] ?? 'Task.task_name';
122 209 // Resolve order safely
123 210 $order = (isset($_POST['order']) && strtoupper(wp_unslash($_POST['order'])) === 'ASC')
124 211 ? 'ASC'
125 212 : 'DESC';
@@ -144,25 +231,103 @@
144 231 }elseif($filter_by == 'mine'){
145 232 $wppm_tl_filter = "(FIND_IN_SET('$current_user->ID',Task.users)>0)";
146 233 }elseif($filter_by == 'archived'){
147 234 $wppm_tl_filter = "Task.is_archived = 1";
235 +} elseif($filter_by == 'today'){
236 + $wppm_tl_filter = "DATE(Task.end_date) = CURDATE()";
237 +}elseif($filter_by == 'upcoming'){
238 + $wppm_tl_filter = "DATE(Task.end_date) BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 7 DAY) AND Task.status != 4 AND Task.active = 1 AND Task.is_archived = 0";
239 +}elseif ($filter_by == 'mytasks') {
240 + $wppm_tl_filter = "(
241 + FIND_IN_SET('$current_user->ID', Task.users)
242 + OR Task.created_by = '$current_user->ID'
243 + )
244 + AND Task.status != 4
245 + AND Task.active = 1
246 + AND Task.is_archived = 0";
247 +
148 248 }
149 249
250 +if(!empty($tl_advanced_filters['created_by'])){
251 + $created_by_ids = array_map('intval', $tl_advanced_filters['created_by']);
252 + $wppm_tl_filter .= " AND Task.created_by IN (" . implode(',', $created_by_ids) . ")";
253 +}
254 +if(!empty($tl_advanced_filters['assigned'])){
255 + $assigned_ids = array_map('intval', $tl_advanced_filters['assigned']);
256 + $assigned_sql = [];
257 + foreach ($assigned_ids as $id) {
258 + $assigned_sql[] = "FIND_IN_SET('$id', Task.users)";
259 + }
260 + $wppm_tl_filter .= " AND (" . implode(' OR ', $assigned_sql) . ")";
261 +}
262 +if(!empty($tl_advanced_filters['priority'])){
263 + $priority = array_map('intval', $tl_advanced_filters['priority']);
264 + $wppm_tl_filter .= " AND Task.priority IN (" . implode(',', $priority) . ")";
265 +}
266 +if(!empty($tl_advanced_filters['start_date'])){
267 + $start_date = sanitize_text_field($tl_advanced_filters['start_date']);
268 + $wppm_tl_filter .= $wpdb->prepare(" AND (CAST(Task.start_date AS DATE)) >= %s", $start_date);
269 +}
270 +if(!empty($tl_advanced_filters['end_date'])){
271 + $end_date = sanitize_text_field($tl_advanced_filters['end_date']);
272 + $wppm_tl_filter .= $wpdb->prepare(" AND (CAST(Task.end_date AS DATE)) <= %s", $end_date);
273 +}
274 +
275 +$advanced_conditions = [];
276 +// Created By
277 +if (!empty($advanced_filter['created_by'])) {
278 + $created_by_ids = array_map('intval', $advanced_filter['created_by']);
279 + $advanced_conditions[] = "Task.created_by IN (" . implode(',', $created_by_ids) . ")";
280 +}
281 +// Assigned Users
282 +if (!empty($advanced_filter['assigned'])) {
283 + $assigned_ids = array_map('intval', $advanced_filter['assigned']);
284 + $assigned_sql = [];
285 + foreach ($assigned_ids as $id) {
286 + $assigned_sql[] = "FIND_IN_SET('$id', Task.users)";
287 + }
288 + $advanced_conditions[] = "(" . implode(' OR ', $assigned_sql) . ")";
289 +}
290 +// Priority
291 +if (!empty($advanced_filter['priority'])) {
292 + $priority = array_map('intval', $advanced_filter['priority']);
293 + $advanced_conditions[] = "Task.priority IN (" . implode(',', $priority) . ")";
294 +}
295 +// Start Date
296 +if (!empty($advanced_filter['start_date'])) {
297 + $start_date = sanitize_text_field($advanced_filter['start_date']);
298 + $advanced_conditions[] = $wpdb->prepare("(CAST(Task.start_date AS DATE)) >= %s", $start_date);
299 +}
300 +// End Date
301 +if (!empty($advanced_filter['end_date'])) {
302 + $end_date = sanitize_text_field($advanced_filter['end_date']);
303 + $advanced_conditions[] = $wpdb->prepare("(CAST(Task.end_date AS DATE)) <= %s", $end_date);
304 +}
305 +if (!empty($advanced_conditions)) {
306 + $wppm_tl_filter .= " AND " . implode(" AND ", $advanced_conditions);
307 +}
308 +// Subtasks are shown only within their parent task, never as their own row in the task list.
309 +$wppm_tl_filter .= " AND (Task.parent_task_id = 0 OR Task.parent_task_id IS NULL)";
310 +//setcookie('wppm_advanced_filters',wp_json_encode( $advanced_filter ),time() + 3600);
150 311 if(!empty($wppm_hide_task_statuses_from_frontend) && is_array($wppm_hide_task_statuses_from_frontend) && ((isset($_POST['is_frontend'])) && (sanitize_text_field(wp_unslash($_POST['is_frontend']))==1))){
151 312 foreach($wppm_hide_task_statuses_from_frontend as $status){
152 313 $wppm_tl_filter .= " AND Task.status != '$status'";
153 314 }
154 315 }
155 -if($proj_filter!=0 || $project_id!=0){
156 - if($project_id!=0){
157 - $proj_filter = $project_id;
158 - }
159 - $wppm_task_by_proj_filter = "Task.project = '$proj_filter'";
160 -}else{
161 - $wppm_task_by_proj_filter ="1=1";
316 +if ( $proj_filter != 0 || $project_id != 0 ) {
317 + if ( $project_id != 0 ) {
318 + $proj_filter = $project_id;
319 + }
320 + $proj_filter = absint( $proj_filter );
321 + $wppm_task_by_proj_filter = $wpdb->prepare(
322 + "Task.project = %d",
323 + $proj_filter
324 + );
325 +} else {
326 + $wppm_task_by_proj_filter = "1=1";
162 327 }
163 328 $wppm_default_task_date = get_option('wppm_default_task_date');
164 -$search_tag_text = '%'.$wpdb->esc_like($search_tag).'%';
329 +$search_tag_text = "";
165 330 if(!empty($search_tag)){
166 331 $search_tag_text = '%'.$wpdb->esc_like($search_tag).'%';
167 332 $query = ("SELECT Task.*
168 333 FROM {$wpdb->prefix}wppm_task AS Task
@@ -169,9 +334,9 @@
169 334 Left join {$wpdb->prefix}wppm_project proj ON Task.project = proj.id
170 335 Left join {$wpdb->prefix}wppm_task_statuses task_statuses ON Task.status = task_statuses.id
171 336 Left join {$wpdb->prefix}wppm_task_priorities task_priorities ON Task.priority = task_priorities.id
172 337 Left join {$wpdb->prefix}wppm_project_users proj_users ON Task.project = proj_users.proj_id
173 - Left join {$wpdb->base_prefix}users user ON (FIND_IN_SET(user.id,Task.users)>0) AND user.display_name LIKE '$search_tag_text'
338 + Left join {$wpdb->base_prefix}users user ON (FIND_IN_SET(user.ID,Task.users)>0)
174 339 Left join {$wpdb->prefix}wppm_project_meta proj_meta ON Task.project = proj_meta.project_id");
175 340 }
176 341 else{
177 342 if($current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin'){
@@ -202,31 +367,207 @@
202 367 $no_of_rows = ( "SELECT count(*) FROM ($query");
203 368 if(!empty($search_tag )){
204 369 if($current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin'){
205 370 if(!empty($public_projects)){
206 - $where = " where (proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) AND $wppm_tl_filter AND $wppm_task_by_proj_filter AND (Task.task_name LIKE '$search_tag_text' OR proj.project_name LIKE '$search_tag_text' OR task_statuses.name LIKE '$search_tag_text' OR task_priorities.name LIKE '$search_tag_text' OR user.display_name LIKE '$search_tag_text') $wppm_proj_attr ";
371 + //$where = " where (proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) AND $wppm_tl_filter AND $wppm_task_by_proj_filter AND (Task.task_name LIKE '$search_tag_text' OR proj.project_name LIKE '$search_tag_text' OR task_statuses.name LIKE '$search_tag_text' OR task_priorities.name LIKE '$search_tag_text' OR user.display_name LIKE '$search_tag_text') $wppm_proj_attr ";
372 + $where = $wpdb->prepare( " WHERE (proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) AND $wppm_tl_filter AND $wppm_task_by_proj_filter
373 + AND (
374 + Task.task_name LIKE %s
375 + OR proj.project_name LIKE %s
376 + OR task_statuses.name LIKE %s
377 + OR task_priorities.name LIKE %s
378 + OR user.display_name LIKE %s
379 + ) $wppm_proj_attr",
380 + $search_tag_text,
381 + $search_tag_text,
382 + $search_tag_text,
383 + $search_tag_text,
384 + $search_tag_text
385 + );
207 386 }else{
208 - $where = " where $wppm_tl_filter AND $wppm_task_by_proj_filter AND (Task.task_name LIKE '$search_tag_text' OR proj.project_name LIKE '$search_tag_text' OR task_statuses.name LIKE '$search_tag_text' OR task_priorities.name LIKE '$search_tag_text' OR user.display_name LIKE '$search_tag_text') $wppm_proj_attr ";
387 + $where = $wpdb->prepare(
388 + " WHERE $wppm_tl_filter
389 + AND $wppm_task_by_proj_filter
390 + AND (
391 + Task.task_name LIKE %s
392 + OR proj.project_name LIKE %s
393 + OR task_statuses.name LIKE %s
394 + OR task_priorities.name LIKE %s
395 + OR user.display_name LIKE %s
396 + )
397 + $wppm_proj_attr",
398 + $search_tag_text,
399 + $search_tag_text,
400 + $search_tag_text,
401 + $search_tag_text,
402 + $search_tag_text
403 + );
209 404 }
210 405 } else{
211 406 if(!empty($public_projects)){
212 - $where = " where (proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) AND $wppm_tl_filter AND $wppm_task_by_proj_filter AND (((FIND_IN_SET('$current_user->ID',Task.users)>0) OR (Task.created_by= '$cu_id') OR (proj_users.user_id = '$cu_id' AND proj_users.role_id = 1 AND (FIND_IN_SET('$current_user->ID',proj.users)>0)) OR (Task.project = proj_meta.project_id AND proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) OR (proj.created_by='$cu_id' AND (FIND_IN_SET('$current_user->ID',proj.users)>0))) AND (Task.task_name LIKE '$search_tag_text' OR proj.project_name LIKE '$search_tag_text' OR task_statuses.name LIKE '$search_tag_text' OR task_priorities.name LIKE '$search_tag_text' OR user.display_name LIKE '$search_tag_text')) $wppm_proj_attr";
213 - }else{
214 - $where = " where $wppm_tl_filter AND $wppm_task_by_proj_filter AND (((FIND_IN_SET('$current_user->ID',Task.users)>0) OR (Task.created_by= '$cu_id') OR (proj_users.user_id = '$cu_id' AND proj_users.role_id = 1 AND (FIND_IN_SET('$current_user->ID',proj.users)>0)) OR (Task.project = proj_meta.project_id AND proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) OR (proj.created_by='$cu_id' AND (FIND_IN_SET('$current_user->ID',proj.users)>0))) AND (Task.task_name LIKE '$search_tag_text' OR proj.project_name LIKE '$search_tag_text' OR task_statuses.name LIKE '$search_tag_text' OR task_priorities.name LIKE '$search_tag_text' OR user.display_name LIKE '$search_tag_text')) $wppm_proj_attr";
407 + $where = $wpdb->prepare(
408 + " WHERE
409 + (proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) AND (proj.is_archived = 0)
410 + AND $wppm_tl_filter
411 + AND $wppm_task_by_proj_filter
412 + AND (
413 + (
414 + FIND_IN_SET(%d, Task.users) > 0
415 + OR Task.created_by = %d
416 + OR (
417 + proj_users.user_id = %d
418 + AND proj_users.role_id = 1
419 + AND FIND_IN_SET(%d, proj.users) > 0
420 + )
421 + OR (
422 + Task.project = proj_meta.project_id
423 + AND proj_meta.meta_key='public_project'
424 + AND proj_meta.meta_value=1
425 + )
426 + OR (
427 + proj.created_by = %d
428 + AND FIND_IN_SET(%d, proj.users) > 0
429 + )
430 + )
431 + AND (
432 + Task.task_name LIKE %s
433 + OR proj.project_name LIKE %s
434 + OR task_statuses.name LIKE %s
435 + OR task_priorities.name LIKE %s
436 + OR user.display_name LIKE %s
437 + )
438 + )
439 + $wppm_proj_attr",
440 + $current_user->ID,
441 + $cu_id,
442 + $cu_id,
443 + $current_user->ID,
444 + $cu_id,
445 + $current_user->ID,
446 + $search_tag_text,
447 + $search_tag_text,
448 + $search_tag_text,
449 + $search_tag_text,
450 + $search_tag_text
451 + );
452 + }else{
453 + $where = $wpdb->prepare(
454 + " WHERE
455 + (proj.is_archived = 0)
456 + AND $wppm_tl_filter
457 + AND $wppm_task_by_proj_filter
458 + AND (
459 + (
460 + FIND_IN_SET(%d, Task.users) > 0
461 + OR Task.created_by = %d
462 + OR (
463 + proj_users.user_id = %d
464 + AND proj_users.role_id = 1
465 + AND FIND_IN_SET(%d, proj.users) > 0
466 + )
467 + OR (
468 + Task.project = proj_meta.project_id
469 + AND proj_meta.meta_key='public_project'
470 + AND proj_meta.meta_value=1
471 + )
472 + OR (
473 + proj.created_by = %d
474 + AND FIND_IN_SET(%d, proj.users) > 0
475 + )
476 + )
477 + AND (
478 + Task.task_name LIKE %s
479 + OR proj.project_name LIKE %s
480 + OR task_statuses.name LIKE %s
481 + OR task_priorities.name LIKE %s
482 + OR user.display_name LIKE %s
483 + )
484 + )
485 + $wppm_proj_attr",
486 + $current_user->ID,
487 + $cu_id,
488 + $cu_id,
489 + $current_user->ID,
490 + $cu_id,
491 + $current_user->ID,
492 + $search_tag_text,
493 + $search_tag_text,
494 + $search_tag_text,
495 + $search_tag_text,
496 + $search_tag_text
497 + );
215 498 }
216 499 }
217 500 }else{
218 501 if($current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin'){
219 502 if(!empty($public_projects)){
220 - $where = " where (proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) AND $wppm_tl_filter AND $wppm_task_by_proj_filter $wppm_proj_attr";
503 + $where = $wpdb->prepare(
504 + " WHERE
505 + (proj_meta.meta_key = %s AND proj_meta.meta_value = %d)
506 + AND (proj.is_archived = 0)
507 + AND $wppm_tl_filter
508 + AND $wppm_task_by_proj_filter
509 + $wppm_proj_attr",
510 + 'public_project',
511 + 1
512 + );
221 513 }else{
222 - $where = " where $wppm_tl_filter AND $wppm_task_by_proj_filter $wppm_proj_attr";
514 + $where = " where (proj.is_archived = 0) AND $wppm_tl_filter AND $wppm_task_by_proj_filter $wppm_proj_attr";
223 515 }
224 516 } else{
225 517 if(!empty($public_projects)){
226 - $where = " where (proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) AND $wppm_tl_filter AND $wppm_task_by_proj_filter $wppm_proj_attr";
518 + $where = $wpdb->prepare(
519 + " WHERE
520 + (
521 + proj_meta.meta_key = %s
522 + AND proj_meta.meta_value = %d
523 + )
524 + AND (proj.is_archived = 0)
525 + AND $wppm_tl_filter
526 + AND $wppm_task_by_proj_filter
527 + $wppm_proj_attr",
528 + 'public_project',
529 + 1
530 + );
227 531 }else{
228 - $where = " where $wppm_tl_filter AND $wppm_task_by_proj_filter AND ((FIND_IN_SET('$current_user->ID',Task.users)>0) OR (Task.created_by= '$cu_id') OR (proj_users.user_id = '$cu_id' AND proj_users.role_id = 1 AND (FIND_IN_SET('$current_user->ID',proj.users)>0)) OR (Task.project = proj_meta.project_id AND proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) OR (proj.created_by='$cu_id' AND (FIND_IN_SET('$current_user->ID',proj.users)>0))) $wppm_proj_attr";
532 + $where = $wpdb->prepare(
533 + " WHERE
534 + (proj.is_archived = 0)
535 + AND $wppm_tl_filter
536 + AND $wppm_task_by_proj_filter
537 + AND (
538 + (
539 + FIND_IN_SET(%d, Task.users) > 0
540 + )
541 + OR (
542 + Task.created_by = %d
543 + )
544 + OR (
545 + proj_users.user_id = %d
546 + AND proj_users.role_id = %d
547 + AND FIND_IN_SET(%d, proj.users) > 0
548 + )
549 + OR (
550 + Task.project = proj_meta.project_id
551 + AND proj_meta.meta_key = %s
552 + AND proj_meta.meta_value = %d
553 + )
554 + OR (
555 + proj.created_by = %d
556 + AND FIND_IN_SET(%d, proj.users) > 0
557 + )
558 + )
559 + $wppm_proj_attr",
560 + $current_user->ID,
561 + $cu_id,
562 + $cu_id,
563 + 1,
564 + $current_user->ID,
565 + 'public_project',
566 + 1,
567 + $cu_id,
568 + $current_user->ID
569 + );
229 570 }
230 571 }
231 572 }
232 573 $query = apply_filters('wppm_task_list_list_view_query',$query,$search_tag_text);
@@ -302,16 +643,17 @@
302 643 <span class="wppm-heading-inline"><?php echo (isset($page) && $page === 'wppm-archived-tasks' ) ? esc_html_e('Archived Tasks','taskbuilder'): esc_html_e('Tasks','taskbuilder');?> </span>
303 644 <span class="wppm-add-new-btn btn-primary" id="wppm_add_new_task_btn_tl" style="background-color:<?php echo esc_attr($appearance_settings['list-header-button-background-color'])?>;color:<?php echo esc_attr($appearance_settings['list-header-button-text-color'])?>;<?php echo esc_attr($style)?>;" onclick="wppm_add_new_task()"><img class="wppm_add_new_task_img" src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/plus_icon.svg'); ?>" alt="add_icon"><?php echo esc_html_e('Add New','taskbuilder');?></span>
304 645 <!-- Dashboard Button -->
305 646 <a class="wppm-add-new-btn btn-primary" style="background-color:<?php echo esc_attr($appearance_settings['list-header-button-background-color'])?>;color:<?php echo esc_attr($appearance_settings['list-header-button-text-color'])?>;<?php echo esc_attr($style)?>;" href="<?php echo esc_url( admin_url('admin.php?page=wppm-dashboard') ); ?>"
306 - style="margin-right:10px;">
647 + style="margin-right:10px;" title="<?php echo esc_attr_e('Go to Dashboard','taskbuilder'); ?>">
307 648 <img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/dashboard.svg'); ?>" alt="dashboard_icon">
308 649 <?php esc_html_e('Dashboard','taskbuilder'); ?>
309 650 </a>
651 + </span>
310 652 </div>
311 653 </div>
312 - <div style="display:flex;justify-content:space-between;margin-top:20px;flex-wrap: wrap;">
313 - <div style="display:flex;flex-wrap: wrap;min-width: 0; max-width: 100%; ">
654 + <div>
655 + <div style="display:flex;flex-wrap: wrap;min-width: 0; max-width: 100%;margin-top: 20px;">
314 656 <div id="wppm_task_filter_container">
315 657 <div class="wppm-bulk-actions"style="margin-left: -14px !important;">
316 658 <button
317 659 id="wppm-task-bulk-actions-btn"
@@ -347,22 +689,89 @@
347 689 </select>
348 690 </div>
349 691 </div>
350 692 </div>
351 - <div class="wppm-filter-item wppm_project_autocomplete_container" style="margin: 0 0 0 28px;">
352 - <label for="wppm_task_list_proj_filter">
353 - <?php echo esc_html_e('Project','taskbuilder');?>
354 - </label><br>
355 - <select searchable="search here" onchange="wppm_tasks_by_select_project('<?php echo esc_attr($page); ?>')" class="form-control" size="40" name="wppm_task_list_proj_filter" id="wppm_task_list_proj_filter" data-width="100%" style="width: 100%!important;">
356 - <option value="0" <?php echo ($proj_filter == 0)? 'selected':""?>><?php echo esc_html_e('All','taskbuilder');?></option>
693 + <div class="wppm-filter-item wppm_project_autocomplete_container" style="margin: 0 0 0 20px;">
694 + <label for="wppm_task_list_proj_filter">
695 + <?php echo esc_html_e('Project','taskbuilder');?>
696 + </label><br>
697 + <select searchable="search here" onchange="wppm_tasks_by_select_project('<?php echo esc_attr($page); ?>')" class="form-control" size="40" name="wppm_task_list_proj_filter" id="wppm_task_list_proj_filter" data-width="100%" style="width: 100%!important;">
698 + <option value="0" <?php echo ($proj_filter == 0)? 'selected':""?>><?php echo esc_html_e('All','taskbuilder');?></option>
699 + <?php
700 + if(!empty($projects)){
701 + foreach($projects as $proj) {
702 + ?><option value="<?php echo esc_attr($proj->id)?>" <?php echo ($proj_filter == $proj->id)? 'selected':""?>><?php echo esc_html($proj->project_name,'taskbuilder');?></option>
703 + <?php }
704 + } ?>
705 + </select>
706 + </div>
707 + <!-- FILTER BUTTON -->
708 + <div class="tb-filters" class="wppm-filter-item" style="display:flex;margin-left: 4px;">
709 + <div class="tb-filter-bar">
710 + <span id="tb-advanced-toggle" class="tb-btn" style="margin-top:0px!important;">
711 + <?php echo esc_html_e('⚙️ Filters', 'taskbuilder'); ?>
712 + </span>
713 +
714 + <!-- ACTIVE FILTER CHIPS -->
715 + <div id="tb-active-filters" class="tb-chips"></div>
716 +
717 + <!-- POPOVER -->
718 + <div id="tb-advanced-panel" class="tb-popover">
719 + <div class="tb-mobile-header">
720 + <span><?php echo esc_html_e('Filters', 'taskbuilder'); ?></span>
721 + <button type="button" id="tb-close-filters">✕</button>
722 + </div>
723 + <div class="tb-arrow"></div>
724 +
725 + <div class="tb-section">
726 + <h4> <?php echo esc_html_e('Created By', 'taskbuilder'); ?></h4>
727 + <select id="tb-created-by" class="form-control" multiple>
357 728 <?php
358 - if(!empty($projects)){
359 - foreach($projects as $proj) {
360 - ?>
361 - <option value="<?php echo esc_attr($proj->id)?>" <?php echo ($proj_filter == $proj->id)? 'selected':""?>><?php echo esc_html($proj->project_name,'taskbuilder');?></option>
362 - <?php }
363 - } ?>
729 + if(!empty($users)){
730 + foreach($users as $user): ?>
731 + <option value="<?php echo esc_attr($user->ID); ?>"><?php echo esc_html($user->display_name); ?></option>
732 + <?php endforeach; ?>
733 + <?php } ?>
734 + </select>
735 + <h4> <?php echo esc_html_e('Assigned To', 'taskbuilder'); ?></h4>
736 + <select id="tb-assigned" multiple>
737 + <?php
738 + if(!empty($all_assigned)){
739 + foreach($all_assigned as $uid){
740 + $user = get_userdata($uid);
741 + if($user){ ?>
742 + <option value="<?php echo esc_attr($uid); ?>">
743 + <?php echo esc_html($user->display_name); ?>
744 + </option>
745 + <?php }
746 + }
747 + }
748 + ?>
364 749 </select>
750 + </div>
751 + <div class="tb-section">
752 + <h4> <?php echo esc_html_e('Priority', 'taskbuilder'); ?></h4>
753 + <select id="tb-priority" class="form-control" multiple>
754 + <?php if(!empty($priorities)) {
755 + foreach($priorities as $priority){ ?>
756 + <option value="<?php echo esc_attr($priority->id); ?>">
757 + <?php echo esc_html($priority->name); ?>
758 + </option>
759 + <?php } } ?>
760 + </select>
761 + </div>
762 + <div class="tb-section">
763 + <h4> <?php echo esc_html_e('Date', 'taskbuilder'); ?></h4>
764 + <input type="date" class="form-control" id="tb-start-date">
765 + <input type="date" class="form-control"id="tb-end-date">
766 + </div>
767 + <div id="tb-filter-actions">
768 + <button class="wppm-submit-btn" id="tb-apply-filter" type="button"> <?php echo esc_html_e('Apply', 'taskbuilder'); ?></button>
769 + <button class="wppm_reset_btn" id="tb-reset-filter" type="button"> <?php echo esc_html_e('Reset', 'taskbuilder'); ?></button>
770 + </div>
771 + </div>
772 + </div>
773 + <div id="tb-backdrop"></div>
365 774 </div>
366 775 <div class="wppm_display_submit" style="margin: 0 0 -5px 10px;">
367 776 <div class="wppm-filter-actions">
368 777 <span class="wppm-link" onclick="wppm_tl_reset_filter('<?php echo esc_attr($page); ?>')"> <?php echo esc_html_e('Reset','taskbuilder');?></span>
@@ -367,19 +776,19 @@
367 776 <div class="wppm-filter-actions">
368 777 <span class="wppm-link" onclick="wppm_tl_reset_filter('<?php echo esc_attr($page); ?>')"> <?php echo esc_html_e('Reset','taskbuilder');?></span>
369 778 </div>
370 779 </div>
371 - </div>
372 - <div id="wppm_task_search" style="display:flex;justify-content:flex-end;">
373 - <img width="25px" height="15" class="wppm_task_search_filter_img" style="position: relative;top: 10px;left: 30px;" height="15px" src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/search.svg'); ?>" alt="search">
374 - <input type="search" id="wppm_task_search_filter" style="margin-right:10px;" name="wppm_task_search_filter" class="form-control form-control-sm" aria-controls="selection-datatable" placeholder="<?php echo esc_attr__('Search','taskbuilder');?>" value="<?php echo (!empty($search_tag)) ? esc_attr($search_tag) : "" ?>">
780 + <div id="wppm_task_search" style="display:flex;justify-content:flex-end;margin-left: auto;">
781 + <img width="25px" height="15" class="wppm_task_search_filter_img" style="position: relative;top: 10px;left: 30px;" height="15px" src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/search.svg'); ?>" alt="search">
782 + <input type="search" id="wppm_task_search_filter" style="margin-right:10px;" name="wppm_task_search_filter" class="form-control form-control-sm" aria-controls="selection-datatable" placeholder="<?php echo esc_attr__('Search','taskbuilder');?>" value="<?php echo (!empty($search_tag)) ? esc_attr($search_tag) : "" ?>">
375 783 </div>
376 784 </div>
377 785 </div>
378 - <div style="display:flex;justify-content:flex-end;margin-right: 10px;">
379 - <span id="wppm_grid_view_btn" onclick="wppm_view_task_search_filter('<?php echo esc_attr($page_no)?>','<?php echo esc_attr($page)?>','<?php echo esc_attr($project_id)?>')"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/grid_view.svg'); ?>" alt="grid_view"><span><?php echo esc_html_e('Grid view','taskbuilder');?></span></span>
380 - </div>
381 786 </div>
787 + <div style="display:flex;justify-content:flex-end;margin-right: 10px;">
788 + <span id="wppm_grid_view_btn" onclick="wppm_view_task_search_filter('<?php echo esc_attr($page_no)?>','<?php echo esc_attr($page)?>','<?php echo esc_attr($project_id)?>')"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/grid_view.svg'); ?>" alt="grid_view"><span><?php echo esc_html_e('Grid view','taskbuilder');?></span></span>
789 + </div>
790 + </div>
382 791 <script>
383 792 jQuery('#wppm-more-actions-btn, #wppm-task-bulk-actions-btn').gpopover({width: 200});
384 793 </script>
385 794 <div id="wppm_task_table_container" class="wppm_task_table_container table-responsive" style="padding: 0 15px 15px 15px;">
@@ -444,8 +853,38 @@
444 853 </thead>
445 854 <tbody>
446 855 <?php
447 856 $task_index = 0;
857 + $statuses = $wpdb->get_results(
858 + "SELECT * FROM {$wpdb->prefix}wppm_task_statuses",
859 + OBJECT_K
860 + );
861 +
862 + $priorities = $wpdb->get_results(
863 + "SELECT * FROM {$wpdb->prefix}wppm_task_priorities",
864 + OBJECT_K
865 + );
866 + $projects = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}wppm_project", OBJECT_K) ;
867 + $task_ids = wp_list_pluck($wppm_task_fillter, 'id');
868 + $checklist_counts = [];
869 + if (!empty($task_ids)) {
870 + $task_ids_sql = implode(',', array_map('absint', $task_ids));
871 + $checklist_results = $wpdb->get_results(" SELECT checklist.task_id,
872 + COUNT(Items.id) AS total_items,
873 + SUM(CASE WHEN Items.checked = 1 THEN 1 ELSE 0 END) AS checked_items
874 + FROM {$wpdb->prefix}wppm_checklist_items AS Items
875 + LEFT JOIN {$wpdb->prefix}wppm_checklist AS checklist
876 + ON Items.checklist_id = checklist.id
877 + WHERE checklist.task_id IN ($task_ids_sql)
878 + GROUP BY checklist.task_id"
879 + );
880 + foreach ($checklist_results as $row) {
881 + $checklist_counts[$row->task_id] = [
882 + 'total' => (int) $row->total_items,
883 + 'checked' => (int) $row->checked_items,
884 + ];
885 + }
886 + }
448 887 if(!empty($wppm_task_fillter)){
449 888 foreach($wppm_task_fillter as $task) {
450 889 $task_id = absint($task->id);
451 890 $wppm_task_duration = $wppmfunction->wppm_get_duration($task->start_date,$task->end_date);
@@ -453,28 +892,21 @@
453 892 if(!empty($task)){
454 893 $taskdata = $wppmfunction->get_task($task->id);
455 894 $project_data = $wppmfunction->get_project($task->project);
456 895 $task_index++;
457 - $total=$wpdb->get_var("SELECT COUNT(Items.id) AS check_id
458 - FROM {$wpdb->prefix}wppm_checklist_items AS Items
459 - Left join {$wpdb->prefix}wppm_checklist checklist ON Items.checklist_id = checklist.id
460 - WHERE checklist.task_id = '$task_id'");
461 - $total_checked_items=$wpdb->get_var("SELECT COUNT(Items.id) AS check_id
462 - FROM {$wpdb->prefix}wppm_checklist_items AS Items
463 - Left join {$wpdb->prefix}wppm_checklist checklist ON Items.checklist_id = checklist.id
464 - WHERE checklist.task_id = '$task_id' AND Items.checked=1");
465 -
896 + $total = $checklist_counts[$task_id]['total'] ?? 0;
897 + $total_checked_items = $checklist_counts[$task_id]['checked'] ?? 0;
466 898 if(isset($task->status)){
467 899 $tstatus = absint($task->status);
468 - $status = $wpdb->get_row( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_task_statuses where id = %d",$tstatus) );
900 + $status = $statuses[$task->status] ?? null;
469 901 }
470 902 if(!empty($task->priority)){
471 903 $tpriority = absint($task->priority);
472 - $priority = $wpdb->get_row( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_task_priorities where id = %d",$tpriority) );
904 + $priority = $priorities[$task->priority] ?? null;
473 905 }
474 906 if(isset($task->project)){
475 907 $tproj = absint($task->project);
476 - $project = $wpdb->get_row( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_project where id = %d",$tproj) );
908 + $project = $projects[$task->project] ?? null;
477 909 }
478 910 if($wppm_task_time == 1){
479 911 $tsDate = new DateTime($task->start_date);
480 912 $teDate = new DateTime($task->end_date);
@@ -509,9 +941,8 @@
509 941 $task_end_date = $teDate->format($wppm_date_setting);
510 942 }else{
511 943 $task_end_date = isset($task->end_date) ? $task->end_date: "" ;
512 944 }
513 -
514 945 }
515 946 } elseif($wppm_task_time == 0){
516 947 $tsDate = new DateTime($task->start_date);
517 948 $teDate = new DateTime($task->end_date);
@@ -574,8 +1005,12 @@
574 1005 </div>
575 1006 </td>
576 1007 <td onmouseover="link=true;">
577 1008 <?php echo esc_html($task->task_name) ?>
1009 + <?php $wppm_row_subtask_progress = $wppmfunction->get_subtask_progress($task->id);
1010 + if($wppm_row_subtask_progress['total'] > 0){ ?>
1011 + <span class="wppm_subtask_badge" title="<?php esc_attr_e('Subtasks','taskbuilder'); ?>"><?php echo esc_html($wppm_row_subtask_progress['completed'].'/'.$wppm_row_subtask_progress['total']); ?></span>
1012 + <?php } ?>
578 1013 </td>
579 1014 <td onmouseover="link=true;">
580 1015 <?php if(!empty($project->project_name)){
581 1016 echo esc_html($project->project_name);
@@ -597,10 +1032,10 @@
597 1032 <?php if(!empty($task_start_date)){ ?>
598 1033 <?php echo esc_html($task_start_date);
599 1034 } ?>
600 1035 </td>
601 - <td onmouseover="link=true;">
602 - <?php if(!empty($task_end_date) && ($task->status!=4 && $task_end_date < $current_date && $task_end_date != '0000-00-00 00:00:00' && $task_end_date != '00-00-0000 00:00:00' && $task_end_date != '00-00-0000' && $task_end_date != '0000-00-00')){
1036 + <td onmouseover="link=true;"><?php
1037 + if(!empty($task_end_date) && ($task->status!=4 && $task_end_date < $current_date && $task_end_date != '0000-00-00 00:00:00' && $task_end_date != '00-00-0000 00:00:00' && $task_end_date != '00-00-0000' && $task_end_date != '0000-00-00')){
603 1038 $style = "color:#FF0000";
604 1039 } else{
605 1040 $style = "color:#2C3E50";
606 1041 }?>
@@ -738,8 +1173,14 @@
738 1173 .select2-container {
739 1174 max-width: 150px !important;
740 1175 min-width: 150px !important;
741 1176 }
1177 +
1178 + .select2-selection--multiple {
1179 + max-width: 290px !important;
1180 + min-width: 290px !important;
1181 + }
1182 +
742 1183 #wppm_task_filter{
743 1184 min-height: 30px !important;
744 1185 max-height: 35px !important;
745 1186 }
@@ -761,16 +1202,90 @@
761 1202 background-color:<?php echo esc_attr($appearance_settings['list-header-button-hover-color'])?>!important;
762 1203 }
763 1204 </style>
764 1205 <script type="text/javascript">
765 - var link = true;
766 - jQuery( document ).ready( function( jQuery ) {
767 - jQuery("input[name='wppm_task_search_filter']").keypress(function(e) {
768 - //Enter key
769 - if (e.which == 13) {
770 - wppm_task_search_filter('<?php echo esc_attr($page); ?>');
771 - }
772 - });
1206 + var link = true;
1207 + window.listFilters = window.listFilters || {
1208 + created_by: [],
1209 + assigned: [],
1210 + priority: [],
1211 + start_date: "",
1212 + end_date: ""
1213 + };
1214 +
1215 + var listFilters = window.listFilters;
1216 + jQuery( document ).ready( function( jQuery ) {
1217 + // SET VALUES AFTER INIT
1218 + let createdBy = <?php echo wp_json_encode(array_map('strval', $advanced_filter['created_by'] ?? [])); ?>;
1219 +
1220 + let assigned = <?php echo wp_json_encode(array_map('strval', $advanced_filter['assigned'] ?? [])); ?>;
1221 +
1222 + let priority = <?php echo wp_json_encode(array_map('strval', $advanced_filter['priority'] ?? [])); ?>;
1223 + jQuery('#tb-created-by').val(createdBy).trigger('change');
1224 + jQuery('#tb-assigned').val(assigned).trigger('change');
1225 + jQuery('#tb-priority').val(priority).trigger('change');
1226 + jQuery('#tb-start-date').val('<?php echo esc_attr($advanced_filter['start_date'] ?? ''); ?>');
1227 + jQuery('#tb-end-date').val('<?php echo esc_attr($advanced_filter['end_date'] ?? ''); ?>');
1228 + jQuery(document).off("click", "#tb-apply-filter").on("click", "#tb-apply-filter", function (e) {
1229 + e.preventDefault();
1230 + listFilters.created_by = jQuery("#tb-created-by").val() || [];
1231 + listFilters.assigned = jQuery("#tb-assigned").val() || [];
1232 + listFilters.priority = jQuery("#tb-priority").val() || [];
1233 + listFilters.start_date = jQuery("#tb-start-date").val() || "";
1234 + listFilters.end_date = jQuery("#tb-end-date").val() || "";
1235 + listFilters.id = "<?php echo esc_attr($project_id); ?>";
1236 + renderActiveFilters(listFilters);
1237 + setListFilterCookie(listFilters);
1238 + triggerFilter(1, listFilters,'list');
1239 + });
1240 + jQuery(document).on("click", ".tb-remove", function () {
1241 + let key = jQuery(this).attr("data-key");
1242 + let value = jQuery(this).attr("data-value");
1243 + // DATE REMOVE
1244 + if (key === "date") {
1245 + listFilters.start_date = "";
1246 + listFilters.end_date = "";
1247 + jQuery("#tb-start-date").val("");
1248 + jQuery("#tb-end-date").val("");
1249 + } else {
1250 + listFilters[key] = (listFilters[key] || [])
1251 + .map(String)
1252 + .filter(v => v !== String(value));
1253 + jQuery(`#tb-${key}`).val(listFilters[key]).trigger("change");
1254 + }
1255 + // REMOVE CHIP UI
1256 + jQuery(this).closest(".tb-chip").remove();
1257 + syncUIWithFilters(listFilters);
1258 + // save cookie
1259 + setListFilterCookie(listFilters);
1260 + // reload data
1261 + triggerFilter(1,listFilters,'list');
1262 + });
1263 + jQuery(document)
1264 + .off("click", "#tb-reset-filter").on("click", "#tb-reset-filter", function () {
1265 + resetFilters('list');
1266 + });
1267 + let saved = getListFilterCookie();
1268 + if (saved && typeof saved === "object") {
1269 + window.listFilters = {
1270 + created_by: saved.created_by || [],
1271 + assigned: saved.assigned || [],
1272 + priority: saved.priority || [],
1273 + start_date: saved.start_date || "",
1274 + end_date: saved.end_date || ""
1275 + };
1276 + listFilters = window.listFilters;
1277 + }
1278 + setTimeout(function () {
1279 + syncUIWithFilters(listFilters);
1280 + renderActiveFilters(listFilters);
1281 + }, 100);
1282 + jQuery("input[name='wppm_task_search_filter']").keypress(function(e) {
1283 + //Enter key
1284 + if (e.which == 13) {
1285 + wppm_task_search_filter('<?php echo esc_attr($page); ?>');
1286 + }
1287 + });
773 1288 jQuery("#wppm_task_name_th").hover(function(){
774 1289 jQuery('#wppm_chevron_sort_up_task_name_img').show();
775 1290 jQuery('#wppm_chevron_sort_down_task_name_img').hide();
776 1291 });
@@ -801,8 +1316,14 @@
801 1316
802 1317 })
803 1318 jQuery('#wppm_task_list_proj_filter').select2({ dropdownAutoWidth: true, width: 'auto' });
804 1319 jQuery('#wppm_task_list_proj_filter').val(<?php echo esc_attr($proj_filter) ?>);
1320 + jQuery('#tb-created-by').select2({ dropdownAutoWidth: true, width: '100%'});
1321 + jQuery('#tb-created-by').val(<?php echo wp_json_encode($advanced_filter['created_by'] ?? []); ?>).trigger('change');
1322 + jQuery('#tb-assigned').select2({ dropdownAutoWidth: true, width: '100%' });
1323 + jQuery('#tb-assigned').val(<?php echo wp_json_encode($advanced_filter['assigned'] ?? []); ?>).trigger('change');
1324 + jQuery('#tb-priority').select2({dropdownAutoWidth: true, width: '100%'});
1325 + jQuery('#tb-priority').val(<?php echo wp_json_encode($advanced_filter['priority'] ?? []); ?>).trigger('change');
805 1326 /**
806 1327 * Bulk item selector change
807 1328 */
808 1329 function wppm_bulk_task_item_select_change() {
@@ -815,5 +1336,27 @@
815 1336 jQuery("#wppm-task-bulk-actions-btn").hide();
816 1337 jQuery(".wppm-bulk-selector").prop("checked", false);
817 1338 }
818 1339 }
819 -</script>
1340 + jQuery(document).off("click", "#tb-advanced-toggle").on("click", "#tb-advanced-toggle", function (e) {
1341 + e.stopPropagation();
1342 + jQuery("#tb-advanced-panel").toggleClass("tb-open");
1343 + });
1344 +
1345 + /* Close on backdrop click */
1346 + jQuery(document).on("click", "#tb-backdrop", function () {
1347 + jQuery("#tb-advanced-panel").removeClass("tb-open");
1348 + jQuery(this).removeClass("active");
1349 + });
1350 +
1351 + /* Close on outside (desktop only) */
1352 + jQuery(document).on("click", function (e) {
1353 + if (window.innerWidth > 768) {
1354 + if (!jQuery(e.target).closest("#tb-advanced-panel, #tb-advanced-toggle").length) {
1355 + jQuery("#tb-advanced-panel").removeClass("tb-open");
1356 + }
1357 + }
1358 + });jQuery(document).on("click", "#tb-close-filters", function () {
1359 + jQuery("#tb-advanced-panel").removeClass("tb-open");
1360 + jQuery("#tb-backdrop").removeClass("active");
1361 + });
1362 +</script>