MainWP-Client-Notes-For-Pro.../mainwp-work-notes-proreports-extention/mainwp-work-notes.js
Stingray82 0d81901848 Work Notes: Improve date handling, DB safety, and migration JS
- Added strict Y-m-d validation to save handler to prevent invalid manual date entries.
- Improved DB query safety:
  • ajax_load_work_note_action() now uses a single, clean $wpdb->prepare().
  • Switched delete handler to use $wpdb->delete().
- Polished migration toolbar JS injection for reliability.
- General code cleanup for consistency and maintainability.

Changelog:
* Added: Strict date format validation when saving notes, blocking invalid manual entries.
* Improved: Database query safety for loading and deleting notes.
* Improved: Migration toolbar JS injection reliability.
* Cleaned: General code formatting and minor logic refinements.
2025-08-12 13:43:24 +01:00

196 lines
No EOL
6.2 KiB
JavaScript

jQuery(document).ready(function ($) {
// ---- Cached selectors
const $noteId = $('input[name="note_id"]');
const $siteId = $('input[name="wpid"]');
const $date = $('#work_notes_date');
const $contentTA = $('textarea[name="work_notes_content"]');
const $saveBtn = $('#save-work-note');
// ---- Helpers
function getEditorContent() {
const ed = window.tinyMCE ? tinyMCE.get('work_notes_content') : null;
return ed ? ed.getContent() : $contentTA.val();
}
function setEditorContent(html) {
const ed = window.tinyMCE ? tinyMCE.get('work_notes_content') : null;
if (ed) ed.setContent(html || '');
$contentTA.val(html || '');
}
function setDateInput(value, triggerChange = true) {
// Prefer Flatpickr API when available
if (window.workNotesFlatpickrInstance) {
window.workNotesFlatpickrInstance.setDate(value || null, true); // true => triggerChange
} else {
$date.val(value || '');
if (triggerChange) $date.trigger('change');
}
}
// Replaces deprecated .focus()/.blur() event shorthands
function fixDatePicker() {
// If an altInput exists, ensure it's in sync
const val = $date.val();
setDateInput(val, true);
}
function resetForm() {
$noteId.val('-1');
$saveBtn.text('Save Work Note');
// Reset date to today where possible
const today = (window.mainwpWorkNotes && mainwpWorkNotes.today) ? mainwpWorkNotes.today : '';
setDateInput(today, true);
// Clear editor
setEditorContent('');
fixDatePicker();
}
function reloadNotesTable(wpid) {
$.post(window.mainwpWorkNotes.ajax_url, {
action: 'load_work_notes_form',
nonce: window.mainwpWorkNotes.nonce,
site_id: wpid
}).done(function (response) {
if (response && response.success && response.data && response.data.html) {
$('.ui.celled.table tbody').replaceWith(response.data.html);
// Using delegated handlers below, so no need to rebind, but call just in case
bindWorkNotesEvents();
} else {
alert((response && response.data && response.data.message) || 'Failed to reload notes.');
}
}).fail(function () {
alert('Failed to reload notes.');
});
}
function bindWorkNotesEvents() {
// EDIT note
$(document).off('click', '.edit-note').on('click', '.edit-note', function () {
const noteIdVal = $(this).data('note-id');
const wpid = $siteId.val();
$.post(window.mainwpWorkNotes.ajax_url, {
action: 'load_work_note',
nonce: window.mainwpWorkNotes.nonce,
wpid: wpid,
note_id: noteIdVal
}).done(function (response) {
if (response && response.success) {
$noteId.val(noteIdVal);
$saveBtn.text('Update Work Note');
// Date
setDateInput(response.data.date, true);
// Content
setEditorContent(response.data.content);
fixDatePicker();
} else {
alert(response && response.data ? response.data.message : 'Failed to load the note.');
}
}).fail(function () {
alert('Failed to load the note.');
});
});
// DELETE note
$(document).off('click', '.delete-note').on('click', '.delete-note', function () {
if (!window.confirm('Are you sure you want to delete this note?')) return;
const noteIdVal = $(this).data('note-id');
const wpid = $siteId.val();
$.post(window.mainwpWorkNotes.ajax_url, {
action: 'delete_work_note',
nonce: window.mainwpWorkNotes.nonce,
wpid: wpid,
note_id: noteIdVal
}).done(function (response) {
if (response && response.success) {
alert(response.data.message || 'Note deleted.');
reloadNotesTable(wpid);
resetForm();
} else {
alert(response && response.data ? response.data.message : 'Failed to delete the note.');
}
}).fail(function () {
alert('Failed to delete the note.');
});
});
}
// SAVE / UPDATE
$saveBtn.off('click').on('click', function () {
const noteIdVal = $noteId.val();
const wpid = $siteId.val();
// Gate Manual Entry
let dateVal = $date.val();
if (window.workNotesFlatpickrInstance) {
const fp = window.workNotesFlatpickrInstance;
// Prefer the selected date if present
if (fp.selectedDates && fp.selectedDates[0]) {
dateVal = fp.formatDate(fp.selectedDates[0], 'Y-m-d');
} else if (fp.altInput && fp.altInput.value) {
// If user typed into the alt input, parse it using altFormat
const parsed = fp.parseDate(fp.altInput.value, fp.config.altFormat);
if (parsed) {
dateVal = fp.formatDate(parsed, 'Y-m-d');
}
}
}
const content = getEditorContent();
$.post(window.mainwpWorkNotes.ajax_url, {
action: 'save_work_note',
nonce: window.mainwpWorkNotes.nonce,
note_id: noteIdVal,
wpid: wpid,
work_notes_date: dateVal,
work_notes_content: content
}).done(function (response) {
if (response && response.success) {
alert(response.data.message || 'Note saved.');
reloadNotesTable(wpid);
resetForm();
} else {
alert(response && response.data ? response.data.message : 'Failed to save the note.');
}
}).fail(function () {
alert('Failed to save the note.');
});
});
// ---- Init Flatpickr if present
if (typeof window.flatpickr !== 'undefined') {
window.workNotesFlatpickrInstance = flatpickr('#work_notes_date', {
dateFormat: 'Y-m-d',
altInput: true,
altFormat: (window.mainwpWorkNotes && mainwpWorkNotes.date_format) || 'd/m/Y',
defaultDate: $date.val() || (window.mainwpWorkNotes && mainwpWorkNotes.today) || null,
allowInput: true,
onChange: function (selectedDates, _str, inst) {
if (selectedDates[0]) {
$date.val(inst.formatDate(selectedDates[0], 'Y-m-d')).trigger('change');
}
},
onClose: function (_selectedDates, _str, inst) {
if (inst.altInput && inst.altInput.value) {
const parsed = inst.parseDate(inst.altInput.value, inst.config.altFormat);
if (parsed) {
$date.val(inst.formatDate(parsed, 'Y-m-d')).trigger('change');
}
}
}
});
}
// ---- Kick things off
fixDatePicker();
bindWorkNotesEvents();
});