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/open_task/wppm_open_task.php +769 -190 4.0.96.0.6 View file →
@@ -3,10 +3,12 @@
3 3 exit; // Exit if accessed directly
4 4 }
5 5
6 6 global $current_user,$wpdb,$wppmfunction;
7 -$id = isset($_POST) && isset($_POST['id']) ? intval(sanitize_text_field($_POST['id'])) : "0";
7 +$id = isset($_POST) && isset($_POST['id']) ? intval(sanitize_text_field(wp_unslash($_POST['id']))) : "0";
8 +$page = isset($_POST) && isset($_POST['page']) ? sanitize_text_field(wp_unslash($_POST['page'])) : '';
8 9 $task_list_view = get_option('wppm_default_task_list_view');
10 +$project_id = isset($_POST) && isset($_POST['project_id']) ? intval(sanitize_text_field($_POST['project_id'])) : "0";
9 11 $wppm_default_task_date = get_option('wppm_default_task_date');
10 12 $wppm_task_time = get_option('wppm_task_time');
11 13 $appearance_settings = get_option("wppm-ap-individual-task");
12 14 $wppm_tinymce_visibility_open_task = get_option('wppm_tinymce_visibility_open_task');
@@ -14,15 +16,16 @@
14 16 $wppm_rich_text_editor = get_option('wppm_rich_text_editor');
15 17 $wppm_toolbar_actions = get_option('wppm_toolbar_actions');
16 18 $wppm_date_setting = get_option('wppm_date_setting');
17 19 $wppm_task_hide_comment_section = get_option('wppm_task_hide_comment_section');
20 +$wppm_deafault_time_duration_task = get_option('wppm_display_time_duration_task');
18 21 $url_auth = false;
19 22 $auth_id = $wppmfunction->wppm_get_auth_code($id);
20 23 $auth_id = sanitize_text_field($auth_id);
21 24 // url authentication.
22 -$auth_code = isset( $_POST['auth-code'] ) ? sanitize_text_field( $_POST['auth-code'] ) : ''; // phpcs:ignore
25 +$auth_code = isset( $_POST['auth-code'] ) ? sanitize_text_field( wp_unslash($_POST['auth-code'] ) ) : ''; // phpcs:ignore
23 26 if ( ! $auth_code ) {
24 - $auth_code = isset( $_POST['auth_code'] ) ? sanitize_text_field( $_POST['auth_code'] ) : ''; // phpcs:ignore
27 + $auth_code = isset( $_POST['auth_code'] ) ? sanitize_text_field( wp_unslash($_POST['auth_code'] ) ) : ''; // phpcs:ignore
25 28 }
26 29
27 30 if ( $auth_code && $auth_id == $auth_code ) {
28 31 $url_auth = true;
@@ -27,37 +30,40 @@
27 30 if ( $auth_code && $auth_id == $auth_code ) {
28 31 $url_auth = true;
29 32 }
30 33 if (!(($current_user->ID && $current_user->has_cap('manage_options')) || ($wppmfunction->has_permission('view_task',$id)) || ($url_auth==true))) { ?>
31 - <div style="align-item:center;" ><h6><?php esc_attr_e( 'Unauthorized access!', 'taskbuilder' ); ?></h6></div>
34 + <div style="text-align:center;padding:20px 0;">
35 + <h6><?php esc_attr_e( 'Unauthorized access!', 'taskbuilder' ); ?></h6>
36 + <a href="<?php echo esc_url( admin_url('admin.php?page=wppm-tasks') ); ?>" class="btn btn-success btn-sm"><?php esc_html_e( 'Go to Task List', 'taskbuilder' ); ?></a>
37 + </div>
32 38 <?php
33 39 wp_die();
34 40 }
35 -$proj_id = isset($_POST) && isset($_POST['proj_id']) ? intval(sanitize_text_field($_POST['proj_id'])) : 0;
36 -$current_date = date('Y-m-d');
41 +$proj_id = isset($_POST) && isset($_POST['proj_id']) ? intval(sanitize_text_field(wp_unslash($_POST['proj_id']))) : 0;
42 +$current_date = wp_date('Y-m-d');
37 43 $wppm_current_user_capability = get_user_meta( $current_user->ID, 'wppm_capability', true );
38 -$cu_id = $current_user->ID;
44 +$cu_id = absint($current_user->ID);
39 45 if(!empty($id)){
40 - $task = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}wppm_task where id='".esc_sql($id)."'");
46 + $task = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_task where id=%d",$id));
41 47 $project_data = $wppmfunction->get_project($task->project);
42 - $task_comment = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}wppm_task_comment where task_id='".esc_sql($id)."' ORDER BY create_time DESC");
43 - $orderby_proj_sql = esc_sql(sanitize_sql_orderby( "create_time DESC" ));
44 - $task_comment = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}wppm_task_comment where task_id='".esc_sql($id)."' ORDER BY ". $orderby_proj_sql);
45 - $task_proj = isset($task->project) ? esc_sql($task->project) :"";
46 - $task_id = isset($task->id) ? esc_sql($task->id):"";
48 + $task_comment = $wpdb->get_results( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_task_comment where task_id=%d ORDER BY create_time DESC",$id));
49 + $orderby_proj_sql = (sanitize_sql_orderby( "create_time DESC" ));
50 + $task_comment = $wpdb->get_results( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_task_comment where task_id=%d ORDER BY ". $orderby_proj_sql,$id));
51 + $task_proj = isset($task->project) ? absint($task->project) :"";
52 + $task_id = isset($task->id) ? absint($task->id):"";
47 53 }
48 -$user_role = $wpdb->get_var( "SELECT role_id FROM {$wpdb->prefix}wppm_project_users where proj_id = '$task_proj' AND user_id = '$cu_id'");
54 +$user_role = $wpdb->get_var( $wpdb->prepare("SELECT role_id FROM {$wpdb->prefix}wppm_project_users where proj_id = %d AND user_id = %d",$task_proj,$cu_id));
49 55 if(!empty($task_proj)){
50 - $project_name = $wpdb->get_var( "SELECT project_name FROM {$wpdb->prefix}wppm_project where id= '$task_proj'");
56 + $project_name = $wpdb->get_var( $wpdb->prepare("SELECT project_name FROM {$wpdb->prefix}wppm_project where id= %d",$task_proj));
51 57 }
52 -$wppm_checklist=$wpdb->get_results( "SELECT * FROM {$wpdb->prefix}wppm_checklist where task_id='$task_id'" );
58 +$wppm_checklist=$wpdb->get_results( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_checklist where task_id=%d",$task_id));
53 59 if(!empty($task->status)){
54 - $task_status_var = esc_sql($task->status);
55 - $task_status = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}wppm_task_statuses where id='$task_status_var'");
60 + $task_status_var = absint($task->status);
61 + $task_status = $wpdb->get_row( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_task_statuses where id=%d",$task_status_var));
56 62 }
57 63 if(!empty($task->priority)){
58 - $task_priority_var = esc_sql($task->priority);
59 - $task_priority = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}wppm_task_priorities where id='$task_priority_var'");
64 + $task_priority_var = absint($task->priority);
65 + $task_priority = $wpdb->get_row( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_task_priorities where id=%d",$task_priority_var));
60 66 }
61 67 if(!empty($task->users)){
62 68 $users = explode(",",$task->users);
63 69 }
@@ -62,9 +68,9 @@
62 68 $users = explode(",",$task->users);
63 69 }
64 70
65 71 if(!empty($task->description)){
66 - $task_description = stripslashes((htmlspecialchars_decode($task->description, ENT_QUOTES)));
72 + $task_description = !empty($task->description) ? wp_kses_post(wpautop($task->description)) : '';
67 73 }
68 74
69 75 if($wppm_task_time == 1){
70 76 $tsDate = new DateTime($task->start_date);
@@ -152,9 +158,9 @@
152 158 }
153 159 }
154 160 }
155 161 $flag = false;
156 -$wppm_task_fillter = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}wppm_task where id='".esc_sql($id)."'");
162 +$wppm_task_fillter = $wpdb->get_results( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_task where id=%d",$id));
157 163 if(!empty($wppm_task_fillter)){
158 164 foreach($wppm_task_fillter as $key_filter=>$val_filter){
159 165 $val_array = (array) $val_filter;
160 166 $tusers = $val_array['users'];
@@ -159,12 +165,12 @@
159 165 $val_array = (array) $val_filter;
160 166 $tusers = $val_array['users'];
161 167 $tusers_arr = explode(',',$tusers);
162 168 $tproject_id = $val_array['project'];
163 - $tproject_id = esc_sql($tproject_id);
169 + $tproject_id = absint($tproject_id);
164 170 if(!empty($tusers) && in_array($current_user->ID,$tusers_arr)){
165 - $project_user_role = $wpdb->get_var("SELECT role_id FROM {$wpdb->prefix}wppm_project_users WHERE proj_id = '$tproject_id' AND user_id = '$cu_id'");
166 - $project_users = $wpdb->get_var("SELECT users FROM {$wpdb->prefix}wppm_project WHERE id = '$tproject_id'");
171 + $project_user_role = $wpdb->get_var( $wpdb->prepare("SELECT role_id FROM {$wpdb->prefix}wppm_project_users WHERE proj_id = %d AND user_id = %d",$tproject_id,$cu_id));
172 + $project_users = $wpdb->get_var( $wpdb->prepare("SELECT users FROM {$wpdb->prefix}wppm_project WHERE id = %d",$tproject_id));
167 173 $project_users_arr = explode(',',(string)$project_users);
168 174 if((!empty($project_user_role)) && ($project_user_role == 1) && in_array($current_user->ID,$project_users_arr)){
169 175 $flag= true;
170 176 break;
@@ -171,43 +177,73 @@
171 177 }
172 178 }
173 179 }
174 180 }
175 -$project_creator = $wpdb->get_var("SELECT created_by FROM {$wpdb->prefix}wppm_project WHERE created_by = '$cu_id'");
181 +$project_creator = $wpdb->get_var( $wpdb->prepare("SELECT created_by FROM {$wpdb->prefix}wppm_project WHERE created_by = %d",$cu_id));
176 182 ?>
177 183 <form id="wppm_open_task" method="post">
184 + <div id="wppm_alert_success" class="alert alert-success wppm_alert" style="display:none;" role="alert">
185 + <img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/success.svg'); ?>" alt="success"> <span class="wppm_alert_text"></span>
186 + </div>
187 + <div id="wppm_alert_error" class="alert alert-danger wppm_alert" style="display:none;" role="alert">
188 + <img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/warning-triangle.svg'); ?>" alt="warning-triangle"> <span class="wppm_alert_text"></span>
189 + </div>
178 190 <div class="wppm_headers row">
179 191 <div class="col-sm-8">
180 192 <span class="wppm-heading-inline">
181 193 <?php echo esc_html_e('Task','taskbuilder');?>
182 194 </span><?php
183 - if($current_user->has_cap('manage_options') || $wppmfunction->has_permission('add_new_task',$task_id) || ($flag==true) || $project_creator!=""){
195 + if(($current_user->has_cap('manage_options') || $wppmfunction->has_permission('add_new_task',$task_id) || ($flag==true) || $project_creator!="") && $task->is_archived!=1){
184 196 $style = "display:inline;";
185 197 }else{
186 198 $style = "display:none;";
187 199 }
188 200 $style = apply_filters('wppm_add_new_task_btn_style_open_task_form',$style);
201 + if(($wppm_task_fillter && (!empty($project_user_role)) && ($project_user_role == 1) && in_array($current_user->ID,$project_users_arr)) || $wppm_current_user_capability == 'wppm_admin'|| $wppm_current_user_capability == 'wppm_manager' || $current_user->has_cap('manage_options') || $project_data['created_by']==$current_user->ID){
202 + $archive_style= "display:inline;";
203 + }else{
204 + $archive_style= "display:none;";
205 + }
189 206 if($proj_id==0) {
190 - ?> <span onclick="wppm_add_new_task(<?php echo esc_attr($proj_id) ?>)" class="wppm_add_new_task_btn" id="wppm_add_new_task_btn" style="<?php echo $style?>" title="Create Task"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/plus.svg'); ?>" alt="add"></span>
207 + ?> <span onclick="wppm_add_new_task(<?php echo esc_attr($proj_id) ?>,<?php echo esc_attr($project_id) ?>)" class="wppm_add_new_task_btn" id="wppm_add_new_task_btn" style="<?php echo esc_attr($style)?>" title="<?php esc_attr_e( 'Create Task', 'taskbuilder' ); ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/plus.svg'); ?>" alt="add"></span>
191 208 <?php }
192 209 else{ ?>
193 - <span class="wppm_add_new_task_btn" id="wppm_add_new_task_btn" title="Create Task" onclick="wppm_create_project_task(<?php echo esc_attr($proj_id) ?>)" style="<?php echo $style ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/plus.svg'); ?>" alt="add"></span>
210 + <span class="wppm_add_new_task_btn" id="wppm_add_new_task_btn" title="<?php esc_attr_e( '"Create Task', 'taskbuilder' ); ?>" onclick="wppm_create_project_task(<?php echo esc_attr($proj_id) ?>)" style="<?php echo esc_attr($style) ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/plus.svg'); ?>" alt="add"></span>
194 211 <?php } ?>
195 - <?php if($proj_id==0) {
196 - $task_list_function = ($task_list_view==1)?"wppm_get_task_list()":"wppm_view_task_search_filter()";
212 + <?php if($proj_id==0) {
213 + if (($project_id!=0)) {
214 + $task_list_function = "wppm_get_project_tasks_kanban_view( {$project_id})";
215 + }
216 + if (empty($project_id) && $task_list_view == 1) {
217 + $task_list_function = "wppm_get_task_list('', {$project_id})";
218 + }
219 + if(empty($task_list_view) && empty($project_id)) {
220 + $task_list_function = "wppm_view_task_search_filter('', '', {$project_id})";
221 + }
197 222 ?>
198 - <span class="wppm-task-list-btn" id="wppm_task_list_btn" title="Task List" onclick="<?php echo $task_list_function ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/list.svg'); ?>" alt="list"></span>
223 + <span class="wppm-task-list-btn" id="wppm_task_list_btn" title="<?php esc_attr_e( 'Task List', 'taskbuilder' ); ?>"onclick="<?php echo esc_attr($task_list_function) ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/list.svg'); ?>" alt="list"></span>
199 224 <?php }
200 225 else{
201 226 ?>
202 - <span class="wppm-task-list-btn" id="wppm_task_list_btn" title="Task List" onclick="wppm_get_project_tasks(<?php echo esc_attr($proj_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/list.svg'); ?>" alt="list"></span>
227 + <span class="wppm-task-list-btn" id="wppm_task_list_btn" title="<?php esc_attr_e( 'Task List', 'taskbuilder' ); ?>" onclick="wppm_get_project_tasks(<?php echo esc_attr($proj_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/list.svg'); ?>" alt="list"></span>
203 228 <?php } ?>
204 - <?php $style = (($current_user->ID && $current_user->has_cap('manage_options')) || ($wppmfunction->has_permission('delete_task',$id)) || $wppm_current_user_capability == 'wppm_admin'|| $project_data['created_by']==$current_user->ID )? "display:inline":"display:none"; ?>
205 - <?php $clone_style = (($current_user->ID && $current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin') || ($wppmfunction->has_permission('clone_task',$id)) || $project_data['created_by']==$current_user->ID )? "display:inline":"display:none"; ?>
206 - <span class="wppm-delete_task_btn" id="wppm_delete_task_btn" title="Delete Task" onclick="wppm_get_delete_task(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>)" style="<?php echo esc_attr($style) ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/bin.svg'); ?>" alt="delete"></span>
207 - <div class="wppm-clone_task_btn" id="wppm_clone_task_btn" title="Clone Task" onclick="wppm_clone_task(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id)?>)" style="<?php echo esc_attr($clone_style) ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/duplicate.svg'); ?>" alt="clone"></div>
229 + <?php $style = ((($current_user->ID && $current_user->has_cap('manage_options')) || ($wppmfunction->has_permission('delete_task',$id)) || $wppm_current_user_capability == 'wppm_admin'|| $project_data['created_by']==$current_user->ID ) && $user_role != 3) ? "display:inline":"display:none"; ?>
230 + <?php $clone_style = ((($current_user->ID && $current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin') || ($wppmfunction->has_permission('clone_task',$id)) || $project_data['created_by']==$current_user->ID ) && $task->is_archived!=1 && $user_role != 3) ? "display:inline":"display:none"; ?>
231 + <?php $ar_css = ($task->is_archived==1) ? "display:none;" : "display:inline"; ?>
232 + <span class="wppm-dashboard-btn" id="wppm_dashboard_btn" title="<?php esc_attr_e( 'Dashboard', 'taskbuilder' ); ?>" onclick="wppm_get_project_tasks(<?php echo esc_attr($proj_id) ?>)">
233 + <a href="<?php echo esc_url(admin_url('admin.php?page=wppm-dashboard')); ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/dashboard-icon.svg'); ?>" alt="dashboard"></a>
234 + </span>
235 + <span class="wppm-delete_task_btn" id="wppm_delete_task_btn" title="Delete Task" onclick="wppm_get_delete_task(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>,<?php echo esc_attr($project_id) ?>)" style="<?php echo esc_attr($style) ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/bin.svg'); ?>" alt="delete"></span>
236 + <span class="wppm-clone_task_btn" id="wppm_clone_task_btn" title="Clone Task" onclick="wppm_clone_task(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id)?>,<?php echo esc_attr($project_id) ?>)" style="<?php echo esc_attr($clone_style) ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/duplicate.svg'); ?>" alt="clone"></span>
237 + <span class="wppm-print_task_btn" id="wppm_print_task_btn" title="Print Task" onclick="wppm_print_task(<?php echo esc_attr($id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/printer_menu.svg'); ?>" alt="print" style="<?php echo esc_attr($ar_css);?>"></span>
238 + <span class="wppm-archieve_task_btn" id="wppm_archieve_task_btn" title="<?php echo ($task->is_archived==1 ) ? 'Restore Task' : 'Archive Task'; ?>" onclick="wppm_archive_task(<?php echo esc_attr($id) ?>,<?php echo esc_attr($task->is_archived) ?>,<?php echo esc_attr($project_id) ?>)" style="<?php echo esc_attr($archive_style) ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/archive.svg'); ?>" alt="archive"></span>
239 + <input type="hidden" name="wppm_archive_task_ajax_nonce" id="wppm_archive_task_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_archive_task_ajax_nonce' ) ); ?>">
240 + <div class="menu" id="wppmprint_menu" onclick="event.stopPropagation();">
241 + <a href="#" id="wppm_openPDF" onclick="wppm_open_pdf(<?php echo esc_attr($id) ?>)">🖨️ <?php echo esc_html_e('Open In Browser','taskbuilder');?></a>
242 + <a href="#" id="wppm_downloadPDF" onclick="wppm_download_pdf(<?php echo esc_attr($id) ?>)">💾 <?php echo esc_html_e('Download PDF','taskbuilder');?></a>
243 + </div>
208 244 <?php do_action('wppm_individual_task_button',$id);?>
209 - </div>
245 + </div>
210 246 </div>
211 247 <div id="wppm_load_individual_task_container" class="row">
212 248 <div class="col-sm-8 wppm_body col-md-9">
213 249 <div class="wppm_task_details_container">
@@ -212,13 +248,28 @@
212 248 <div class="col-sm-8 wppm_body col-md-9">
213 249 <div class="wppm_task_details_container">
214 250 <div class="row">
215 251 <div class="col-sm-12">
216 - <span class="wppm_task_label"> <?php echo esc_html_e($task->task_name,'taskbuilder');
217 - if ($wppmfunction->has_permission('change_task_details',$id) || $current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin') { ?>
218 - <span id="wppm_individual_edit_task_subject" onclick="wppm_edit_task_details(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>)" class="btn btn-sm wppm_action_btn" style="background-color:#FFFFFF !important;color:#000000 !important;"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/edit_01.svg'); ?>" alt="edit"></span>
252 + <span class="wppm_task_label"> <?php echo isset($task->task_name) ? esc_html($task->task_name ):"" ?>
253 + <?php if (($wppmfunction->has_permission('change_task_details',$id) || $current_user->has_cap('manage_options') || $wppm_current_user_capability == 'wppm_admin') && $task->is_archived!=1) { ?>
254 + <span id="wppm_individual_edit_task_subject" onclick="wppm_edit_task_details(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>,<?php echo esc_attr($project_id) ?>)" class="btn btn-sm wppm_action_btn" style="background-color:#FFFFFF !important;color:#000000 !important;"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/edit_01.svg'); ?>" alt="edit"></span>
219 255 <?php } ?>
220 256 </span>
257 + <?php if(!empty($task->parent_task_id)){
258 + $wppm_parent_task = $wpdb->get_row( $wpdb->prepare("SELECT id, task_name FROM {$wpdb->prefix}wppm_task where id=%d",absint($task->parent_task_id)));
259 + if(!empty($wppm_parent_task)){
260 + $wppm_can_convert_subtask = (($current_user->has_cap('manage_options') || $wppmfunction->has_permission('delete_task',$id)) && $task->is_archived!=1);
261 + ?>
262 + <div class="wppm_subtask_parent_link">
263 + <?php echo esc_html_e('Subtask of','taskbuilder');?>
264 + <a href="#" onclick="wppm_open_subtask(<?php echo esc_attr($wppm_parent_task->id) ?>,<?php echo esc_attr($proj_id) ?>);return false;"><?php echo esc_html($wppm_parent_task->task_name); ?></a>
265 + <?php if($wppm_can_convert_subtask){ ?>
266 + &nbsp;|&nbsp;<a href="#" onclick="wppm_convert_subtask_to_task(<?php echo esc_attr($id) ?>,<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>);return false;"><?php echo esc_html_e('Convert to Task','taskbuilder');?></a>
267 + <input type="hidden" name="wppm_convert_subtask_to_task_ajax_nonce" id="wppm_convert_subtask_to_task_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_convert_subtask_to_task' ) ); ?>">
268 + <?php } ?>
269 + </div>
270 + <?php }
271 + } ?>
221 272 </div>
222 273 </div>
223 274 <div class="row">
224 275 <div class="col-sm-3">
@@ -224,9 +275,9 @@
224 275 <div class="col-sm-3">
225 276 <span class="wppm_task_details_label"><?php echo esc_html_e('Project:','taskbuilder');?></span>
226 277 </div>
227 278 <div class="col-sm-9">
228 - <span class="wppm_task_details"><?php echo (isset($project_name))? esc_html_e($project_name,'taskbuilder'):"" ?></span>
279 + <span class="wppm_task_details"><?php echo (isset($project_name))? esc_html($project_name ):"" ?></span>
229 280 </div>
230 281 </div>
231 282 <div class="row">
232 283 <div class="col-sm-3">
@@ -257,9 +308,9 @@
257 308 } ?>
258 309 <span class="wppm_task_details"><?php echo (isset($task_create_date))? esc_html($task_create_date):"" ?></span>
259 310 </div>
260 311 </div>
261 - <?php if($wppm_default_task_date == 1){ ?>
312 + <?php if($wppm_default_task_date == 1 && $wppm_deafault_time_duration_task==0){ ?>
262 313 <div class="row">
263 314 <div class="col-sm-3">
264 315 <span class="wppm_task_details_label"><?php echo esc_html_e('Start Date:','taskbuilder');?></span>
265 316 </div>
@@ -277,15 +328,28 @@
277 328 <span class="wppm_task_details" id="wppm_edit_tend_date" style="<?php echo esc_attr($style); ?>"><?php echo (isset($task_end_date))? esc_html($task_end_date):"" ?></span>
278 329 </div>
279 330 <input type="hidden" name="wppm_edit_tend_date_ajax_nonce" id="wppm_edit_tend_date_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_set_change_task_end_date' ) ); ?>">
280 331 </div>
281 - <?php } ?>
332 + <?php }
333 + if($wppm_deafault_time_duration_task==1){
334 + $wppm_task_duration = $wppmfunction->wppm_get_duration($task->start_date,$task->end_date);
335 + $tstatus = isset($task->status) ? $task->status :"";
336 + $style = (!empty($task->end_date) && $tstatus!=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')) ? "color:#FF1111":"color:#2C3E51"; ?>
337 + <div class="row">
338 + <div class="col-sm-3">
339 + <span class="wppm_task_details_label"><?php echo esc_html_e('Task Duration:','taskbuilder');?></span>
340 + </div>
341 + <div class="col-sm-9">
342 + <span class="wppm_task_details" id="wppm_edit_task_duration" style="<?php echo esc_attr($style); ?>"><?php echo (isset($wppm_task_duration))? esc_html($wppm_task_duration ): "" ?></span>
343 + </div>
344 + </div> <?php
345 + }?>
282 346 <div class="row">
283 347 <div class="col-sm-3">
284 348 <span class="wppm_task_details_label"><?php echo esc_html_e('Task Priority:','taskbuilder');?></span>
285 349 </div>
286 350 <div class="col-sm-9">
287 - <span class="wppm_task_details_priority"><span class="wppm_admin_label" style="background-color:<?php echo (isset($task_priority->bg_color))? esc_html($task_priority->bg_color):""?>;color:<?php echo (isset($task_priority->color))? esc_html($task_priority->color):""?>;"><?php echo (isset($task_priority->name)) ? esc_html_e($task_priority->name,'taskbuilder'):"" ?> </span></span>
351 + <span class="wppm_task_details_priority"><span class="wppm_admin_label" style="background-color:<?php echo (isset($task_priority->bg_color))? esc_html($task_priority->bg_color):""?>;color:<?php echo (isset($task_priority->color))? esc_html($task_priority->color):""?>;"><?php echo (isset($task_priority->name)) ? esc_html($task_priority->name):"" ?> </span></span>
288 352 </div>
289 353 </div>
290 354 <div class="row">
291 355 <div class="col-sm-3">
@@ -291,13 +355,173 @@
291 355 <div class="col-sm-3">
292 356 <span class="wppm_task_details_label"><?php echo esc_html_e('Description:','taskbuilder');?></span>
293 357 </div>
294 358 <div class="col-sm-9">
295 - <span class="wppm_task_description"><?php echo (isset($task_description))? wp_kses_post(wpautop($task_description)):"" ?></span>
359 + <span class="wppm_task_description"><?php echo (!empty($task_description))? wp_kses_post(wpautop($task_description)):"" ?></span>
296 360 </div>
297 361 </div>
298 362 <?php do_action('wppm_after_task_details_in_open_task',$task->id, $task->project);?>
299 363 </div>
364 + <?php if(empty($task->parent_task_id)){
365 + $wppm_subtasks = $wppmfunction->get_subtasks($task_id);
366 + $wppm_subtask_progress = $wppmfunction->get_subtask_progress($task_id);
367 + $wppm_default_task_status = get_option('wppm_default_task_status');
368 + $wppm_can_add_subtask = (($current_user->has_cap('manage_options') || $wppmfunction->has_permission('add_new_task',$task_id)) && $task->is_archived!=1 && $user_role != 3);
369 + ?>
370 + <div class="wppm_task_subtask_container" id="wppm_task_subtask_container">
371 + <div class="row">
372 + <div class="col-sm-8">
373 + <span class="wppm_checklist_label"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/task_list.svg'); ?>" alt="subtasks"><?php echo esc_html_e('Subtasks','taskbuilder');?></span>
374 + </div>
375 + </div>
376 + <?php if($wppm_subtask_progress['total'] > 0){
377 + $wppm_subtask_percent = round(($wppm_subtask_progress['completed'] / $wppm_subtask_progress['total']) * 100); ?>
378 + <div class="wppm_progress_bar_container row">
379 + <div class="col-sm-4">
380 + <span class="wppm_progressbar_label" id="wppm_subtask_progress_label"><?php echo esc_html($wppm_subtask_progress['completed'].'/'.$wppm_subtask_progress['total']); ?></span>
381 + </div>
382 + <div class="wppm_progress_bar col-sm-8">
383 + <div id="wppm_subtask_progressbar" class="wppm_checkprogress" role="progressbar" style="width: <?php echo esc_attr($wppm_subtask_percent); ?>%;background:#5ba4cf;" aria-valuemin="0" aria-valuemax="100"></div>
384 + </div>
385 + </div>
386 + <?php } ?>
387 + <input type="hidden" name="wppm_set_change_task_status_ajax_nonce" id="wppm_subtask_status_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_set_change_task_status' ) ); ?>">
388 + <input type="hidden" name="wppm_add_new_subtask_ajax_nonce" id="wppm_add_new_subtask_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_add_new_subtask' ) ); ?>">
389 + <input type="hidden" name="wppm_remove_subtask_ajax_nonce" id="wppm_remove_subtask_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_remove_subtask' ) ); ?>">
390 + <input type="hidden" name="wppm_convert_subtask_to_task_ajax_nonce" id="wppm_convert_subtask_to_task_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_convert_subtask_to_task' ) ); ?>">
391 + <ul id="wppm_subtask_items_container" class="wppm_checklist_items_container" style="list-style-type: none; padding-left:0px; margin-top:10px; margin-bottom:10px;">
392 + <?php if(!empty($wppm_subtasks)){
393 + foreach($wppm_subtasks as $subtask){
394 + $wppm_subtask_checked = ($subtask['status']==4) ? 'checked="checked"' : '';
395 + $wppm_subtask_users = !empty($subtask['users']) ? explode(",",$subtask['users']) : array();
396 + $wppm_subtask_can_change_status = ($current_user->has_cap('manage_options') || $wppmfunction->has_permission('change_status',$subtask['id'])) && $task->is_archived!=1;
397 + $wppm_subtask_can_delete = ($current_user->has_cap('manage_options') || $wppmfunction->has_permission('delete_task',$subtask['id'])) && $task->is_archived!=1;
398 + ?>
399 + <li id="wppm_subtask_<?php echo esc_attr($subtask['id']) ?>" class="row wppm_checklist_item" style="margin-bottom:10px;font: 15px 'Helvetica Neue',Helvetica,Arial,sans-serif;">
400 + <div class="col-sm-8">
401 + <input id="wppm_subtask_checkbox_<?php echo esc_attr($subtask['id']) ?>" type="checkbox" onchange="wppm_toggle_subtask_status(<?php echo esc_attr($subtask['id']) ?>,<?php echo esc_attr($task_id) ?>,<?php echo esc_attr($proj_id) ?>,<?php echo esc_attr($wppm_default_task_status) ?>,this.checked)" <?php echo esc_attr($wppm_subtask_checked) ?> <?php echo $wppm_subtask_can_change_status ? '' : 'disabled'; ?> style="margin:5px;">
402 + <label style="padding-top: 5px;font-weight: normal;font: 13px 'Helvetica Neue',Helvetica,Arial,sans-serif;cursor:pointer;" onclick="wppm_open_subtask(<?php echo esc_attr($subtask['id']) ?>,<?php echo esc_attr($proj_id) ?>)"><?php echo esc_html($subtask['task_name']); ?></label>
403 + </div>
404 + <div class="col-sm-4" style="text-align:right;">
405 + <?php $wppm_subtask_avatar_count = 0;
406 + $wppm_subtask_total_users = count( array_filter( $wppm_subtask_users ) );
407 + foreach($wppm_subtask_users as $wppm_subtask_user_id){
408 + if(!$wppm_subtask_user_id) continue;
409 + $wppm_subtask_avatar_count++;
410 + if($wppm_subtask_avatar_count > 3) break;
411 + $wppm_subtask_user_data = get_userdata($wppm_subtask_user_id);
412 + $wppm_subtask_user_name = !empty($wppm_subtask_user_data) ? $wppm_subtask_user_data->display_name : '';
413 + echo get_avatar($wppm_subtask_user_id, 20, "mysteryman", $wppm_subtask_user_name, array('extra_attr' => 'title="'.esc_attr($wppm_subtask_user_name).'"'));
414 + }
415 + $wppm_subtask_more_users = $wppm_subtask_total_users - 3;
416 + if ( $wppm_subtask_more_users > 0 ) {
417 + ?>
418 + <span class="wppm_subtask_more_users" title="<?php echo esc_attr( sprintf( _n( '%d more user assigned', '%d more users assigned', $wppm_subtask_more_users, 'taskbuilder' ), $wppm_subtask_more_users ) ); ?>">+<?php echo esc_html( $wppm_subtask_more_users ); ?></span>
419 + <?php
420 + } ?>
421 + <?php if($wppm_subtask_can_delete){ ?>
422 + <a href="#" title="<?php echo esc_attr__('Convert to Task','taskbuilder'); ?>" onclick="wppm_convert_subtask_to_task(<?php echo esc_attr($subtask['id']) ?>,<?php echo esc_attr($task_id) ?>,<?php echo esc_attr($proj_id) ?>);return false;" style="font-size:11px;margin-right:8px;"><?php echo esc_html_e('Convert to Task','taskbuilder');?></a>
423 + <span onclick="wppm_delete_subtask(<?php echo esc_attr($subtask['id']) ?>,<?php echo esc_attr($task_id) ?>,<?php echo esc_attr($proj_id) ?>)" style="cursor:pointer;"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/trash.svg'); ?>" alt="delete"></span>
424 + <?php } ?>
425 + </div>
426 + </li>
427 + <?php
428 + }
429 + } ?>
430 + </ul>
431 + <?php if($wppm_can_add_subtask){
432 + $wppm_all_task_statuses = $wpdb->get_results("SELECT * FROM {$wpdb->prefix}wppm_task_statuses ORDER BY load_order ASC");
433 + ?>
434 + <div class="row">
435 + <div class="col-sm-12" style="padding-top:15px;">
436 + <a class="wppm_add_checklist" id="wppm_add_subtask_btn" onclick="wppm_show_add_subtask()"><?php echo esc_html_e('+ Add subtask','taskbuilder');?></a>
437 + </div>
438 + </div>
439 + <div class="row">
440 + <div class="col-sm-12" style="display:none;" id="wppm_add_subtask_label_container">
441 + <div class="row">
442 + <div class="wppm_task_frm_fields col-sm-6">
443 + <span class="wppm_form_field_label"><b><?php echo esc_html_e('Subtask Name','taskbuilder');?></b> <span style="color:#ff0000;">*</span></span><br>
444 + <input type="text" id="wppm_subtask_label" class="form-control" placeholder="<?php echo esc_attr__('Subtask name','taskbuilder') ?>" name="wppm_subtask_label">
445 + </div>
446 + <div class="wppm_task_frm_fields col-sm-6">
447 + <span class="wppm_form_field_label"><b><?php echo esc_html_e('Status','taskbuilder');?></b></span><br>
448 + <select id="wppm_subtask_status" name="wppm_subtask_status" class="form-control">
449 + <?php if(!empty($wppm_all_task_statuses)){
450 + foreach($wppm_all_task_statuses as $wppm_st){ ?>
451 + <option value="<?php echo esc_attr($wppm_st->id) ?>" <?php selected($wppm_st->id, $wppm_default_task_status); ?>><?php echo esc_html($wppm_st->name) ?></option>
452 + <?php }
453 + } ?>
454 + </select>
455 + </div>
456 + </div>
457 + <div class="row">
458 + <div class="wppm_task_frm_fields col-sm-6">
459 + <span class="wppm_form_field_label"><b><?php echo esc_html_e('Due date','taskbuilder');?></b></span><br>
460 + <input type="text" id="wppm_subtask_due_date" class="form-control" name="wppm_subtask_due_date" value="" autocomplete="off">
461 + </div>
462 + <div class="wppm_task_frm_fields col-sm-6">
463 + <span class="wppm_form_field_label"><b><?php echo esc_html_e('Assignee','taskbuilder');?></b></span><br>
464 + <input class="form-control wppm_subtask_assign_users ui-autocomplete-input" name="wppm_subtask_assign_users" type="text" autocomplete="off" placeholder="<?php echo esc_attr__('Search User...','taskbuilder');?>">
465 + </div>
466 + </div>
467 + <div class="row">
468 + <div class="col-sm-12">
469 + <ul class="wppm_subtask_filter_display_users_container" style="list-style:none;padding-left:0;"></ul>
470 + </div>
471 + </div>
472 + <div class="row">
473 + <div class="wppm_task_frm_fields col-sm-12">
474 + <span class="wppm_form_field_label"><b><?php echo esc_html_e('Description','taskbuilder');?></b></span><br>
475 + <textarea id="wppm_subtask_description" name="wppm_subtask_description" class="form-control" rows="3"></textarea>
476 + </div>
477 + </div>
478 + <div class="row" style="padding-top:10px;">
479 + <div class="col-sm-12">
480 + <input type="button" value="<?php echo esc_attr__('Add','taskbuilder') ?>" class="btn btn-success btn-sm" onclick="wppm_add_new_subtask(<?php echo esc_attr($task_id)?>,<?php echo esc_attr($proj_id) ?>)">
481 + <button type="button" class="wppm_reset_btn" onclick="wppm_hide_add_subtask()"><?php echo esc_html_e('Cancel','taskbuilder');?></button>
482 + </div>
483 + </div>
484 + </div>
485 + </div>
486 + <script type="text/javascript">
487 + jQuery(document).ready(function(){
488 + jQuery('#wppm_subtask_due_date').flatpickr({
489 + enableTime: true,
490 + dateFormat: "Y-m-d H:i"
491 + });
492 + jQuery('.wppm_subtask_assign_users').autocomplete({
493 + minLength: 1,
494 + appendTo: jQuery('.wppm_subtask_assign_users').parent(),
495 + source: function(request, response){
496 + jQuery.getJSON(wppm_admin.ajax_url, {
497 + action: 'wppm_filter_autocomplete',
498 + term: request.term,
499 + field: 'task_users_by_project_name',
500 + proj_id: <?php echo (int) $task->project; ?>
501 + }, function(data){ response(data); });
502 + },
503 + select: function(event, ui){
504 + if(!ui.item.user_id){ return false; }
505 + var html_str = '<li class="wppm_filter_display_element" style="list-style:none">'
506 + +'<div class="flex-container">'
507 + +'<div class="wppm_filter_display_text">'
508 + + ui.item.label
509 + + '<input type="hidden" name="wppm_subtask_user_names[]" value="'+ui.item.user_id+'">'
510 + +'</div>'
511 + +'<div class="wppm_filter_display_remove" onclick="wppm_remove_subtask_user(this);"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/cross.svg'); ?>" alt="delete"></div>'
512 + +'</div>'
513 + +'</li>';
514 + jQuery('.wppm_subtask_filter_display_users_container').append(html_str);
515 + jQuery(this).val('');
516 + return false;
517 + }
518 + }).focus(function(){ jQuery(this).autocomplete("search", ""); });
519 + });
520 + </script>
521 + <?php } ?>
522 + </div>
523 + <?php } ?>
300 524 <div class="wppm_task_checklist_container" id="wppm_task_checklist_container">
301 525 <div id="wppm_checklist_container">
302 526 <?php
303 527 if(!empty($wppm_checklist)){
@@ -304,13 +528,13 @@
304 528 foreach( $wppm_checklist as $key=>$list){
305 529 ?>
306 530 <div class="row">
307 531 <div class="col-sm-8">
308 - <span class="wppm_checklist_label"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/checklist.svg'); ?>" alt="checklist"><?php echo esc_html_e($list->checklist_name,'taskbuilder');?></span>
532 + <span class="wppm_checklist_label"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/checklist.svg'); ?>" alt="checklist"><?php echo isset($list->checklist_name) ? esc_html($list->checklist_name):"" ?></span>
309 533 </div>
310 534 <?php
311 - $check_style = (($list->created_by == $current_user->ID || $current_user->has_cap('manage_options') || $user_role == 1 || $wppmfunction->has_permission('edit_checklist',$task->id)))? "display:inline":"display:none"; ?>
312 - <?php $disabled = (($list->created_by == $current_user->ID || $current_user->has_cap('manage_options') || $user_role == 1 || $wppmfunction->has_permission('delete_checklist',$task->id)|| ($wppmfunction->has_permission('add_checklist',0))))? "":"disabled"; ?>
535 + $check_style = (($list->created_by == $current_user->ID || $current_user->has_cap('manage_options') || $user_role == 1 || $wppmfunction->has_permission('edit_checklist',$task->id)) && $task->is_archived!=1)? "display:inline":"display:none"; ?>
536 + <?php $disabled = (($list->created_by == $current_user->ID || $current_user->has_cap('manage_options') || $user_role == 1 || $wppmfunction->has_permission('delete_checklist',$task->id)|| ($wppmfunction->has_permission('add_checklist',0))) && $task->is_archived!=1)? "":"disabled"; ?>
313 537 <?php if($wppmfunction->has_permission('add_checklist',$task->id) || $current_user->has_cap('manage_options')){ ?>
314 538 <div class="col-sm-4" style="text-align:right;<?php echo esc_attr($check_style) ?>">
315 539 <a class="wppm_delete_checklist" onclick="wppm_delete_checklist(<?php echo esc_attr($list->id);?>,<?php echo esc_attr($task->id);?>,<?php echo esc_attr($proj_id);?>)"><?php echo esc_html_e('Delete Checklist','taskbuilder');?></a>
316 540 <input type="hidden" name="wppm_delete_checklist_ajax_nonce" id="wppm_delete_checklist_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_delete_checklist' ) ); ?>">
@@ -325,32 +549,44 @@
325 549 <div id="CheckProgress_<?php echo esc_attr($list->id);?>" class="wppm_checkprogress" role="progressbar" style="width: 0%" aria-valuemin="0" aria-valuemax="100"></div>
326 550 </div>
327 551 </div>
328 552 <?php
329 - $list_id = esc_sql($list->id);
330 - $wppm_checklist_items = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}wppm_checklist_items where checklist_id='$list_id'");
553 + $list_id = absint($list->id);
554 + $sql = $wpdb->prepare(
555 + "SELECT *
556 + FROM {$wpdb->prefix}wppm_checklist_items
557 + WHERE checklist_id = %d
558 + ORDER BY load_order ASC",
559 + $list_id
560 + );
561 + // Execute
562 + $wppm_checklist_items = $wpdb->get_results($sql);
331 563 ?>
564 + <ul id="wppm_checklist_items_container_<?php echo esc_attr($list->id) ?>" class="wppm_checklist_items_container" style="list-style-type: none; padding-left:0px; margin-top:10px; margin-bottom:10px;">
332 565 <?php
333 566 if(!empty( $wppm_checklist_items)){
334 567 foreach($wppm_checklist_items as $key=>$val){
335 568 $checked = $val->checked == 1 ? 'checked="checked"' : '';
336 569 ?>
337 - <div id="wppm_checklist_<?php echo esc_attr($val->id) ?>" class="row wppm_checklist_item" style="margin-bottom:10px;font: 15px 'Helvetica Neue',Helvetica,Arial,sans-serif;">
570 + <li id="wppm_checklist_<?php echo esc_attr($val->id) ?>" data-id="<?php echo esc_attr($val->id); ?>" class="row wppm_checklist_item" style="margin-bottom:10px;font: 15px 'Helvetica Neue',Helvetica,Arial,sans-serif;">
338 571 <div class="col-sm-8" id="wppm_checklist_item_container_<?php echo esc_attr($val->id) ?>">
339 - <input id="wppm_checklist_item_<?php echo esc_attr($val->id) ?>" class="wppm_checklist_item_<?php echo esc_attr($val->checklist_id) ?>" onchange="wppm_checklist_progress(<?php echo esc_attr($val->checklist_id) ?>,<?php echo esc_attr($val->id) ?>,<?php echo esc_attr($task->id) ?>)" type="checkbox" name="wppm_checklist" <?php echo esc_attr($checked) ?> value="<?php echo esc_attr($val->id) ?>" <?php echo esc_attr($disabled) ?> style="margin:5px;"><label style="padding-top: 5px;font-weight: normal;font: 13px 'Helvetica Neue',Helvetica,Arial,sans-serif;"><?php echo esc_html_e($val->item_name,'taskbuilder') ?></label>
572 + <span class="wppm_chk_items_drag">☰</span>
573 + <input id="wppm_checklist_item_<?php echo esc_attr($val->id) ?>" class="wppm_checklist_item_<?php echo esc_attr($val->checklist_id) ?>" onchange="wppm_checklist_progress(<?php echo esc_attr($val->checklist_id) ?>,<?php echo esc_attr($val->id) ?>,<?php echo esc_attr($task->id) ?>)" type="checkbox" name="wppm_checklist" <?php echo esc_attr($checked) ?> value="<?php echo esc_attr($val->id) ?>" <?php echo esc_attr($disabled) ?> style="margin:5px;"><label style="padding-top: 5px;font-weight: normal;font: 13px 'Helvetica Neue',Helvetica,Arial,sans-serif;"><?php echo isset($val->item_name) ? esc_html($val->item_name) : "" ?></label>
340 574 <input type="hidden" name="wppm_checklist_progress_ajax_nonce" id="wppm_checklist_progress_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_set_checklist_progress' ) ); ?>">
341 575 </div>
342 - <?php if ($list->created_by == $current_user->ID || $current_user->has_cap('manage_options') || $user_role == 1 || $wppmfunction->has_permission('delete_checklist',$task->id)) { ?>
576 + <?php if (($list->created_by == $current_user->ID || $current_user->has_cap('manage_options') || $user_role == 1 || $wppmfunction->has_permission('delete_checklist',$task->id)) && $task->is_archived!=1) { ?>
343 577 <div class="col-sm-4" id="wppm_checklist_action_<?php echo esc_attr($val->id) ?>" style="text-align:right; display:none;cursor:pointer;">
578 + <span onclick=wppm_edit_checklist_item(<?php echo esc_attr($val->id) ?>,<?php echo esc_attr($val->checklist_id) ?>,<?php echo esc_attr( $proj_id);?>,<?php echo esc_attr($id) ?>)><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/edit1.svg'); ?>" alt="edit"></span>
579 + <input type="hidden" name="wppm_edit_checklist_item_ajax_nonce" id="wppm_edit_checklist_item_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_edit_checklist_item' ) ); ?>">
344 580 <span onclick=wppm_delete_checklist_item(<?php echo esc_attr($val->id) ?>,<?php echo esc_attr($val->checklist_id) ?>,<?php echo esc_attr($proj_id);?>,<?php echo esc_attr($id) ?>)><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/trash.svg'); ?>" alt="delete"></span>
345 581 <input type="hidden" name="wppm_delete_checklist_item_ajax_nonce" id="wppm_delete_checklist_item_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_remove_checklist_item' ) ); ?>">
346 582 </div>
347 583 <?php } ?>
348 - </div>
584 + </li>
349 585 <?php
350 586 }
351 587 } ?>
352 - <?php if($wppmfunction->has_permission('add_checklist',$task->id) || $current_user->has_cap('manage_options')){ ?>
588 + <?php if(($wppmfunction->has_permission('add_checklist',$task->id) || $current_user->has_cap('manage_options')) && $task->is_archived!=1){ ?>
353 589 <div class="row">
354 590 <div class="col-sm-12 wppm_add_checklist_item_container_<?php echo esc_attr($list->id) ?>" style="padding-top:15px;">
355 591 <a class="wppm_add_checklist" id="wppm_add_checklist_item_btn_<?php echo esc_attr($list->id) ?>" onclick="wppm_add_checklist_item(<?php echo esc_attr($list->id)?>)"><?php echo esc_html_e('+ Add item','taskbuilder');?></a>
356 592 </div>
@@ -355,9 +591,9 @@
355 591 <a class="wppm_add_checklist" id="wppm_add_checklist_item_btn_<?php echo esc_attr($list->id) ?>" onclick="wppm_add_checklist_item(<?php echo esc_attr($list->id)?>)"><?php echo esc_html_e('+ Add item','taskbuilder');?></a>
356 592 </div>
357 593 </div>
358 594 <?php }?>
359 - <?php if($wppmfunction->has_permission('add_checklist',$task->id) || $current_user->has_cap('manage_options')){ ?>
595 + <?php if(($wppmfunction->has_permission('add_checklist',$task->id) || $current_user->has_cap('manage_options')) && $task->is_archived!=1){ ?>
360 596 <div class="row">
361 597 <div class="col-sm-12" style="display:none;" id="wppm_add_checklist_label_container_<?php echo esc_attr($list->id) ?>">
362 598 <div class="row" id="wppm_add_new_checklist_item_<?php echo esc_attr($list->id) ?>">
363 599 <div class="col-sm-12">
@@ -371,32 +607,35 @@
371 607 </div>
372 608 </div>
373 609 <?php }?>
374 610 <hr class="wppm_checklist_divider">
611 + </ul>
375 612 <?php
376 613 }
377 614 } ?>
378 615 </div><?php
379 - if($wppmfunction->has_permission('add_checklist',$task->id) || $current_user->has_cap('manage_options')){ ?>
380 - <div id="wppm_add_checklist_container">
381 - <div class="row">
382 - <div class="col-sm-12">
383 - <span id="wppm_add_checklist" onclick="wppm_add_checklist()"> <?php echo esc_html_e('+Add a checklist','taskbuilder')?> </span>
616 + if($user_role != 3){
617 + if(($wppmfunction->has_permission('add_checklist',$task->id) || $current_user->has_cap('manage_options')) && $task->is_archived!=1){ ?>
618 + <div id="wppm_add_checklist_container">
619 + <div class="row">
620 + <div class="col-sm-12">
621 + <span id="wppm_add_checklist" onclick="wppm_add_checklist()"> <?php echo esc_html_e('+Add a checklist','taskbuilder')?> </span>
622 + </div>
384 623 </div>
385 - </div>
386 - <div class="row" id="wppm_add_new_checklist" style="display:none;">
387 - <div class="col-sm-12">
388 - <input type="text" class="wppm_checklist_label" placeholder="<?php echo esc_attr__('Please insert checklist title','taskbuilder');?>" id="wppm_checklist_label" name="wppm_checklist_label">
389 - <input type="button" value="Add" id="wppm_checklist_btn" class="btn btn-success btn-sm" onclick="wppm_add_new_checklist(<?php echo esc_attr($id)?>,<?php echo esc_attr($proj_id) ?>)">
390 - <input type="hidden" name="wppm_checklist_ajax_nonce" id="wppm_checklist_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_add_new_checklist' ) ); ?>">
391 - <span onclick="wppm_remove_add_checklist()"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/cross1.svg'); ?>"></span>
624 + <div class="row" id="wppm_add_new_checklist" style="display:none;">
625 + <div class="col-sm-12">
626 + <input type="text" class="wppm_checklist_label" placeholder="<?php echo esc_attr__('Please insert checklist title','taskbuilder');?>" id="wppm_checklist_label" name="wppm_checklist_label">
627 + <input type="button" value="Add" id="wppm_checklist_btn" class="btn btn-success btn-sm" onclick="wppm_add_new_checklist(<?php echo esc_attr($id)?>,<?php echo esc_attr($proj_id) ?>)">
628 + <input type="hidden" name="wppm_checklist_ajax_nonce" id="wppm_checklist_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_add_new_checklist' ) ); ?>">
629 + <span onclick="wppm_remove_add_checklist()"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/cross1.svg'); ?>"></span>
630 + </div>
392 631 </div>
393 - </div>
394 - </br>
395 - </div><?php
396 - } ?>
632 + </br>
633 + </div><?php
634 + }
635 + }?>
397 636 </div>
398 - <div id="wppm_activity_container" style="<?php echo ($wppm_task_hide_comment_section==0) ? 'display:none;' : 'display:block;' ?>">
637 + <div id="wppm_activity_container" style="<?php echo ($wppm_task_hide_comment_section==0 || $user_role==3) ? 'display:none;' : 'display:block;' ?>">
399 638 <div class="row">
400 639 <div class="col-sm-12" style="margin-top:5px;">
401 640 <span class="wppm_task_discussion"><?php echo esc_html_e('Comment','taskbuilder')?></span><br>
402 641 </div>
@@ -401,13 +640,13 @@
401 640 <span class="wppm_task_discussion"><?php echo esc_html_e('Comment','taskbuilder')?></span><br>
402 641 </div>
403 642 </div>
404 643 <div class="row">
405 - <div class="col-sm-12">
644 + <div class="col-sm-12" style="<?php echo ($task->is_archived==1) ? 'display:none;' : 'display:block;' ?>">
406 645 <textarea id="wppm_task_comment" placeholder="<?php echo esc_attr__('Write a comment...','taskbuilder');?>" onclick="wppm_add_task_comment()" name="wppm_task_comment"></textarea>
407 646 </div>
408 647 </div>
409 - <div class="row" id="wppm_comment_btn">
648 + <div class="row" id="wppm_comment_btn" style="<?php echo ($task->is_archived==1) ? 'display:none;' : 'display:block;' ?>">
410 649 <div class="col-sm-6">
411 650 <span id="wppm_attach_file" onclick="wppm_upload_file()"><?php echo esc_html_e('Attach Files','taskbuilder')?></span>
412 651 </div>
413 652 <div class="col-sm-6">
@@ -419,23 +658,30 @@
419 658 </button>
420 659 <input type="hidden" name="_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_submit_task_comment' ) ); ?>">
421 660 </div>
422 661 </div>
423 - <div class="row">
662 + <div class="row" style="<?php echo ($task->is_archived==1) ? 'display:none;' : 'display:block;' ?>">
424 663 <div class="wppm_attachment_container col-sm-12" style="display:none;">
425 664 </div>
426 665 </div>
427 666 </div>
428 - <div class="wppm_thread_container" style="<?php echo ($wppm_task_hide_comment_section==0) ? 'display:none;' : 'display:block;' ?>">
667 + <div class="wppm_thread_container" style="<?php echo ($wppm_task_hide_comment_section==0 || $user_role==3) ? 'display:none;' : 'display:block;' ?>">
429 668 <?php
430 669 if(!empty($task_comment)){
431 670 foreach($task_comment as $comment){
432 - $task_comment_meta = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}wppm_task_comment_meta where task_id='".esc_sql($id)."' AND comment_id='".esc_sql($comment->id)."'");
671 + $task_comment_meta = $wpdb->get_row( $wpdb->prepare(
672 + "SELECT *
673 + FROM {$wpdb->prefix}wppm_task_comment_meta
674 + WHERE task_id = %d
675 + AND comment_id = %d",
676 + absint($id),
677 + absint($comment->id)
678 + )
679 + );
433 680 $user = get_userdata( $comment->created_by );
434 - $comment_body = stripslashes((htmlspecialchars_decode($comment->body, ENT_QUOTES)));
435 - $comment_body = preg_replace('#<script(.*?)>(.*?)</script>#is', '', $comment_body);
436 - $date = date("Y-m-d H:i:s" ,strtotime($comment->create_time));
437 - $thread_date = date("d F Y, h:i:s A" ,strtotime($date));
681 + $comment_body = (!empty($comment->body) ? ($comment->body) : '');
682 + $date = wp_date("Y-m-d H:i:s" ,strtotime($comment->create_time));
683 + $thread_date = wp_date("d F Y, h:i:s A" ,strtotime($date));
438 684 $attachment_ids = isset($comment->attachment_ids)? $comment->attachment_ids : '';
439 685 if($attachment_ids!=""){
440 686 $attachments = explode(",",$attachment_ids);
441 687 } else {
@@ -447,22 +693,30 @@
447 693 <?php echo (get_avatar($comment->created_by, 40));?>
448 694 </div>
449 695 <div class="wppm_thread_body">
450 696 <div class="wppm_thread_user_name">
451 - <strong style="color:<?php echo esc_attr($appearance_settings['comment-primary-color']);?>"><?php echo esc_html($user->display_name) ?></strong>
697 + <strong style="color:<?php echo esc_attr($appearance_settings['comment-primary-color']);?>"><?php echo isset($user->display_name) ? esc_html($user->display_name) : '' ?></strong>
452 698 <span><?php if(!empty($comment->body) && (isset($task_comment_meta->comment_type) && $task_comment_meta->comment_type=='change_task_status')){
453 699 $comment_log_body = unserialize($comment->body);
454 700 $prev_status = $comment_log_body['prev_status'];
455 701 $new_status = $comment_log_body['new_status'];
456 702 if(isset($prev_status)){
457 - $prev_status = esc_sql($prev_status);
458 - $task_prev_status = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}wppm_task_statuses where id='$prev_status'");
703 + $task_prev_status = $wpdb->get_row( $wpdb->prepare(
704 + "SELECT * FROM {$wpdb->prefix}wppm_task_statuses where id = %d",
705 + absint($prev_status)
706 + ));
459 707 }
460 708 if(isset($new_status)){
461 - $new_status = esc_sql($new_status);
462 - $task_new_status = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}wppm_task_statuses where id='$new_status'");
709 + $task_new_status = $wpdb->get_row( $wpdb->prepare(
710 + "SELECT * FROM {$wpdb->prefix}wppm_task_statuses where id = %d",
711 + absint($new_status)
712 + ));
463 713 }
464 - esc_html_e("changed status from $task_prev_status->name to $task_new_status->name","taskbuilder");
714 + printf(
715 + esc_html__( 'Changed status from %1$s to %2$s', 'taskbuilder' ),
716 + esc_html( $task_prev_status->name ),
717 + esc_html( $task_new_status->name )
718 + );
465 719 } if(!empty($comment->body) && (isset($task_comment_meta->comment_type) && $task_comment_meta->comment_type=='change_task_creator')){
466 720 $comment_log_body = unserialize($comment->body);
467 721 $prev_user = $comment_log_body['prev_user'];
468 722 $new_user = $comment_log_body['new_user'];
@@ -467,9 +721,13 @@
467 721 $prev_user = $comment_log_body['prev_user'];
468 722 $new_user = $comment_log_body['new_user'];
469 723 $prev_user_data = get_userdata($prev_user);
470 724 $new_user_data = get_userdata($new_user);
471 - esc_html_e("changed creator from $prev_user_data->display_name to $new_user_data->display_name","taskbuilder");
725 + printf(
726 + esc_html__( 'Changed creator from %1$s to %2$s', 'taskbuilder' ),
727 + esc_html( $prev_user_data->display_name ),
728 + esc_html( $new_user_data->display_name )
729 + );
472 730 }
473 731 if( !empty($comment->body) && (isset($task_comment_meta->comment_type) && $task_comment_meta->comment_type=='change_assign_user')){
474 732 esc_html_e("changed the Assignee","taskbuilder");
475 733 }
@@ -477,23 +735,33 @@
477 735 $comment_log_body = unserialize($comment->body);
478 736 $prev_prio = $comment_log_body['prev_prio'];
479 737 $new_prio = $comment_log_body['new_prio'];
480 738 if(isset($prev_prio)){
481 - $prev_prio = esc_sql($prev_prio);
482 - $task_prev_prio = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}wppm_task_priorities where id= '$prev_prio'");
739 + $prev_prio = absint($prev_prio);
740 + $task_prev_prio = $wpdb->get_row( $wpdb->prepare(
741 + "SELECT * FROM {$wpdb->prefix}wppm_task_priorities where id = %d",
742 + $prev_prio
743 + ));
483 744 }
484 745 if(isset($new_prio)){
485 - $new_prio = esc_sql($new_prio);
486 - $task_new_prio = $wpdb->get_row("SELECT * FROM {$wpdb->prefix}wppm_task_priorities where id= '$new_prio'");
746 + $new_prio = absint($new_prio);
747 + $task_new_prio = $wpdb->get_row( $wpdb->prepare(
748 + "SELECT * FROM {$wpdb->prefix}wppm_task_priorities where id = %d",
749 + $new_prio
750 + ));
487 751 }
488 752 $task_prev_prio_name = !empty($task_prev_prio) ? $task_prev_prio->name: "None";
489 753 $task_new_prio_name = !empty($task_new_prio) ? $task_new_prio->name: "None";
490 - esc_html_e("changed priority from $task_prev_prio_name to $task_new_prio_name","taskbuilder");
754 + printf(
755 + esc_html__( 'Changed priority from %1$s to %2$s', 'taskbuilder' ),
756 + esc_html( $task_prev_prio_name ),
757 + esc_html( $task_new_prio_name )
758 + );
491 759 }
492 760 ?>
493 - <small class="wppm_comment_date" style="color:<?php echo esc_attr($appearance_settings['comment-date-color']);?>"><i><?php echo esc_html($thread_date) ?></i></small>
761 + <small class="wppm_comment_date" style="color:<?php echo esc_attr($appearance_settings['comment-date-color']);?>"><i><?php echo isset($thread_date) ? esc_html($thread_date) : '' ?></i></small>
494 762 <div class="wppm_thread_action">
495 - <?php if(( (($current_user->has_cap('manage_options')) || ($wppmfunction->has_comment_permission('edit_task_comment',$id,$comment->id))) && ((empty($task_comment_meta->comment_type)) || (isset($task_comment_meta->comment_type) && $task_comment_meta->comment_type=='comment')))){ ?>
763 + <?php if((((($current_user->has_cap('manage_options')) || ($wppmfunction->has_comment_permission('edit_task_comment',$id,$comment->id))) && ((empty($task_comment_meta->comment_type)) || (isset($task_comment_meta->comment_type) && $task_comment_meta->comment_type=='comment')))) && ($task->is_archived!=1)){ ?>
496 764 <span title="Edit this thread" onclick="wppm_edit_thread(<?php echo esc_attr($comment->id)?>,<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/edit1.svg'); ?>" alt="edit"></span>
497 765 <span title="Delete this thread" onclick="wppm_delete_thread(<?php echo esc_attr($comment->id) ?>,<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/trash.svg'); ?>" alt="delete"></span>
498 766 <?php } ?>
499 767 </div>
@@ -499,11 +767,16 @@
499 767 </div>
500 768 </div>
501 769 <div class="wppm_thread_messege" style="color:<?php echo esc_attr($appearance_settings['comment-secondary-color']);?>">
502 770 <?php
503 - $allowedtags = array( 'br' => array(), 'abbr' => array('title' => array(),), 'p' => array(), 'strong' => array(), 'a' => array('href' => array(), 'title' => array(), 'target'=> array(), 'rel'=>array()),'em' =>array(),'span' =>array(), 'blockquote'=>array('cite' => array(),),'div' => array('class' => array(),'title' => array(),'style' => array(),),'ul'=>array(),'li'=>array(),'ol'=>array(),'img' => array( 'alt'=> array(),'class' => array(),'height' => array(),'src'=> array(),'width'=> array(),));
771 + $allowedtags = array( 'br' => array(), 'abbr' => array('title' => array(),), 'p' => array(), 'strong' => array(), 'a' => array('href' => array(), 'title' => array(), 'target'=> array(), 'rel'=>array()),'em' =>array(),'span' =>array('class' => true,
772 + 'data-user-id' => true,'data-username' => true,), 'blockquote'=>array('cite' => array(),),'div' => array('class' => array(),'title' => array(),'style' => array(),),'ul'=>array(),'li'=>array(),'ol'=>array(),'img' => array( 'alt'=> array(),'class' => array(),'height' => array(),'src'=> array(),'width'=> array(),));
504 773 if(!empty($comment_body) && ((empty($task_comment_meta->comment_type)) || (isset($task_comment_meta->comment_type) && $task_comment_meta->comment_type=='comment') || (isset($task_comment_meta->comment_type) && $task_comment_meta->comment_type=='delete_task_comment'))){
505 - echo wp_kses(wpautop($comment_body),$allowedtags) ;
774 + $comment_body = $wppmfunction->wppm_clean_mentions_html($comment_body);
775 + $comment_body = $wppmfunction->wppm_highlight_user_mentions($comment_body, $current_user->ID);
776 + //echo wp_kses(wpautop($comment_body),$allowedtags);
777 + //wp_kses($comment, $allowed_tags);
778 + echo wp_kses_post(($comment_body));
506 779 } elseif(!empty($comment->body) && (isset($task_comment_meta->comment_type) && $task_comment_meta->comment_type=='change_task_status')){ ?>
507 780 <span class="wppm_admin_label" style="margin-right: 10px; background-color:<?php echo isset($task_prev_status->bg_color) ? esc_attr($task_prev_status->bg_color):""; ?>;color:<?php echo isset($task_prev_status->color) ? esc_attr($task_prev_status->color): "" ?>;"><?php echo isset($task_prev_status->name) ? esc_attr($task_prev_status->name) : "" ?></span> <img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/arrow-right.svg'); ?>" alt="arrow_right"> <span class="wppm_admin_label" style="margin-left:10px; background-color:<?php echo isset($task_new_status->bg_color) ? esc_attr($task_new_status->bg_color):""; ?>;color:<?php echo isset($task_new_status->color) ? esc_attr($task_new_status->color): "" ?>;"><?php echo isset($task_new_status->name) ? esc_attr($task_new_status->name) : "" ?></span><?php
508 781 }elseif(!empty($comment->body) && (isset($task_comment_meta->comment_type) && $task_comment_meta->comment_type=='change_task_creator')){ ?>
509 782 <span style="margin-right: 10px;"><?php echo isset($prev_user_data->display_name) ? esc_attr($prev_user_data->display_name) : "" ?></span> <img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/arrow-right.svg'); ?>" alt="arrow_right"> <span style="margin-left:10px;"><?php echo isset($new_user_data->display_name) ? esc_attr($new_user_data->display_name) : "" ?></span><?php
@@ -552,10 +825,13 @@
552 825 <?php
553 826 if(!empty($attachments)){
554 827 foreach( $attachments as $attachment ):
555 828 $download_url = site_url('/').'?wppm_attachment='.$attachment.'&tid='.$id.'&tac='.$auth_id;
556 - $attachment = esc_sql($attachment);
557 - $attach = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}wppm_attachments where id='$attachment'");
829 + $attachment = absint($attachment);
830 + if (empty($attachment)) {
831 + continue; // or return, depending on the context
832 + }
833 + $attach = $wpdb->get_row( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_attachments where id=%d",$attachment));
558 834 $findStr = ".txt";
559 835 if(!empty( $attach)){
560 836 $attachment_name = preg_replace('/' . $findStr . '/', "", $attach->name, 1);
561 837 $attachment_name = sanitize_file_name($attachment_name);
@@ -565,10 +841,10 @@
565 841 <tr class="wppm_attachment_tr">
566 842 <td>
567 843 <a class="wppm_attachment_link" href="<?php echo esc_url($download_url) ?>" target="_blank">
568 844 <span class="wppm_attachment_file_name" style="padding: 7px;"><?php echo isset($attach->file_name) ? esc_html($attach->file_name):"";?></span></a>
569 - <?php if((($comment->created_by == $current_user->ID) || ($current_user->has_cap('manage_options')) || ($wppmfunction->has_comment_permission('edit_task_comment',$id,$comment->id)))){ ?>
570 - <span class="wppm_thread_action_btn" onclick="wppm_thread_attachment_remove(this,<?php echo esc_attr($attach->id); ?>,<?php echo esc_attr($comment->id); ?>,<?php echo esc_attr($id); ?>,<?php echo esc_attr($proj_id);?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/cancel.svg'); ?>" alt="cancel"></span>
845 + <?php if((($comment->created_by == $current_user->ID) || ($current_user->has_cap('manage_options')) || ($wppmfunction->has_comment_permission('edit_task_comment',$id,$comment->id))) && ($task->is_archived!=1)){ ?>
846 + <span class="wppm_thread_action_btn" onclick="wppm_thread_attachment_remove(this,<?php echo !empty($attach->id) ? esc_attr($attach->id) : 0; ?>,<?php echo !empty($comment->id) ? esc_attr($comment->id) : 0; ?>,<?php echo !empty($id) ? esc_attr($id) : 0; ?>,<?php echo !empty($proj_id) ? esc_attr($proj_id) : 0;?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/cancel.svg'); ?>" alt="cancel"></span>
571 847 <?php } ?>
572 848 </td>
573 849 </tr>
574 850 <input type="hidden" name="wppm_ajax_nonce" id="wppm_ajax_nonce" value="<?php echo esc_attr( wp_create_nonce( 'wppm_remove_thread_attachment' ) ); ?>">
@@ -589,12 +865,14 @@
589 865 <div class="row wppm_widget" id="wppm_status_widget">
590 866 <div class="wppm-widget-header" style="background-color:<?php echo esc_attr($appearance_settings['widget-header-bg-color'])?>">
591 867 <h4 class="widget_header" style="color:<?php echo esc_attr($appearance_settings['widget-header-text-color'])?>"><?php echo esc_html_e('Status','taskbuilder')?></h4>
592 868 <?php
593 - if($current_user->has_cap('manage_options') || $wppm_current_user_capability == ('wppm_admin') || ($flag==true) || ($wppmfunction->has_permission('change_task_status',$id))!=""){
594 - ?>
595 - <span class="wppm_edit_task_details_widget" onclick="wppm_edit_task_status(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/edit_01.svg'); ?>" alt="edit"></span>
596 - <?php
869 + if($user_role != 3){
870 + if((($current_user->has_cap('manage_options') || $wppm_current_user_capability == ('wppm_admin') || ($flag==true) || ($wppmfunction->has_permission('change_task_status',$id))!="") && ($task->is_archived!=1))){
871 + ?>
872 + <span class="wppm_edit_task_details_widget" onclick="wppm_edit_task_status(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>,<?php echo esc_attr($project_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/edit_01.svg'); ?>" alt="edit"></span>
873 + <?php
874 + }
597 875 }
598 876 ?>
599 877 </div>
600 878 <hr class="widget_divider">
@@ -605,11 +883,13 @@
605 883 <div class="row wppm_widget" id="wppm_raisedby_widget">
606 884 <div class="wppm-widget-header" style="background-color:<?php echo esc_attr($appearance_settings['widget-header-bg-color'])?>">
607 885 <h4 class="widget_header" style="color:<?php echo esc_attr($appearance_settings['widget-header-text-color'])?>">
608 886 <?php echo esc_html_e('Task Creator','taskbuilder')?></h4>
609 - <?php if ($wppmfunction->has_permission('change_raised_by',$id ) || $current_user->has_cap('manage_options')) { ?>
610 - <span class="wppm_edit_task_details_widget" onclick="wppm_edit_task_creator(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/edit_01.svg'); ?>" alt="edit"></span>
611 - <?php } ?>
887 + <?php if($user_role != 3){
888 + if ((($wppmfunction->has_permission('change_raised_by',$id ) || $current_user->has_cap('manage_options')) && ($task->is_archived!=1))) { ?>
889 + <span class="wppm_edit_task_details_widget" onclick="wppm_edit_task_creator(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>,<?php echo esc_attr($project_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/edit_01.svg'); ?>" alt="edit"></span>
890 + <?php }
891 + }?>
612 892 </div>
613 893 <hr class="widget_divider"> <?php
614 894 if(isset($task->created_by)){
615 895 $user_info = get_userdata($task->created_by);
@@ -626,11 +906,14 @@
626 906 </div>
627 907 <div class="row wppm_widget" id="wppm_task_users_widget_container">
628 908 <div class="wppm-widget-header" style="background-color:<?php echo esc_attr($appearance_settings['widget-header-bg-color'])?>">
629 909 <h4 class="widget_header" style="color:<?php echo esc_attr($appearance_settings['widget-header-text-color'])?>;"><?php echo esc_html_e('Users','taskbuilder')?></h4>
630 - <?php if ($wppmfunction->has_permission('assign_task_users',$id ) || $current_user->has_cap('manage_options')) { ?>
631 - <span class="wppm_edit_task_details_widget" onclick="wppm_edit_task_users(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/edit_01.svg'); ?>" alt="edit"></span>
632 - <?php } ?>
910 + <?php
911 + if($user_role != 3){
912 + if ((($wppmfunction->has_permission('assign_task_users',$id ) || $current_user->has_cap('manage_options')) && ($task->is_archived!=1))) { ?>
913 + <span class="wppm_edit_task_details_widget" onclick="wppm_edit_task_users(<?php echo esc_attr($id) ?>,<?php echo esc_attr($proj_id) ?>,<?php echo esc_attr($project_id) ?>)"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/edit_01.svg'); ?>" alt="edit"></span>
914 + <?php }
915 + }?>
633 916 </div>
634 917 <hr class="widget_divider">
635 918 <div class="wppm-widget-body" style="background-color:<?php echo esc_attr($appearance_settings['widget-body-bg-color'])?>">
636 919 <div id="wppm_task_users">
@@ -661,9 +944,9 @@
661 944 </div>
662 945 </div>
663 946 <?php do_action('wppm_after_task_widgets',$id,$task_id );?>
664 947 </div>
665 - <input type="hidden" id="wppm_nonce" value="<?php echo wp_create_nonce('wppm_upload_file')?>">
948 + <input type="hidden" id="wppm_nonce" value="<?php echo esc_attr(wp_create_nonce('wppm_upload_file'))?>">
666 949 <input type="file" id="wppm_attachment_upload" class="hidden" onchange="">
667 950 </div>
668 951 </form>
669 952 <style>
@@ -674,9 +957,31 @@
674 957 fill:red!important;
675 958 }
676 959 </style>
677 960 <script>
678 -jQuery( document ).ready( function( jQuery ) {<?php
961 +jQuery( document ).ready( function( jQuery ) {
962 + const button = document.getElementById('wppm_print_task_btn');
963 + const box = document.getElementById('wppmprint_menu');
964 +
965 + // Show box on button click
966 + button.addEventListener('click', (e) => {
967 + e.stopPropagation(); // prevent document click from firing immediately
968 + box.style.display = 'flex';
969 + });
970 +
971 + // Prevent hiding when clicking inside box
972 + box.addEventListener('click', (e) => {
973 + e.stopPropagation();
974 + });
975 +
976 + // Hide when clicking outside
977 + document.addEventListener('click', () => {
978 + box.style.display = 'none';
979 + });
980 + jQuery('#wppm_task_comment').on('focus', function(){
981 + // showMentionList('');
982 + });
983 +<?php
679 984 if ((($current_user->ID && $current_user->has_cap('manage_options')) || $wppmfunction->has_permission('change_task_details',$task->id))){ ?>
680 985 jQuery("#wppm_edit_tstart_date").flatpickr({
681 986 enableTime: true,
682 987 dateFormat: "Y-m-d H:i",
@@ -720,9 +1025,9 @@
720 1025 jQuery('#CheckProgress_'+<?php echo esc_attr($chklist->id);?>).css('width', progressWidth + '%');
721 1026 if(progressWidth>0){
722 1027 jQuery('#wppm_progressbar_label_'+<?php echo esc_attr($chklist->id);?>).text(progressWidth+'%');
723 1028 }
724 - <?php $wppm_checklist_items = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}wppm_checklist_items where checklist_id=".$chklist->id);
1029 + <?php $wppm_checklist_items = $wpdb->get_results( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_checklist_items where checklist_id=%d",$chklist->id));
725 1030 foreach ($wppm_checklist_items as $chkitems) {
726 1031 ?> jQuery( '#wppm_checklist_'+<?php echo esc_attr($chkitems->id);?>).on("mouseover", function () {
727 1032 jQuery( '#wppm_checklist_action_'+<?php echo esc_attr($chkitems->id);?>).css("display","inline");
728 1033 jQuery( '#wppm_checklist_'+<?php echo esc_attr($chkitems->id);?>).css("background-color","#e7e8ea");
@@ -738,46 +1043,88 @@
738 1043 $italic = (isset($wppm_toolbar_actions['italic']) && $wppm_toolbar_actions['italic']==1)? 'italic' :"";
739 1044 $underline = (isset($wppm_toolbar_actions['underline']) && $wppm_toolbar_actions['underline']==1)?'underline' :"";
740 1045 $blockquote = (isset($wppm_toolbar_actions['blockquote']) && $wppm_toolbar_actions['blockquote']==1)? 'blockquote' :"";
741 1046 $align = (isset($wppm_toolbar_actions['align']) && $wppm_toolbar_actions['align']==1)? ' alignleft aligncenter alignright ' :"";
742 - $bullist = (isset($wppm_toolbar_actions['bullist']) && $wppm_toolbar_actions['bullist']==1)? $bullist = 'bullist' :"";
743 - $numlist = (isset($wppm_toolbar_actions['numlist']) && $wppm_toolbar_actions['numlist']==1)? $numlist = 'numlist' :"";
744 - $rtl = (isset($wppm_toolbar_actions['rtl']) && $wppm_toolbar_actions['rtl']==1)? $rtl = 'rtl' :"";
745 - $link = (isset($wppm_toolbar_actions['link']) && $wppm_toolbar_actions['link']==1)? $link = 'link' :"";
746 - $image = (isset($wppm_toolbar_actions['wppm_insert_editor_img']) && $wppm_toolbar_actions['wppm_insert_editor_img']==1)? $image = 'image' :"";
747 - $forecolor = (isset($wppm_toolbar_actions['forecolor']) && $wppm_toolbar_actions['forecolor']==1)? $forecolor = 'forecolor' :"";
748 - $backcolor = (isset($wppm_toolbar_actions['backcolor']) && $wppm_toolbar_actions['backcolor']==1)? $backcolor = 'backcolor' :"";
749 - $strikethrough = (isset($wppm_toolbar_actions['strikethrough']) && $wppm_toolbar_actions['strikethrough']==1)? $strikethrough = 'strikethrough' :"";
750 - if(($wppm_tinymce_visibility_open_task==1)){
751 - if(!empty($wppm_rich_text_editor) && ($wppm_rich_text_editor == 1)){
752 - ?>
753 - tinymce.remove();
754 - tinymce.init({
1047 + $bullist = (isset($wppm_toolbar_actions['bullist']) && $wppm_toolbar_actions['bullist']==1)? 'bullist' :"";
1048 + $numlist = (isset($wppm_toolbar_actions['numlist']) && $wppm_toolbar_actions['numlist']==1)? 'numlist' :"";
1049 + $rtl = (isset($wppm_toolbar_actions['rtl']) && $wppm_toolbar_actions['rtl']==1)? 'rtl' :"";
1050 + $link = (isset($wppm_toolbar_actions['link']) && $wppm_toolbar_actions['link']==1)? 'link' :"";
1051 + $image = (isset($wppm_toolbar_actions['wppm_insert_editor_img']) && $wppm_toolbar_actions['wppm_insert_editor_img']==1)? 'image' :"";
1052 + $forecolor = (isset($wppm_toolbar_actions['forecolor']) && $wppm_toolbar_actions['forecolor']==1)? 'forecolor' :"";
1053 + $backcolor = (isset($wppm_toolbar_actions['backcolor']) && $wppm_toolbar_actions['backcolor']==1)? 'backcolor' :"";
1054 + $strikethrough = (isset($wppm_toolbar_actions['strikethrough']) && $wppm_toolbar_actions['strikethrough']==1)? 'strikethrough' :"";
1055 + $toolbar = trim("$bold $italic $underline $blockquote | $align | $bullist $numlist | $rtl | $link $image | $forecolor $backcolor $strikethrough");
1056 + if(($wppm_tinymce_visibility_open_task==1)){ ?>
1057 + if((wppm_admin.rich_text_editor) && (wppm_admin.rich_text_editor.trim().length > 0) && (wppm_admin.rich_text_editor == 1)){
1058 + getMentionDropdown(editor);
1059 + tinymce.remove();
1060 + tinymce.init({
755 1061 selector:'#wppm_task_comment',
756 1062 body_id: 'wppm_task_comment',
757 - directionality : '<?php //echo 'rtl'; ?>',
758 1063 menubar: false,
759 1064 statusbar: false,
760 1065 height : '200',
761 1066 width : '100%',
762 - plugins: [
763 - 'lists link image directionality paste textcolor'
764 - ],
765 - image_advtab: true,
766 - toolbar: '<?php echo $bold ?> <?php echo $italic ?> <?php echo $underline ?> <?php echo $blockquote?> | <?php echo $align ?> | <?php echo $bullist ?> <?php echo $numlist ?> | <?php echo $rtl ?> | <?php echo $link ?> <?php echo $image ?> | <?php echo $forecolor?> <?php echo $backcolor?> <?php echo $strikethrough ?>',
767 - branding: false,
768 - autoresize_bottom_margin: 20,
769 - browser_spellcheck : true,
770 - relative_urls : false,
771 - remove_script_host : false,
772 - convert_urls : true,
773 - paste_as_text: true,
1067 + plugins: ['lists link image directionality paste textcolor'],
1068 + valid_elements: '*[*]',
1069 + extended_valid_elements: 'span[class|data-username|data-user-id|,p,br,strong,em,a[href|target]contenteditable]',
1070 + toolbar:'<?php echo esc_js($toolbar); ?>',
1071 + content_style: `
1072 + .wppm-mention{
1073 + display:inline-block;
1074 + background:linear-gradient(135deg,#eef2ff,#e0e7ff);
1075 + color:#5b21b6;
1076 + padding:2px 8px;
1077 + border-radius:16px;
1078 + font-weight:600;
1079 + border:1px solid #c7d2fe;
1080 + }
1081 +
1082 + .wppm-mention-me{
1083 + background:linear-gradient(135deg,#fef3c7,#fde68a);
1084 + color:#92400e;
1085 + border:1px solid #fbbf24;
1086 + font-weight:700;
1087 + }
1088 + `
774 1089 setup: function (editor) {
1090 + wppmmenwppmMentionSetup(editor)
1091 +
1092 + } // ✅ only ONE setup
1093 + });
1094 + jQuery('#wppm_comment_btn').show();
775 1095 }
776 - });
777 - jQuery('#wppm_comment_btn').show();
778 - <?php } ?>
779 - <?php } ?>
1096 + <?php } ?>
1097 + });
1098 +
1099 +jQuery(function(jQuery){
1100 + // Checklist Sorting
1101 + jQuery(".wppm_checklist_items_container").sortable({
1102 + handle: ".wppm_chk_items_drag",
1103 + update: function() {
1104 + let order = [];
1105 + jQuery(this).find("li").each(function(){
1106 + order.push(jQuery(this).data("id")); // checklist item id
1107 + });
1108 +
1109 + // AJAX Save
1110 + jQuery.post(wppm_admin.ajax_url, {
1111 + action: "wppm_update_checklist_order",
1112 + order: order,
1113 + task_id: <?php echo esc_attr($id); ?>,
1114 + _ajax_nonce: '<?php echo esc_attr( wp_create_nonce( 'wppm_update_checklist_order' ) ); ?>'
1115 + }, function(response_str){
1116 + var response = JSON.parse(response_str);
1117 + jQuery('.wppm_submit_wait').hide();
1118 + if (response.sucess_status=='1') {
1119 + jQuery('#wppm_alert_success .wppm_alert_text').text(response.messege);
1120 + }
1121 + jQuery('#wppm_alert_success').slideDown('fast',function(){});
1122 + setTimeout(function(){ jQuery('#wppm_alert_success').slideUp('fast',function(){}); }, 3000);
1123 + });
1124 + }
1125 + });
1126 +
780 1127 });
781 1128
782 1129 function wppm_cancel_comment(){ <?php
783 1130 if(!empty($wppm_rich_text_editor) && ($wppm_rich_text_editor == 1)){
@@ -800,54 +1147,64 @@
800 1147 <?php }?>
801 1148 }
802 1149
803 1150 function wppm_add_task_comment(){
804 - <?php
805 - if(!empty($wppm_rich_text_editor) && ($wppm_rich_text_editor == 1)){
806 - ?>
807 - tinymce.remove();
808 - tinymce.init({
809 - selector:'#wppm_task_comment',
810 - body_id: 'wppm_task_comment',
811 - directionality : '<?php //echo 'rtl'; ?>',
812 - menubar: false,
813 - statusbar: false,
814 - height : '200',
815 - width : '100%',
816 - plugins: [
817 - 'lists link image directionality paste textcolor'
818 - ],
819 - image_advtab: true,
820 - toolbar: '<?php echo $bold ?> <?php echo $italic ?> <?php echo $underline ?> <?php echo $blockquote?> | <?php echo $align ?> | <?php echo $bullist ?> <?php echo $numlist ?> | <?php echo $rtl ?> | <?php echo $link ?> <?php echo $image ?> | <?php echo $forecolor?> <?php echo $backcolor?> <?php echo $strikethrough ?>',
821 - branding: false,
822 - autoresize_bottom_margin: 20,
823 - browser_spellcheck : true,
824 - relative_urls : false,
825 - remove_script_host : false,
826 - convert_urls : true,
827 - paste_as_text: true,
828 - setup: function (editor) {
829 - }
830 - });
831 - <?php } else{ ?>
1151 + if((wppm_admin.rich_text_editor == 1)){
1152 + tinymce.remove();
1153 + tinymce.init({
1154 + selector:'#wppm_task_comment',
1155 + body_id: 'wppm_task_comment',
1156 + directionality : '<?php //echo 'rtl'; ?>',
1157 + menubar: false,
1158 + statusbar: false,
1159 + height : '200',
1160 + width : '100%',
1161 + plugins: [
1162 + 'lists link image directionality paste textcolor'
1163 + ],
1164 + image_advtab: true,
1165 + toolbar:'<?php echo esc_js( $toolbar ); ?>',
1166 + branding: false,
1167 + autoresize_bottom_margin: 20,
1168 + browser_spellcheck : true,
1169 + relative_urls : false,
1170 + remove_script_host : false,
1171 + convert_urls : true,
1172 + paste_as_text: true,
1173 + setup: function (editor) {
1174 + wppmMentionSetup(editor);
1175 + }
1176 + });
1177 + } else{
832 1178 jQuery('#wppm_task_comment').css("width", "100%");
833 1179 jQuery('#wppm_task_comment').css("height", "160px");
834 1180 jQuery('#wppm_task_comment').css("color", "#000");
835 - <?php }?>
1181 + }
836 1182 jQuery('#wppm_comment_btn').show();
837 1183 }
838 1184
839 -function wppm_submit_task_comment(id,proj_id){
1185 +function wppm_submit_task_comment(id, proj_id){
1186 + jQuery('#wppm_mention_list').remove();
840 1187 var dataform = new FormData(jQuery('#wppm_open_task')[0]);
841 1188 dataform.append('action','wppm_submit_task_comment');
842 - <?php
843 - if(!empty($wppm_rich_text_editor) && ($wppm_rich_text_editor == 1)){ ?>
844 - var comment_body = tinyMCE.get('wppm_task_comment').getContent().trim();
845 - <?php } else{ ?>
846 - var comment_body = jQuery("#wppm_task_comment").val();
847 - <?php }?>
848 - dataform.append('comment_body',comment_body);
849 - dataform.append('task_id',id);
1189 + let comment_body;
1190 + if(wppm_admin.rich_text_editor == 1){
1191 + const editor = tinyMCE.get('wppm_task_comment');
1192 + // Remove dropdown from TinyMCE iframe
1193 + const dropdown = editor.getDoc().getElementById('wppm_mention_list');
1194 + if (dropdown) {
1195 + dropdown.remove();
1196 + }
1197 + comment_body = editor.getContent().trim();
1198 + //comment_body = tinyMCE.get('wppm_task_comment').getContent().trim();
1199 + // remove mention dropdown if accidentally inserted
1200 + //comment_body = comment_body.replace(/<div[^>]*id="wppm_mention_list"[^>]*>.*?<\/div>/gi, '');
1201 + comment_body = comment_body.replace( /<div class="mention-item"[\s\S]*?<\/div>/g, '');
1202 + } else {
1203 + comment_body = jQuery("#wppm_task_comment").val();
1204 + }
1205 + dataform.append('comment_body', comment_body);
1206 + dataform.append('task_id', id);
850 1207 jQuery('#wppm_task_container').html(wppm_admin.loading_html);
851 1208 jQuery.ajax({
852 1209 url: wppm_admin.ajax_url,
853 1210 type: 'POST',
@@ -854,12 +1211,12 @@
854 1211 data: dataform,
855 1212 processData: false,
856 1213 contentType: false
857 1214 })
858 - .done(function (response_str) {
859 - if((proj_id!=0)||(proj_id!="")){
860 - wppm_open_project_tasks(id,proj_id);
861 - }else if((proj_id==0)||(proj_id=="")){
1215 + .done(function () {
1216 + if (proj_id != 0 && proj_id != "") {
1217 + wppm_open_project_tasks(id, proj_id);
1218 + } else {
862 1219 wppm_open_task(id);
863 1220 }
864 1221 });
865 1222 }
@@ -898,9 +1255,10 @@
898 1255 var file_extension = file_name_split[file_name_split.length-1];
899 1256 file_extension = file_extension.toLowerCase();
900 1257 if( (jQuery.inArray(file_extension,allowedExtension) > -1)){
901 1258 flag = true;
902 - alert("<?php _e('Attached file type not allowed!','taskbuilder')?>");
1259 + alert("<?php echo esc_js(__( 'Attached file type not allowed!', 'taskbuilder' ) ); ?>");
1260 +
903 1261 };
904 1262 <?php
905 1263 $max_upload = (int)(ini_get('upload_max_filesize')); ?>
906 1264 var current_filesize=file.size/1000000;
@@ -905,9 +1263,9 @@
905 1263 $max_upload = (int)(ini_get('upload_max_filesize')); ?>
906 1264 var current_filesize=file.size/1000000;
907 1265 if(current_filesize > <?php echo esc_attr($max_upload); ?>){
908 1266 flag = true;
909 - alert("<?php _e('File size exceed allowed limit!','taskbuilder')?>");
1267 + alert("<?php echo esc_js(__('File size exceed allowed limit!','taskbuilder')); ?>");
910 1268 }
911 1269 if (!flag){
912 1270 var html_str = '<div class="wppm_attachment">'+
913 1271 '<div class="progress" style="float: none !important; width: unset !important;">'+
@@ -954,6 +1312,227 @@
954 1312 });
955 1313 }
956 1314 });
957 1315 jQuery('#wppm_attachment_upload').trigger('click');
1316 +}
1317 +
1318 +function wppmMentionSetup(editor) {
1319 + let mentionIndex = -1;
1320 + editor.on('keyup', function (e) {
1321 + editor.lastMentionRange = editor.selection.getRng();
1322 + let rng = editor.selection.getRng();
1323 + let node = rng.startContainer;
1324 +
1325 + if (!node || node.nodeType !== 3) return;
1326 +
1327 + let text = node.textContent;
1328 + let cursorPos = rng.startOffset;
1329 + let textBeforeCursor = text.substring(0, cursorPos);
1330 +
1331 + let match = textBeforeCursor.match(/@(\w*)$/);
1332 + let dropdown = getMentionDropdown(editor);
1333 +
1334 + if (match) {
1335 + let query = match[1];
1336 + let rect = rng.getBoundingClientRect();
1337 + if (!rect || rect.top === 0) {
1338 + rect = editor.selection.getNode().getBoundingClientRect();
1339 + }
1340 + let top = rect.bottom + editor.getWin().scrollY;
1341 + let left = rect.left + editor.getWin().scrollX;
1342 + jQuery.post(wppm_admin.ajax_url, {
1343 + action: 'wppm_filter_autocomplete',
1344 + term: query,
1345 + field : 'task_user_name',
1346 + task_id:<?php echo esc_attr($task_id) ?>,
1347 + proj_id:<?php echo esc_attr($proj_id) ?>
1348 + }, function (res) {
1349 +
1350 + if (typeof res === "string") res = JSON.parse(res);
1351 + if (res.success) res = res.data;
1352 +
1353 + if (!Array.isArray(res)) return;
1354 +
1355 + dropdown.empty();
1356 + if( res.length === 0 ){
1357 + dropdown.hide();
1358 + return;
1359 + }else{
1360 + res.forEach(user => {
1361 + let item = jQuery('<div>')
1362 + .addClass('mention-item')
1363 + .attr('data-username', user.label)
1364 + .attr('data-user-id', user.user_id)
1365 + .text(user.label)
1366 + .css({
1367 + padding: '8px 12px',
1368 + cursor: 'pointer',
1369 + fontSize: '14px',
1370 + color: '#333',
1371 + background: '#fff',
1372 + borderBottom: '1px solid #eee'
1373 + });
1374 +
1375 + item.on('mouseenter', function () {
1376 + jQuery(this).css({
1377 + background: '#0073aa',
1378 + color: '#fff'
1379 + });
1380 + });
1381 + item.on('mouseleave', function () {
1382 + if (!jQuery(this).hasClass('active')) {
1383 + jQuery(this).css({
1384 + background: '#fff',
1385 + color: '#333'
1386 + });
1387 + }
1388 + });
1389 + dropdown.append(item);
1390 + });
1391 + let items = dropdown.find('.mention-item');
1392 + items.removeClass('active').css({
1393 + background: '#fff',
1394 + color: '#333'
1395 + });
1396 + items.eq(0)
1397 + .addClass('active')
1398 + .css({
1399 + background: '#0073aa',
1400 + color: '#fff'
1401 + });
1402 + mentionIndex = 0;
1403 + updateActiveItem(items.eq(0), mentionIndex);
1404 + dropdown.css({
1405 + position: 'absolute',
1406 + display: 'none',
1407 + background: '#fff',
1408 + border: '1px solid #ddd',
1409 + borderRadius: '6px',
1410 + padding: '5px 0',
1411 + minWidth: '180px',
1412 + maxHeight: '220px',
1413 + overflowY: 'auto',
1414 + boxShadow: '0 4px 10px rgba(0,0,0,.15)',
1415 + zIndex: 999999999999999
1416 + }).show();
1417 + }
1418 + });
1419 + } else {
1420 + dropdown.hide();
1421 + }
1422 + });
1423 + editor.on('keydown', function (e) {
1424 + let dropdown = getMentionDropdown(editor);
1425 + let items = dropdown.find('.mention-item');
1426 +
1427 + if (!dropdown.is(':visible') || !items.length) return;
1428 +
1429 + // DOWN
1430 + if (e.key === 'ArrowDown') {
1431 + e.preventDefault();
1432 + mentionIndex++;
1433 +
1434 + if (mentionIndex >= items.length) {
1435 + mentionIndex = 0;
1436 + }
1437 + updateActiveItem(items, mentionIndex);
1438 + items.removeClass('active').css({
1439 + background: '#fff',
1440 + color: '#333'
1441 + });
1442 +
1443 + items.eq(mentionIndex)
1444 + .addClass('active')
1445 + .css({
1446 + background: '#0073aa',
1447 + color: '#fff'
1448 + });
1449 + }
1450 +
1451 + // UP
1452 + if (e.key === 'ArrowUp') {
1453 + e.preventDefault();
1454 + mentionIndex--;
1455 + if (mentionIndex < 0) {
1456 + mentionIndex = items.length - 1;
1457 + }
1458 + updateActiveItem(items, mentionIndex);
1459 + items.removeClass('active').css({
1460 + background: '#fff',
1461 + color: '#333'
1462 + });
1463 +
1464 + items.eq(mentionIndex)
1465 + .addClass('active')
1466 + .css({
1467 + background: '#0073aa',
1468 + color: '#fff'
1469 + });
1470 + }
1471 + // ENTER
1472 + if (e.key === 'Enter') {
1473 + if (mentionIndex >= 0) {
1474 + e.preventDefault();
1475 + items.eq(mentionIndex).trigger('click');
1476 + }
1477 + }
1478 + // ESC
1479 + if (e.key === 'Escape') {
1480 + dropdown.hide();
1481 + mentionIndex = -1;
1482 + }
1483 + });
1484 + editor.on('click', function (e) {
1485 + let target = jQuery(e.target);
1486 + if (target.hasClass('mention-item')) {
1487 + let username = target.data('username');
1488 + let userId = target.data('user-id');
1489 +
1490 + editor.focus();
1491 +
1492 + let rng = editor.lastMentionRange || editor.selection.getRng();
1493 + editor.selection.setRng(rng);
1494 +
1495 + let node = rng.startContainer;
1496 + if (!node || node.nodeType !== 3) return;
1497 +
1498 + let text = node.textContent;
1499 + let cursorPos = rng.startOffset;
1500 +
1501 + let lastAtIndex = text.substring(0, cursorPos).lastIndexOf('@');
1502 +
1503 + if (lastAtIndex !== -1) {
1504 +
1505 + let range = editor.selection.getRng();
1506 + range.setStart(node, lastAtIndex);
1507 + range.setEnd(node, cursorPos);
1508 +
1509 + editor.selection.setRng(range);
1510 +
1511 + editor.selection.setContent(
1512 + '<span class="wppm-mention" contenteditable="false" data-username="' + username + '" data-user-id="' + userId + '">@' + username + '</span>&nbsp;'
1513 + );
1514 + }
1515 + getMentionDropdown(editor).hide();
1516 + }
1517 + });
1518 +
1519 + editor.on('blur', function () {
1520 + getMentionDropdown(editor).hide();
1521 + });
1522 +
1523 + editor.on('init', function () {
1524 + let body = editor.getBody();
1525 + if (!body) return;
1526 +
1527 + body.addEventListener('mousedown', function (e) {
1528 + if (e.target.classList.contains('mention-item')) {
1529 + e.preventDefault();
1530 + }
1531 + });
1532 + if (!editor.mentionDropdown) {
1533 + editor.mentionDropdown = jQuery('<div class="mention-dropdown"></div>');
1534 + jQuery('body').append(editor.mentionDropdown); // ✅ ONLY HERE
1535 + }
1536 + });
958 1537 }
959 1538 </script>