PluginProbe
Taskbuilder – Project Management & Task Management Tool With Kanban Board / 6.0.7
Taskbuilder – Project Management & Task Management Tool With Kanban Board v6.0.7
6.0.7 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 All 59 releases
← All changes | includes/admin/projects/projects_list.php +336 -58 5.0.3 → 6.0.7 View file →
@@ -4,19 +4,68 @@
4 4 }
5 5 global $wpdb,$wppmfunction,$current_user;
6 6 $status = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}wppm_project_statuses" );
7 7 $categories = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}wppm_project_categories" );
8 -$appearance_settings = get_option("wppm-ap-project-list");
8 +$pb_users = get_users(array(
9 + 'orderby' => 'display_name',
10 + 'order' => 'ASC'
11 +));
12 +$assigned_project_users = $wpdb->get_col( "SELECT DISTINCT users FROM {$wpdb->prefix}wppm_project WHERE users != ''" );
13 +$all_assigned_proj_users = array();
14 +foreach ( $assigned_project_users as $row ) {
15 + foreach ( explode( ',', $row ) as $uid ) {
16 + $uid = trim( $uid );
17 + if ( $uid !== '' ) {
18 + $all_assigned_proj_users[] = $uid;
19 + }
20 + }
21 +}
22 +$all_assigned_proj_users = array_unique( $all_assigned_proj_users );
23 +$appearance_settings = wp_parse_args(
24 + get_option( "wppm-ap-project-list", array() ),
25 + array(
26 + 'list-header-button-background-color' => '#0052CC',
27 + 'list-header-button-hover-color' => '#0065ff',
28 + 'list-header-button-text-color' => '#fff',
29 + )
30 +);
9 31 $wppm_date_setting = get_option('wppm_date_setting');
10 32 $wppm_deafault_time_duration_project = get_option('wppm_display_time_duration_project');
11 33 $wppm_current_user_capability = get_user_meta( $current_user->ID, 'wppm_capability', true );
34 +$wppm_can_create_project = ($current_user->has_cap('manage_options')) || $wppm_current_user_capability == 'wppm_manager'|| $wppm_current_user_capability == 'wppm_admin';
35 +$wppm_can_create_project = apply_filters( 'wppm_can_create_project', $wppm_can_create_project, $current_user->ID );
12 36 $proj_per_page = 20;
13 37 $page_no = (isset($_POST['page_no'])) ? intval(sanitize_text_field($_POST['page_no'])): '0';
38 +$page = isset($_POST['page']) ? sanitize_text_field(wp_unslash($_POST['page'])):"";
14 39 $search_tag = isset($_POST['project_search']) ? sanitize_text_field($_POST['project_search']) : '';
15 40 $order = isset($_POST['order']) ? sanitize_text_field($_POST['order']) :"ASC";
16 41 $sort_by = isset($_POST['sort_by']) ? sanitize_text_field($_POST['sort_by']):"project_name";
17 42 $filter_by = isset($_POST['wppm_project_filter']) ? sanitize_text_field($_POST['wppm_project_filter']) : "all";
18 -$current_date = date('Y-m-d');
43 +$is_archieved = !empty($_POST['is_archieved']) ? 1 : 0;
44 +if ( isset( $_POST['filters'] ) ) {
45 + if ( is_string( $_POST['filters'] ) ) {
46 + $advanced_filter = json_decode( stripslashes( sanitize_text_field( wp_unslash( $_POST['filters'] ) ) ), true );
47 + } elseif ( is_array( $_POST['filters'] ) ) {
48 + $raw_filters = wp_unslash( $_POST['filters'] );
49 + $advanced_filter = array(
50 + 'created_by' => array_map( 'absint', (array) ( $raw_filters['created_by'] ?? array() ) ),
51 + 'assigned' => array_map( 'absint', (array) ( $raw_filters['assigned'] ?? array() ) ),
52 + 'category' => array_map( 'absint', (array) ( $raw_filters['category'] ?? array() ) ),
53 + 'start_date' => sanitize_text_field( $raw_filters['start_date'] ?? '' ),
54 + 'end_date' => sanitize_text_field( $raw_filters['end_date'] ?? '' ),
55 + );
56 + } else {
57 + $advanced_filter = array();
58 + }
59 +} elseif ( ! empty( $_COOKIE['tb_proj_list_filters'] ) ) {
60 + $advanced_filter = json_decode( stripslashes( sanitize_text_field( wp_unslash( $_COOKIE['tb_proj_list_filters'] ) ) ), true );
61 +} else {
62 + $advanced_filter = array();
63 +}
64 +if ( ! is_array( $advanced_filter ) ) {
65 + $advanced_filter = array();
66 +}
67 +$current_date = wp_date('Y-m-d');
19 68 $wppm_pl_filter = "1=1";
20 69 $wppm_hide_completed_status_proj = get_option('wppm_hide_completed_status_proj');
21 70 $cu_id = esc_sql($current_user->ID);
22 71 $wppm_hide_proj_statuses_from_frontend = get_option('wppm_hide_proj_statuses_from_frontend');
@@ -24,8 +73,9 @@
24 73 $wppm_hide_proj_statuses_from_frontend = explode(",",$wppm_hide_proj_statuses_from_frontend);
25 74 } else {
26 75 $wppm_hide_proj_statuses_from_frontend = '';
27 76 }
77 +$is_admin = ( $wppm_current_user_capability === 'wppm_admin' || current_user_can('manage_options') ) ? 1 : 0;
28 78 $filters = array(
29 79 'sort_by' => $sort_by,
30 80 'order' => $order,
31 81 'search' => $search_tag,
@@ -88,8 +138,11 @@
88 138 }elseif($filter_by == '3'){
89 139 $wppm_pl_filter = "status='3'";
90 140 }elseif($filter_by == 'mine'){
91 141 $wppm_pl_filter = "(FIND_IN_SET('$current_user->ID',users)>0)";
142 +}elseif($filter_by == 'active'){
143 + $wppm_pl_filter = " (FIND_IN_SET('$current_user->ID', users) OR created_by = '$current_user->ID' OR $is_admin = 1 )
144 + AND status != 4";
92 145 }
93 146
94 147 if(!empty($wppm_hide_proj_statuses_from_frontend) && is_array($wppm_hide_proj_statuses_from_frontend) && ((isset($_POST['is_frontend'])) && (sanitize_text_field($_POST['is_frontend'])==1))){
95 148 foreach($wppm_hide_proj_statuses_from_frontend as $status){
@@ -95,46 +148,115 @@
95 148 foreach($wppm_hide_proj_statuses_from_frontend as $status){
96 149 $wppm_pl_filter .= " AND status != '$status'";
97 150 }
98 151 }
99 -
152 +$advanced_conditions = array();
153 +if ( ! empty( $advanced_filter['created_by'] ) ) {
154 + $created_by_ids = array_map( 'intval', (array) $advanced_filter['created_by'] );
155 + $advanced_conditions[] = "created_by IN (" . implode( ',', $created_by_ids ) . ")";
156 +}
157 +if ( ! empty( $advanced_filter['assigned'] ) ) {
158 + $assigned_ids = array_map( 'intval', (array) $advanced_filter['assigned'] );
159 + $assigned_sql = array();
160 + foreach ( $assigned_ids as $id ) {
161 + $assigned_sql[] = "FIND_IN_SET('$id', users)";
162 + }
163 + $advanced_conditions[] = "(" . implode( ' OR ', $assigned_sql ) . ")";
164 +}
165 +if ( ! empty( $advanced_filter['category'] ) ) {
166 + $category_ids = array_map( 'intval', (array) $advanced_filter['category'] );
167 + $advanced_conditions[] = "cat_id IN (" . implode( ',', $category_ids ) . ")";
168 +}
169 +if ( ! empty( $advanced_filter['start_date'] ) && preg_match( '/^\d{4}-\d{2}-\d{2}$/', $advanced_filter['start_date'] ) ) {
170 + $advanced_conditions[] = $wpdb->prepare( "(CAST(start_date AS DATE)) >= %s", $advanced_filter['start_date'] );
171 +}
172 +if ( ! empty( $advanced_filter['end_date'] ) && preg_match( '/^\d{4}-\d{2}-\d{2}$/', $advanced_filter['end_date'] ) ) {
173 + $advanced_conditions[] = $wpdb->prepare( "(CAST(end_date AS DATE)) <= %s", $advanced_filter['end_date'] );
174 +}
175 +if ( ! empty( $advanced_conditions ) ) {
176 + $wppm_pl_filter .= " AND " . implode( " AND ", $advanced_conditions );
177 +}
100 178 $wppm_project_time = get_option('wppm_project_time');
101 179 $wppm_default_project_date = get_option('wppm_default_project_date');
102 180 $sort_by = apply_filters('wppm_project_list_sort_by_query',$sort_by);
103 181 $order = apply_filters('wppm_project_list_order_query',$order);
104 182 $search_tag_text = '%'.$wpdb->esc_like($search_tag).'%';
105 -if(!empty($search_tag)){
106 - $search_tag_text = '%'.$wpdb->esc_like($search_tag).'%';
107 - $query = ("SELECT Project.*
108 - FROM {$wpdb->prefix}wppm_project AS Project
109 - Left join {$wpdb->prefix}wppm_project_statuses proj_statuses ON Project.status = proj_statuses.id
110 - Left join {$wpdb->prefix}wppm_project_categories proj_categories ON Project.cat_id = proj_categories.id
111 - Left join {$wpdb->base_prefix}users user ON (FIND_IN_SET(user.ID,Project.users)>0) AND (user.display_name LIKE '$search_tag_text')
112 - Left join {$wpdb->prefix}wppm_project_meta proj_meta ON Project.id = proj_meta.project_id
113 - ");
114 - if($current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin'){
115 - $where = " where $wppm_pl_filter AND (Project.project_name LIKE '$search_tag_text' OR proj_statuses.name LIKE '$search_tag_text' OR proj_categories.name LIKE '$search_tag_text' OR ( user.display_name LIKE '$search_tag_text'))";
116 - }else{
117 - $where = " where $wppm_pl_filter AND (Project.project_name LIKE '$search_tag_text' OR proj_statuses.name LIKE '$search_tag_text' OR proj_categories.name LIKE '$search_tag_text' OR ( user.display_name LIKE '$search_tag_text')) AND ((FIND_IN_SET('$current_user->ID',Project.users)>0) OR (Project.id = proj_meta.project_id AND proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) OR Project.created_by='$cu_id')";
118 - }
119 -}else{
120 - if($sort_by=='project_name'|| $sort_by=='start_date' || $sort_by=='end_date'){
121 - $query = ( "SELECT Project.* FROM {$wpdb->prefix}wppm_project AS Project
122 - Left join {$wpdb->prefix}wppm_project_meta proj_meta ON Project.id = proj_meta.project_id
123 - ");
124 - } else{
125 - $query = ( "SELECT Project.* FROM {$wpdb->prefix}wppm_project AS Project
126 - Left join {$wpdb->prefix}wppm_project_statuses proj_statuses ON Project.status = proj_statuses.id
127 - Left join {$wpdb->prefix}wppm_project_categories proj_categories ON Project.cat_id = proj_categories.id
128 - Left join {$wpdb->prefix}wppm_project_meta proj_meta ON Project.id = proj_meta.project_id
129 - ");
130 - }
131 - if($current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin'){
132 - $where = " where $wppm_pl_filter";
133 - }else{
134 - $where = " where ($wppm_pl_filter AND (FIND_IN_SET('$current_user->ID',Project.users)>0 OR (Project.id = proj_meta.project_id AND proj_meta.meta_key='public_project' AND proj_meta.meta_value=1)) OR Project.created_by='$cu_id')";
135 - }
183 +if (!empty($search_tag)) {
184 + $search_tag_text = '%' . $wpdb->esc_like($search_tag) . '%';
185 + $query = "SELECT Project.*
186 + FROM {$wpdb->prefix}wppm_project AS Project
187 + LEFT JOIN {$wpdb->prefix}wppm_project_statuses proj_statuses ON Project.status = proj_statuses.id
188 + LEFT JOIN {$wpdb->prefix}wppm_project_categories proj_categories ON Project.cat_id = proj_categories.id
189 + LEFT JOIN {$wpdb->base_prefix}users user ON FIND_IN_SET(user.ID, Project.users) > 0
190 + LEFT JOIN {$wpdb->prefix}wppm_project_meta proj_meta ON Project.id = proj_meta.project_id";
191 + // SAFE search condition
192 + $search_sql = $wpdb->prepare(
193 + "(Project.project_name LIKE %s
194 + OR proj_statuses.name LIKE %s
195 + OR proj_categories.name LIKE %s
196 + OR user.display_name LIKE %s)",
197 + $search_tag_text,
198 + $search_tag_text,
199 + $search_tag_text,
200 + $search_tag_text
201 + );
202 + if ($current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin') {
203 + // ✅ Admin (safe)
204 + $where = " WHERE $wppm_pl_filter AND $search_sql";
205 + } else {
206 + // ✅ Non-admin (safe)
207 + $where = $wpdb->prepare(
208 + " WHERE $wppm_pl_filter
209 + AND $search_sql
210 + AND (
211 + FIND_IN_SET(%d, Project.users) > 0
212 + OR (
213 + proj_meta.meta_key = 'public_project'
214 + AND proj_meta.meta_value = 1
215 + )
216 + OR Project.created_by = %d
217 + )",
218 + $current_user->ID,
219 + $cu_id
220 + );
221 + }
222 +} else {
223 + if ($sort_by == 'project_name' || $sort_by == 'start_date' || $sort_by == 'end_date') {
224 + $query = "SELECT Project.*
225 + FROM {$wpdb->prefix}wppm_project AS Project
226 + LEFT JOIN {$wpdb->prefix}wppm_project_meta proj_meta ON Project.id = proj_meta.project_id";
227 + } else {
228 + $query = "SELECT Project.*
229 + FROM {$wpdb->prefix}wppm_project AS Project
230 + LEFT JOIN {$wpdb->prefix}wppm_project_statuses proj_statuses ON Project.status = proj_statuses.id
231 + LEFT JOIN {$wpdb->prefix}wppm_project_categories proj_categories ON Project.cat_id = proj_categories.id
232 + LEFT JOIN {$wpdb->prefix}wppm_project_meta proj_meta ON Project.id = proj_meta.project_id";
233 + }
234 + if ($current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin') {
235 + $where = " WHERE $wppm_pl_filter";
236 + } else {
237 + $where = $wpdb->prepare(
238 + " WHERE $wppm_pl_filter
239 + AND (
240 + FIND_IN_SET(%d, Project.users) > 0
241 + OR (
242 + proj_meta.meta_key = 'public_project'
243 + AND proj_meta.meta_value = 1
244 + )
245 + OR Project.created_by = %d
246 + )",
247 + $current_user->ID,
248 + $cu_id
249 + );
250 + }
136 251 }
252 +$archived_where = '';
253 +if ( isset( $is_archieved ) && $is_archieved === 1 ) {
254 + $archived_where = ' AND Project.is_archived = 1';
255 +} else {
256 + $archived_where = ' AND Project.is_archived = 0';
257 +}
258 +$where .= $archived_where;
137 259 $no_of_rows = ( "SELECT count(*) FROM ($query");
138 260 $no_of_rows = apply_filters('wppm_project_list_no_of_rows',$no_of_rows,$wppm_pl_filter,$search_tag);
139 261 $where = apply_filters('wppm_project_list_query_where',$where, $wppm_pl_filter,$search_tag);
140 262 $query .= $where." Group by Project.id ORDER BY $sort_by $order";
@@ -159,13 +281,17 @@
159 281 <div id="wppm_project_list_container" class="wppm_bootstrap">
160 282 <div class="row">
161 283 <div class="col-sm-12" id="wppm_heading_inline">
162 284 <span class="wppm-heading-inline">
163 - <?php echo esc_html_e('Projects','taskbuilder');?>
285 + <?php echo !empty($is_archieved) ? esc_html__('Archived Projects', 'taskbuilder') : esc_html__('Projects', 'taskbuilder'); ?>
164 286 </span>
165 - <?php if($current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_manager'|| $wppm_current_user_capability == 'wppm_admin' ){ ?>
166 - <img width="25" height="30" id="wppm_add_new_project_btn" class="wppm_add_new_project_btn" onclick="wppm_add_new_project()" src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/add.svg'); ?>" alt="add">
167 - <?php } ?>
287 + <?php if($wppm_can_create_project){ ?>
288 + <span class="wppm-add-new-btn btn-primary" id="wppm_add_new_project_btn" onclick="wppm_add_new_project()" 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'])?>;"><span style="margin-right:5px;"><img id="wppm_add_new_project_icon" src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/plus_icon.svg'); ?>" alt="plus_icon"></span><span><?php echo esc_html_e('Add New','taskbuilder');?></span></span>
289 + <?php } ?>
290 + <span class="wppm-add-new-btn btn-primary" id="wppm_project_list" onclick="wppm_get_project_list()" 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'])?>;"><span style="margin-right:5px;"><img id ="wppm_project_list_icon" src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/list-symbol.svg'); ?>" alt="list-symbol"></span><span><?php echo esc_html_e('Project List','taskbuilder');?></span></span>
291 + <?php if($current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_manager'|| $wppm_current_user_capability == 'wppm_admin' ){ ?>
292 + <span class="wppm-add-new-btn btn-primary"" id="wppm_archieve_project_btn" title="Archive Project" onclick="wppm_archieve_project_list()" 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'])?>;"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/archive_project.svg'); ?>" alt="archive"><span style="margin-left:5px;"><span><?php echo esc_html_e('Archive Project','taskbuilder');?></span></span>
293 + <?php } ?>
168 294 </div>
169 295 </div>
170 296 <div style="display:flex;justify-content:space-between;margin-top:20px;flex-wrap: wrap;">
171 297 <div style="display:flex;flex-wrap: wrap;">
@@ -195,22 +321,76 @@
195 321 </div>
196 322 </div>
197 323 <div class="wppm-filter-item">
198 324 <label for="wppm_project_filter"> <?php echo esc_html_e('Filter','taskbuilder');?></label>
199 - <select id="wppm_project_filter" name="wppm_project_filter" onchange="wppm_apply_project_filter()">
325 + <select id="wppm_project_filter" name="wppm_project_filter" onchange="wppm_apply_project_filter(<?php echo $is_archieved ?>)">
200 326 <option value="all"<?php echo ($filter_by == "all")? 'selected':""?>><?php echo esc_html_e('All','taskbuilder');?></option>
201 - <option style="<?php echo $new_style ?>" value="1" <?php echo ($filter_by == "1")? 'selected':""?>><?php echo esc_html_e($new_status_name,'taskbuilder');?></option>
202 - <option style="<?php echo $inp_status_style ?>" value="2" <?php echo ($filter_by == "2")? 'selected':""?>><?php echo esc_html_e($inp_status_name,'taskbuilder');?></option>
203 - <option style="<?php echo $hold_status_style ?>" value="3" <?php echo ($filter_by == "3")? 'selected':""?>><?php echo esc_html_e($hold_status_name,'taskbuilder');?></option>
204 - <option style="<?php echo $complete_status_style ?>" value="4" <?php echo ($filter_by == "4")? 'selected':""?>><?php echo esc_html_e($completed_status_name,'taskbuilder');?></option>
327 + <option style="<?php echo esc_attr($new_style) ?>" value="1" <?php echo ($filter_by == "1")? 'selected':""?>><?php echo esc_html($new_status_name);?></option>
328 + <option style="<?php echo esc_attr($inp_status_style) ?>" value="2" <?php echo ($filter_by == "2")? 'selected':""?>><?php echo esc_html($inp_status_name);?></option>
329 + <option style="<?php echo esc_attr($hold_status_style) ?>" value="3" <?php echo ($filter_by == "3")? 'selected':""?>><?php echo esc_html($hold_status_name);?></option>
330 + <option style="<?php echo esc_attr($complete_status_style) ?>" value="4" <?php echo ($filter_by == "4")? 'selected':""?>><?php echo esc_html($completed_status_name);?></option>
205 331 <option value="mine" <?php echo ($filter_by == "mine")? 'selected':""?>><?php echo esc_html_e('Mine','taskbuilder');?></option>
206 332 <option value="unassigned" <?php echo ($filter_by == "unassigned")? 'selected':""?>><?php echo esc_html_e('Unassigned','taskbuilder');?></option>
207 333 <option value="overdue" <?php echo ($filter_by == "overdue")? 'selected':""?>><?php echo esc_html_e('Overdue','taskbuilder');?></option>
208 334 </select>
209 335 </div>
336 + <div class="tb-filters" style="display:flex;margin-left: 4px;">
337 + <div class="tb-filter-bar">
338 + <span id="tb-advanced-toggle" class="tb-btn" style="margin: 10px 10px 10px 2px !important;">
339 + <?php echo esc_html_e('⚙️ Filters', 'taskbuilder'); ?>
340 + </span>
341 + <div id="tb-active-filters" class="tb-chips"></div>
342 + <div id="tb-advanced-panel" class="tb-popover">
343 + <div class="tb-mobile-header">
344 + <span><?php echo esc_html_e('Filters', 'taskbuilder'); ?></span>
345 + <button type="button" id="tb-close-filters">✕</button>
346 + </div>
347 + <div class="tb-arrow"></div>
348 + <div class="tb-section">
349 + <h4> <?php echo esc_html_e('Created By', 'taskbuilder'); ?></h4>
350 + <select id="tb-created-by" class="form-control" multiple>
351 + <?php if(!empty($pb_users)){ foreach($pb_users as $pb_user): ?>
352 + <option value="<?php echo esc_attr($pb_user->ID); ?>"><?php echo esc_html($pb_user->display_name); ?></option>
353 + <?php endforeach; } ?>
354 + </select>
355 + <h4> <?php echo esc_html_e('Co-workers', 'taskbuilder'); ?></h4>
356 + <select id="tb-assigned" class="form-control" multiple>
357 + <?php
358 + if(!empty($all_assigned_proj_users)){
359 + foreach($all_assigned_proj_users as $auid){
360 + $auser = get_userdata($auid);
361 + if($auser){ ?>
362 + <option value="<?php echo esc_attr($auid); ?>"><?php echo esc_html($auser->display_name); ?></option>
363 + <?php }
364 + }
365 + }
366 + ?>
367 + </select>
368 + </div>
369 + <div class="tb-section">
370 + <h4> <?php echo esc_html_e('Category', 'taskbuilder'); ?></h4>
371 + <select id="tb-category" class="form-control" multiple>
372 + <?php if(!empty($categories)){ foreach($categories as $pb_cat){ ?>
373 + <option value="<?php echo esc_attr($pb_cat->id); ?>"><?php echo esc_html($pb_cat->name); ?></option>
374 + <?php } } ?>
375 + </select>
376 + </div>
377 + <div class="tb-section">
378 + <h4> <?php echo esc_html_e('Date', 'taskbuilder'); ?></h4>
379 + <input type="date" class="form-control" id="tb-start-date">
380 + <input type="date" class="form-control" id="tb-end-date">
381 + </div>
382 + <div id="tb-filter-actions">
383 + <button class="wppm-submit-btn" id="tb-apply-filter" type="button"><?php echo esc_html_e('Apply', 'taskbuilder'); ?></button>
384 + <button class="wppm_reset_btn" id="tb-reset-filter" type="button"><?php echo esc_html_e('Reset', 'taskbuilder'); ?></button>
385 + </div>
386 + </div>
387 + </div>
388 + <div id="tb-backdrop"></div>
389 + </div>
210 390 <div class="wppm_display_submit">
211 391 <div class="wppm-filter-actions">
212 - <span class="wppm-link" onclick="wppm_pl_reset_filter()"> <?php echo esc_html_e('Reset','taskbuilder');?></span>
392 + <span class="wppm-link" onclick="wppm_pl_reset_filter(<?php echo $is_archieved ?>)"> <?php echo esc_html_e('Reset','taskbuilder');?></span>
213 393 </div>
214 394 </div>
215 395 </div>
216 396 </div>
@@ -268,8 +448,9 @@
268 448 </th>
269 449 <?php }?>
270 450 <th class="wppm_table_header" style="background-color:<?php echo esc_attr($appearance_settings['list-header-background-color'])?>"><span style="color:<?php echo esc_attr($appearance_settings['list-header-text-color'])?>"><?php echo esc_html_e('No. of tasks','taskbuilder'); ?></span></th>
271 451 <th class="wppm_table_header" style="background-color:<?php echo esc_attr($appearance_settings['list-header-background-color'])?>"></th>
452 + <?php do_action('wppm_project_list_extra_column_header'); ?>
272 453 </tr>
273 454 <tbody>
274 455 <?php
275 456 $total_projects=0;
@@ -278,27 +459,27 @@
278 459 foreach( $wppm_fillter as $project ){
279 460 $total_projects++;
280 461 $proejctdata = $wppmfunction->get_project($project->id);
281 462 $wppm_proj_duration = $wppmfunction->wppm_get_duration($project->start_date,$project->end_date);
282 - $pstatus= esc_sql($project->status);
463 + $pstatus= absint($project->status);
283 464 $status = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}wppm_project_statuses where id='$pstatus'" );
284 465 $users = explode(",",$project->users);
285 - $pid= esc_sql($project->id);
466 + $pid= absint($project->id);
286 467 if(isset($project->cat_id)){
287 - $pcat_id = esc_sql($project->cat_id);
468 + $pcat_id = absint($project->cat_id);
288 469 $category = $wpdb->get_var( "SELECT name FROM {$wpdb->prefix}wppm_project_categories where id='$pcat_id'" );
289 470 }
290 471 if(isset($project->id)){
291 472 if($current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin'){
292 - $no_of_tasks = $wpdb->get_var("SELECT count(*) FROM {$wpdb->prefix}wppm_task WHERE project='$pid' ");
473 + $no_of_tasks = $wpdb->get_var("SELECT count(*) FROM {$wpdb->prefix}wppm_task WHERE project='$pid' AND (parent_task_id = 0 OR parent_task_id IS NULL) ");
293 474 }else{
294 - $query =("SELECT count(*) FROM
475 + $query =("SELECT count(*) FROM
295 476 ( SELECT Task.*
296 477 FROM {$wpdb->prefix}wppm_task AS Task
297 478 Left join {$wpdb->prefix}wppm_project proj ON Task.project = proj.id
298 479 Left join {$wpdb->prefix}wppm_project_users proj_users ON Task.project = proj_users.proj_id
299 480 Left join {$wpdb->prefix}wppm_project_meta proj_meta ON proj.id = proj_meta.project_id
300 - where Task.project = '$pid' 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 ) OR (proj.id = proj_meta.project_id AND proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) OR ( Task.project = proj.id AND proj.created_by='$cu_id')) Group by Task.id ) AS Task");
481 + where Task.project = '$pid' AND (Task.parent_task_id = 0 OR Task.parent_task_id IS NULL) 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 ) OR (proj.id = proj_meta.project_id AND proj_meta.meta_key='public_project' AND proj_meta.meta_value=1) OR ( Task.project = proj.id AND proj.created_by='$cu_id')) Group by Task.id ) AS Task");
301 482 $no_of_tasks = $wpdb->get_var($query);
302 483 }
303 484 $no_of_tasks = apply_filters('wppm_no_of_task_proj_list_query',$no_of_tasks,$project->id);
304 485 }
@@ -399,10 +580,10 @@
399 580 <label for="wppm_bulk_select_<?php echo esc_attr($project->id) ?>"></label>
400 581 </div>
401 582 </div>
402 583 </td>
403 - <td onmouseover="link=true;"><?php echo esc_html_e($project->project_name,'taskbuilder') ?></td>
404 - <td onmouseover="link=true;"><span class="wppm_td_project_status" style="background-color:<?php echo esc_attr($status->bg_color);?>; color: <?php echo esc_attr($status->color); ?>"><?php echo esc_html_e($status->name,'taskbuilder') ?></span></td>
584 + <td onmouseover="link=true;"><?php echo esc_html($project->project_name) ?></td>
585 + <td onmouseover="link=true;"><span class="wppm_td_project_status" style="background-color:<?php echo esc_attr($status->bg_color);?>; color: <?php echo esc_attr($status->color); ?>"><?php echo esc_html($status->name) ?></span></td>
405 586 <td onmouseover="link=true;">
406 587 <?php
407 588 $i=0;
408 589 if(!empty(array_filter($users))){
@@ -411,9 +592,9 @@
411 592 if( $i <= 4 ){
412 593 $user_info = get_user_by('id', $user );
413 594 if(!empty($user_info)){
414 595 ?>
415 - <a href="#" title="<?php echo esc_html_e($user_info->display_name) ?>">
596 + <a href="#" title="<?php echo esc_html($user_info->display_name) ?>">
416 597 <?php echo get_avatar($user_info->ID, 25, "mysteryman");?>
417 598 </a> <?php
418 599 }
419 600 }
@@ -418,9 +599,9 @@
418 599 }
419 600 }
420 601 }
421 602 } else{
422 - _e('None','wp_projects');
603 + esc_html_e('None','taskbuilder');
423 604 }
424 605 if($i > 4){
425 606 ?>
426 607 <a href="#" class="wppm_avatar">
@@ -427,9 +608,9 @@
427 608 <span id="wppm_avatar" style="background-color:black;" class="avatar">+<?php echo esc_html($i-4) ?></span>
428 609 </a>
429 610 <?php } ?>
430 611 </td>
431 - <td onmouseover="link=true;" class="wppm_table_td"><?php echo isset($category) ? esc_html_e($category,'taskbuilder'): "" ?></td>
612 + <td onmouseover="link=true;" class="wppm_table_td"><?php echo isset($category) ? esc_html($category): "" ?></td>
432 613 <?php if($wppm_default_project_date==1 && $wppm_deafault_time_duration_project==0){ ?>
433 614 <td onmouseover="link=true;" class="wppm_table_td"><?php echo isset($proj_start_date) ? esc_html($proj_start_date): "" ?></td>
434 615 <?php
435 616 if(!empty($proj_end_date) && $project->status!=4 && $proj_end_date < $current_date && ($proj_end_date != '0000-00-00 00:00:00' && $proj_end_date != '00-00-0000 00:00:00' && $proj_end_date != '00-00-0000' && $proj_end_date != '0000-00-00')) {
@@ -453,8 +634,9 @@
453 634 <?php $style = (($current_user->ID && $current_user->has_cap('manage_options')) || ($wppmfunction->has_project_permission('delete_project',esc_attr($project->id))) || $wppm_current_user_capability == 'wppm_admin' || ($proejctdata['created_by']==$current_user->ID && $wppm_current_user_capability == 'wppm_manager') )? "display:inline":"display:none"; ?>
454 635 <span style="<?php echo esc_attr($style); ?>" onclick="wppm_delete_project(<?php echo esc_attr($project->id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/trash.svg'); ?>" alt="delete"></span>
455 636 <?php ?>
456 637 </td>
638 + <?php do_action('wppm_project_list_extra_column_cell', $project); ?>
457 639 </tr>
458 640 <?php
459 641 }
460 642 }
@@ -483,14 +665,14 @@
483 665 </span>
484 666 <span
485 667 <?php echo esc_html($prev_class) ?>
486 668 style="<?php echo (isset($prev_class) && esc_attr($prev_class) == 'disabled') ? 'display:none;':'display:block;'?>">
487 - <a class="wppm_pagination_prev" onclick="return wppm_load_prev_page(<?php echo esc_attr($prev_page_no) ?>,<?php echo esc_attr($page_no) ?>,'<?php echo esc_attr($sort_by)?>','<?php echo esc_attr($order) ?>');"><?php echo esc_html_e('PREV','taskbuilder');?></a>
669 + <a class="wppm_pagination_prev" onclick="return wppm_load_prev_page(<?php echo esc_attr($prev_page_no) ?>,<?php echo esc_attr($page_no) ?>,'<?php echo esc_attr($sort_by)?>','<?php echo esc_attr($order) ?>','<?php echo esc_attr($is_archieved)?>');"><?php echo esc_html_e('PREV','taskbuilder');?></a>
488 670 </span>
489 671 <span
490 672 <?php echo esc_attr($next_class) ?>
491 673 style="<?php echo (isset($next_class) && $next_class == 'disabled')?'display:none;':'display:block;'?>cursor:pointer;">
492 - <a class="wppm_pagination_next" onclick="return wppm_load_next_page('<?php echo esc_attr($next_page_no) ?>','<?php echo esc_attr($page_no) ?>','<?php echo esc_attr($sort_by)?>','<?php echo esc_attr($order) ?>');"><?php echo esc_html_e('NEXT','taskbuilder');?></a>
674 + <a class="wppm_pagination_next" onclick="return wppm_load_next_page('<?php echo esc_attr($next_page_no) ?>','<?php echo esc_attr($page_no) ?>','<?php echo esc_attr($sort_by)?>','<?php echo esc_attr($order) ?>','<?php echo esc_attr($is_archieved)?>');"><?php echo esc_html_e('NEXT','taskbuilder');?></a>
493 675 </span>
494 676 </div>
495 677 </div>
496 678 </div>
@@ -511,15 +693,111 @@
511 693 }
512 694 #wppm_project_table tr:hover td{
513 695 color: <?php echo esc_attr($appearance_settings['list-item-hover-text-color'])?>!important;
514 696 }
697 + #wppm_add_new_project_btn:hover,#wppm_project_list:hover,#wppm_archieve_project_btn:hover{
698 + background-color: <?php echo esc_attr($appearance_settings['list-header-button-hover-color'])?>!important;
699 + }
515 700 </style>
516 701 <script type="text/javascript">
517 702 jQuery( document ).ready( function( jQuery ) {
703 + let createdBy = <?php echo wp_json_encode(array_map('strval', $advanced_filter['created_by'] ?? [])); ?>;
704 + let assignedUsers = <?php echo wp_json_encode(array_map('strval', $advanced_filter['assigned'] ?? [])); ?>;
705 + let categoryIds = <?php echo wp_json_encode(array_map('strval', $advanced_filter['category'] ?? [])); ?>;
706 + jQuery('#tb-created-by').select2({ width: '100%', dropdownParent: jQuery('#tb-advanced-panel') });
707 + jQuery('#tb-assigned').select2({ width: '100%', dropdownParent: jQuery('#tb-advanced-panel') });
708 + jQuery('#tb-category').select2({ width: '100%', dropdownParent: jQuery('#tb-advanced-panel') });
709 + jQuery('#tb-created-by').val(createdBy).trigger('change');
710 + jQuery('#tb-assigned').val(assignedUsers).trigger('change');
711 + jQuery('#tb-category').val(categoryIds).trigger('change');
712 + jQuery('#tb-start-date').val('<?php echo esc_attr($advanced_filter['start_date'] ?? ''); ?>');
713 + jQuery('#tb-end-date').val('<?php echo esc_attr($advanced_filter['end_date'] ?? ''); ?>');
714 +
715 + window.projectFilters = window.projectFilters || {
716 + created_by: createdBy,
717 + assigned: assignedUsers,
718 + category: categoryIds,
719 + start_date: '<?php echo esc_js($advanced_filter['start_date'] ?? ''); ?>',
720 + end_date: '<?php echo esc_js($advanced_filter['end_date'] ?? ''); ?>'
721 + };
722 +
723 + jQuery(document).off("click", "#tb-apply-filter").on("click", "#tb-apply-filter", function (e) {
724 + e.preventDefault();
725 + window.projectFilters = {
726 + created_by: jQuery("#tb-created-by").val() || [],
727 + assigned: jQuery("#tb-assigned").val() || [],
728 + category: jQuery("#tb-category").val() || [],
729 + start_date: jQuery("#tb-start-date").val() || "",
730 + end_date: jQuery("#tb-end-date").val() || ""
731 + };
732 + renderActiveFilters(window.projectFilters);
733 + setProjectListFilterCookie(window.projectFilters);
734 + triggerProjectFilter(1, window.projectFilters, <?php echo (int) $is_archieved; ?>);
735 + });
736 +
737 + jQuery(document).off("click", ".tb-remove").on("click", ".tb-remove", function () {
738 + let key = jQuery(this).attr("data-key");
739 + let value = jQuery(this).attr("data-value");
740 + if (key === "date") {
741 + window.projectFilters.start_date = "";
742 + window.projectFilters.end_date = "";
743 + jQuery("#tb-start-date").val("");
744 + jQuery("#tb-end-date").val("");
745 + } else {
746 + window.projectFilters[key] = (window.projectFilters[key] || [])
747 + .map(String)
748 + .filter(v => v !== String(value));
749 + jQuery(`#tb-${key}`).val(window.projectFilters[key]).trigger("change");
750 + }
751 + jQuery(this).closest(".tb-chip").remove();
752 + syncUIWithFilters(window.projectFilters);
753 + setProjectListFilterCookie(window.projectFilters);
754 + triggerProjectFilter(1, window.projectFilters, <?php echo (int) $is_archieved; ?>);
755 + });
756 +
757 + jQuery(document).off("click", "#tb-reset-filter").on("click", "#tb-reset-filter", function () {
758 + resetProjectFilters(<?php echo (int) $is_archieved; ?>);
759 + });
760 +
761 + let savedProjectFilters = getProjectListFilterCookie();
762 + if (savedProjectFilters && typeof savedProjectFilters === "object") {
763 + window.projectFilters = {
764 + created_by: savedProjectFilters.created_by || [],
765 + assigned: savedProjectFilters.assigned || [],
766 + category: savedProjectFilters.category || [],
767 + start_date: savedProjectFilters.start_date || "",
768 + end_date: savedProjectFilters.end_date || ""
769 + };
770 + }
771 + setTimeout(function () {
772 + syncUIWithFilters(window.projectFilters);
773 + renderActiveFilters(window.projectFilters);
774 + }, 100);
775 +
776 + jQuery(document).off("click", "#tb-advanced-toggle").on("click", "#tb-advanced-toggle", function (e) {
777 + e.stopPropagation();
778 + jQuery("#tb-advanced-panel").toggleClass("tb-open");
779 + });
780 + jQuery(document).off("click", "#tb-backdrop").on("click", "#tb-backdrop", function () {
781 + jQuery("#tb-advanced-panel").removeClass("tb-open");
782 + jQuery(this).removeClass("active");
783 + });
784 + jQuery(document).off("click.tbProjOutside").on("click.tbProjOutside", function (e) {
785 + if (window.innerWidth > 768) {
786 + if (!jQuery(e.target).closest("#tb-advanced-panel, #tb-advanced-toggle").length) {
787 + jQuery("#tb-advanced-panel").removeClass("tb-open");
788 + }
789 + }
790 + });
791 + jQuery(document).off("click", "#tb-close-filters").on("click", "#tb-close-filters", function () {
792 + jQuery("#tb-advanced-panel").removeClass("tb-open");
793 + jQuery("#tb-backdrop").removeClass("active");
794 + });
795 +
518 796 jQuery("input[name='wppm_project_search_filter']").keypress(function(e) {
519 797 //Enter key
520 798 if (e.which == 13) {
521 - wppm_project_search_filter();
799 + wppm_project_search_filter(<?php echo $is_archieved ?>);
522 800 }
523 801 });
524 802 jQuery("#wppm_proj_name_th").hover(function(){
525 803 jQuery('#wppm_chevron_sort_up_project_name_img').show();