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 +538 -81 5.0.46.0.6 View file →
@@ -4,9 +4,11 @@
4 4 }
5 5
6 6 global $current_user,$wpdb,$wppmfunction;
7 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');
@@ -28,9 +30,12 @@
28 30 if ( $auth_code && $auth_id == $auth_code ) {
29 31 $url_auth = true;
30 32 }
31 33 if (!(($current_user->ID && $current_user->has_cap('manage_options')) || ($wppmfunction->has_permission('view_task',$id)) || ($url_auth==true))) { ?>
32 - <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>
33 38 <?php
34 39 wp_die();
35 40 }
36 41 $proj_id = isset($_POST) && isset($_POST['proj_id']) ? intval(sanitize_text_field(wp_unslash($_POST['proj_id']))) : 0;
@@ -198,15 +203,23 @@
198 203 }else{
199 204 $archive_style= "display:none;";
200 205 }
201 206 if($proj_id==0) {
202 - ?> <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 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>
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>
203 208 <?php }
204 209 else{ ?>
205 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>
206 211 <?php } ?>
207 - <?php if($proj_id==0) {
208 - $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 + }
209 222 ?>
210 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>
211 224 <?php }
212 225 else{
@@ -212,15 +225,18 @@
212 225 else{
213 226 ?>
214 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>
215 228 <?php } ?>
216 - <?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"; ?>
217 - <?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) ? "display:inline":"display:none"; ?>
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"; ?>
218 231 <?php $ar_css = ($task->is_archived==1) ? "display:none;" : "display:inline"; ?>
219 - <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>
220 - <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>
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>
221 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>
222 - <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) ?>)" style="<?php echo esc_attr($archive_style) ?>"><img src="<?php echo esc_url( WPPM_PLUGIN_URL . 'asset/images/archive.svg'); ?>" alt="archive"></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>
223 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' ) ); ?>">
224 240 <div class="menu" id="wppmprint_menu" onclick="event.stopPropagation();">
225 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>
226 242 <a href="#" id="wppm_downloadPDF" onclick="wppm_download_pdf(<?php echo esc_attr($id) ?>)">💾 <?php echo esc_html_e('Download PDF','taskbuilder');?></a>
@@ -225,9 +241,9 @@
225 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>
226 242 <a href="#" id="wppm_downloadPDF" onclick="wppm_download_pdf(<?php echo esc_attr($id) ?>)">💾 <?php echo esc_html_e('Download PDF','taskbuilder');?></a>
227 243 </div>
228 244 <?php do_action('wppm_individual_task_button',$id);?>
229 - </div>
245 + </div>
230 246 </div>
231 247 <div id="wppm_load_individual_task_container" class="row">
232 248 <div class="col-sm-8 wppm_body col-md-9">
233 249 <div class="wppm_task_details_container">
@@ -234,11 +250,26 @@
234 250 <div class="row">
235 251 <div class="col-sm-12">
236 252 <span class="wppm_task_label"> <?php echo isset($task->task_name) ? esc_html($task->task_name ):"" ?>
237 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) { ?>
238 - <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>
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>
239 255 <?php } ?>
240 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 + } ?>
241 272 </div>
242 273 </div>
243 274 <div class="row">
244 275 <div class="col-sm-3">
@@ -329,8 +360,168 @@
329 360 </div>
330 361 </div>
331 362 <?php do_action('wppm_after_task_details_in_open_task',$task->id, $task->project);?>
332 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 } ?>
333 524 <div class="wppm_task_checklist_container" id="wppm_task_checklist_container">
334 525 <div id="wppm_checklist_container">
335 526 <?php
336 527 if(!empty($wppm_checklist)){
@@ -421,28 +612,30 @@
421 612 <?php
422 613 }
423 614 } ?>
424 615 </div><?php
425 - if(($wppmfunction->has_permission('add_checklist',$task->id) || $current_user->has_cap('manage_options')) && $task->is_archived!=1){ ?>
426 - <div id="wppm_add_checklist_container">
427 - <div class="row">
428 - <div class="col-sm-12">
429 - <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>
430 623 </div>
431 - </div>
432 - <div class="row" id="wppm_add_new_checklist" style="display:none;">
433 - <div class="col-sm-12">
434 - <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">
435 - <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) ?>)">
436 - <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' ) ); ?>">
437 - <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>
438 631 </div>
439 - </div>
440 - </br>
441 - </div><?php
442 - } ?>
632 + </br>
633 + </div><?php
634 + }
635 + }?>
443 636 </div>
444 - <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;' ?>">
445 638 <div class="row">
446 639 <div class="col-sm-12" style="margin-top:5px;">
447 640 <span class="wppm_task_discussion"><?php echo esc_html_e('Comment','taskbuilder')?></span><br>
448 641 </div>
@@ -470,9 +663,9 @@
470 663 <div class="wppm_attachment_container col-sm-12" style="display:none;">
471 664 </div>
472 665 </div>
473 666 </div>
474 - <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;' ?>">
475 668 <?php
476 669 if(!empty($task_comment)){
477 670 foreach($task_comment as $comment){
478 671 $task_comment_meta = $wpdb->get_row( $wpdb->prepare(
@@ -484,9 +677,9 @@
484 677 absint($comment->id)
485 678 )
486 679 );
487 680 $user = get_userdata( $comment->created_by );
488 - $comment_body = (!empty($comment->body) ? wp_kses_post(wpautop($comment->body)) : '');
681 + $comment_body = (!empty($comment->body) ? ($comment->body) : '');
489 682 $date = wp_date("Y-m-d H:i:s" ,strtotime($comment->create_time));
490 683 $thread_date = wp_date("d F Y, h:i:s A" ,strtotime($date));
491 684 $attachment_ids = isset($comment->attachment_ids)? $comment->attachment_ids : '';
492 685 if($attachment_ids!=""){
@@ -574,11 +767,16 @@
574 767 </div>
575 768 </div>
576 769 <div class="wppm_thread_messege" style="color:<?php echo esc_attr($appearance_settings['comment-secondary-color']);?>">
577 770 <?php
578 - $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(),));
579 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'))){
580 - 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));
581 779 } elseif(!empty($comment->body) && (isset($task_comment_meta->comment_type) && $task_comment_meta->comment_type=='change_task_status')){ ?>
582 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
583 781 }elseif(!empty($comment->body) && (isset($task_comment_meta->comment_type) && $task_comment_meta->comment_type=='change_task_creator')){ ?>
584 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
@@ -628,8 +826,11 @@
628 826 if(!empty($attachments)){
629 827 foreach( $attachments as $attachment ):
630 828 $download_url = site_url('/').'?wppm_attachment='.$attachment.'&tid='.$id.'&tac='.$auth_id;
631 829 $attachment = absint($attachment);
830 + if (empty($attachment)) {
831 + continue; // or return, depending on the context
832 + }
632 833 $attach = $wpdb->get_row( $wpdb->prepare("SELECT * FROM {$wpdb->prefix}wppm_attachments where id=%d",$attachment));
633 834 $findStr = ".txt";
634 835 if(!empty( $attach)){
635 836 $attachment_name = preg_replace('/' . $findStr . '/', "", $attach->name, 1);
@@ -664,12 +865,14 @@
664 865 <div class="row wppm_widget" id="wppm_status_widget">
665 866 <div class="wppm-widget-header" style="background-color:<?php echo esc_attr($appearance_settings['widget-header-bg-color'])?>">
666 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>
667 868 <?php
668 - 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))){
669 - ?>
670 - <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>
671 - <?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 + }
672 875 }
673 876 ?>
674 877 </div>
675 878 <hr class="widget_divider">
@@ -680,11 +883,13 @@
680 883 <div class="row wppm_widget" id="wppm_raisedby_widget">
681 884 <div class="wppm-widget-header" style="background-color:<?php echo esc_attr($appearance_settings['widget-header-bg-color'])?>">
682 885 <h4 class="widget_header" style="color:<?php echo esc_attr($appearance_settings['widget-header-text-color'])?>">
683 886 <?php echo esc_html_e('Task Creator','taskbuilder')?></h4>
684 - <?php if ((($wppmfunction->has_permission('change_raised_by',$id ) || $current_user->has_cap('manage_options')) && ($task->is_archived!=1))) { ?>
685 - <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>
686 - <?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 + }?>
687 892 </div>
688 893 <hr class="widget_divider"> <?php
689 894 if(isset($task->created_by)){
690 895 $user_info = get_userdata($task->created_by);
@@ -701,11 +906,14 @@
701 906 </div>
702 907 <div class="row wppm_widget" id="wppm_task_users_widget_container">
703 908 <div class="wppm-widget-header" style="background-color:<?php echo esc_attr($appearance_settings['widget-header-bg-color'])?>">
704 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>
705 - <?php if ((($wppmfunction->has_permission('assign_task_users',$id ) || $current_user->has_cap('manage_options')) && ($task->is_archived!=1))) { ?>
706 - <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>
707 - <?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 + }?>
708 916 </div>
709 917 <hr class="widget_divider">
710 918 <div class="wppm-widget-body" style="background-color:<?php echo esc_attr($appearance_settings['widget-body-bg-color'])?>">
711 919 <div id="wppm_task_users">
@@ -768,8 +976,11 @@
768 976 // Hide when clicking outside
769 977 document.addEventListener('click', () => {
770 978 box.style.display = 'none';
771 979 });
980 + jQuery('#wppm_task_comment').on('focus', function(){
981 + // showMentionList('');
982 + });
772 983 <?php
773 984 if ((($current_user->ID && $current_user->has_cap('manage_options')) || $wppmfunction->has_permission('change_task_details',$task->id))){ ?>
774 985 jQuery("#wppm_edit_tstart_date").flatpickr({
775 986 enableTime: true,
@@ -832,47 +1043,59 @@
832 1043 $italic = (isset($wppm_toolbar_actions['italic']) && $wppm_toolbar_actions['italic']==1)? 'italic' :"";
833 1044 $underline = (isset($wppm_toolbar_actions['underline']) && $wppm_toolbar_actions['underline']==1)?'underline' :"";
834 1045 $blockquote = (isset($wppm_toolbar_actions['blockquote']) && $wppm_toolbar_actions['blockquote']==1)? 'blockquote' :"";
835 1046 $align = (isset($wppm_toolbar_actions['align']) && $wppm_toolbar_actions['align']==1)? ' alignleft aligncenter alignright ' :"";
836 - $bullist = (isset($wppm_toolbar_actions['bullist']) && $wppm_toolbar_actions['bullist']==1)? $bullist = 'bullist' :"";
837 - $numlist = (isset($wppm_toolbar_actions['numlist']) && $wppm_toolbar_actions['numlist']==1)? $numlist = 'numlist' :"";
838 - $rtl = (isset($wppm_toolbar_actions['rtl']) && $wppm_toolbar_actions['rtl']==1)? $rtl = 'rtl' :"";
839 - $link = (isset($wppm_toolbar_actions['link']) && $wppm_toolbar_actions['link']==1)? $link = 'link' :"";
840 - $image = (isset($wppm_toolbar_actions['wppm_insert_editor_img']) && $wppm_toolbar_actions['wppm_insert_editor_img']==1)? $image = 'image' :"";
841 - $forecolor = (isset($wppm_toolbar_actions['forecolor']) && $wppm_toolbar_actions['forecolor']==1)? $forecolor = 'forecolor' :"";
842 - $backcolor = (isset($wppm_toolbar_actions['backcolor']) && $wppm_toolbar_actions['backcolor']==1)? $backcolor = 'backcolor' :"";
843 - $strikethrough = (isset($wppm_toolbar_actions['strikethrough']) && $wppm_toolbar_actions['strikethrough']==1)? $strikethrough = 'strikethrough' :"";
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' :"";
844 1055 $toolbar = trim("$bold $italic $underline $blockquote | $align | $bullist $numlist | $rtl | $link $image | $forecolor $backcolor $strikethrough");
845 1056 if(($wppm_tinymce_visibility_open_task==1)){ ?>
846 1057 if((wppm_admin.rich_text_editor) && (wppm_admin.rich_text_editor.trim().length > 0) && (wppm_admin.rich_text_editor == 1)){
847 - tinymce.remove();
848 - tinymce.init({
1058 + getMentionDropdown(editor);
1059 + tinymce.remove();
1060 + tinymce.init({
849 1061 selector:'#wppm_task_comment',
850 1062 body_id: 'wppm_task_comment',
851 - directionality : '<?php //echo 'rtl'; ?>',
852 1063 menubar: false,
853 1064 statusbar: false,
854 1065 height : '200',
855 1066 width : '100%',
856 - plugins: [
857 - 'lists link image directionality paste textcolor'
858 - ],
859 - image_advtab: true,
860 - toolbar:'<?php echo esc_js( $toolbar ); ?>',
861 - branding: false,
862 - autoresize_bottom_margin: 20,
863 - browser_spellcheck : true,
864 - relative_urls : false,
865 - remove_script_host : false,
866 - convert_urls : true,
867 - 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 + `
868 1089 setup: function (editor) {
1090 + wppmmenwppmMentionSetup(editor)
1091 +
1092 + } // ✅ only ONE setup
1093 + });
1094 + jQuery('#wppm_comment_btn').show();
869 1095 }
870 - });
871 - jQuery('#wppm_comment_btn').show();
872 - }
873 - <?php } ?>
874 -});
1096 + <?php } ?>
1097 + });
875 1098
876 1099 jQuery(function(jQuery){
877 1100 // Checklist Sorting
878 1101 jQuery(".wppm_checklist_items_container").sortable({
@@ -947,8 +1170,9 @@
947 1170 remove_script_host : false,
948 1171 convert_urls : true,
949 1172 paste_as_text: true,
950 1173 setup: function (editor) {
1174 + wppmMentionSetup(editor);
951 1175 }
952 1176 });
953 1177 } else{
954 1178 jQuery('#wppm_task_comment').css("width", "100%");
@@ -957,18 +1181,30 @@
957 1181 }
958 1182 jQuery('#wppm_comment_btn').show();
959 1183 }
960 1184
961 -function wppm_submit_task_comment(id,proj_id){
1185 +function wppm_submit_task_comment(id, proj_id){
1186 + jQuery('#wppm_mention_list').remove();
962 1187 var dataform = new FormData(jQuery('#wppm_open_task')[0]);
963 1188 dataform.append('action','wppm_submit_task_comment');
964 - if((wppm_admin.rich_text_editor == 1)){
965 - var comment_body = tinyMCE.get('wppm_task_comment').getContent().trim();
966 - } else{
967 - var comment_body = jQuery("#wppm_task_comment").val();
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();
968 1204 }
969 - dataform.append('comment_body',comment_body);
970 - dataform.append('task_id',id);
1205 + dataform.append('comment_body', comment_body);
1206 + dataform.append('task_id', id);
971 1207 jQuery('#wppm_task_container').html(wppm_admin.loading_html);
972 1208 jQuery.ajax({
973 1209 url: wppm_admin.ajax_url,
974 1210 type: 'POST',
@@ -975,12 +1211,12 @@
975 1211 data: dataform,
976 1212 processData: false,
977 1213 contentType: false
978 1214 })
979 - .done(function (response_str) {
980 - if((proj_id!=0)||(proj_id!="")){
981 - wppm_open_project_tasks(id,proj_id);
982 - }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 {
983 1219 wppm_open_task(id);
984 1220 }
985 1221 });
986 1222 }
@@ -1076,6 +1312,227 @@
1076 1312 });
1077 1313 }
1078 1314 });
1079 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 + });
1080 1537 }
1081 1538 </script>