diff --git a/application/controllers/Notes.php b/application/controllers/Notes.php index de681e717..6e5dcd8be 100644 --- a/application/controllers/Notes.php +++ b/application/controllers/Notes.php @@ -275,6 +275,30 @@ class Notes extends CI_Controller { $this->output->set_content_type('application/json')->set_output(json_encode($response)); } + // API endpoint to get note details by ID + public function get($id = null) { + $this->load->model('note'); + $clean_id = $this->security->xss_clean($id); + if (!is_numeric($clean_id) || !$this->note->belongs_to_user($clean_id, $this->session->userdata('user_id'))) { + $this->output->set_content_type('application/json')->set_output(json_encode(['error' => _("Not found or not allowed")])); + return; + } + $query = $this->note->view($clean_id); + if ($query && $query->num_rows() > 0) { + $row = $query->row(); + $response = [ + 'id' => $row->id, + 'category' => $row->cat, + 'user_id' => $row->user_id, + 'title' => $row->title, + 'content' => $row->note + ]; + $this->output->set_content_type('application/json')->set_output(json_encode($response)); + } else { + $this->output->set_content_type('application/json')->set_output(json_encode(['error' => _("Not found")])); + } + } + // Form validation callback for add: unique Contacts note title for user, only core callsign public function contacts_title_unique($title = null) { $category = $this->input->post('category', TRUE); @@ -315,7 +339,8 @@ class Notes extends CI_Controller { // Check for existing note with the same title $this->load->model('note'); - if ($this->note->get_note_id_by_category($user_id, 'Contacts', $core) > 0) { + $existing_id = $this->note->get_note_id_by_category($user_id, 'Contacts', $core); + if ($existing_id > 0 && $existing_id != $note_id) { $this->form_validation->set_message('contacts_title_unique_edit', __("A note with this callsign already exists in your Contacts. Please enter a unique callsign.")); return FALSE; } @@ -324,4 +349,6 @@ class Notes extends CI_Controller { return TRUE; } + + } diff --git a/application/models/Note.php b/application/models/Note.php index b2b968060..f5f247ea0 100644 --- a/application/models/Note.php +++ b/application/models/Note.php @@ -80,7 +80,8 @@ class Note extends CI_Model { $title = str_replace('0', 'Ø', $check_title); } // Check for existing note with same title in Contacts category - if ($this->get_note_id_by_category($user_id, $category, $check_title) && $category === 'Contacts') { + $existing_id = $this->get_note_id_by_category($user_id, $category, $check_title); + if ($existing_id > 0 && $existing_id != $note_id && $category === 'Contacts') { show_error(__("In Contacts category, the titles of the notes need to be unique.")); return; } diff --git a/application/views/qso/index.php b/application/views/qso/index.php index 3af9573c1..9b9d3a9dc 100644 --- a/application/views/qso/index.php +++ b/application/views/qso/index.php @@ -720,7 +720,9 @@ switch ($date_format) {
- + + +
diff --git a/assets/js/sections/qso.js b/assets/js/sections/qso.js index 7ac238dfa..33f6bdcb4 100644 --- a/assets/js/sections/qso.js +++ b/assets/js/sections/qso.js @@ -73,30 +73,92 @@ function getUTCDateStamp(el) { $(el).attr('value', formatted_date); } + + var saveBtn = document.getElementById('callsign-note-save-btn'); + function setNoteEditorState(state, noteText, saveBtn) { + if (!noteEditor) return; + if (state === 'no_callsign') { + + } else if (state === 'no_note') { + + } else if (state === 'has_note') { + + } + } + + // Note icon state logic -function setNotesVisibility(state) { +function setNotesVisibility(state, noteText = "") { var $icon = $('#note_create_edit'); $icon.removeClass('text-secondary text-info'); - $icon.removeAttr('data-bs-original-title'); - $icon.removeAttr('title'); - if (state == 2) { - // Callsign with existing note - $icon.show(); - $icon.addClass('text-info'); - $icon.attr('data-bs-original-title', lang_qso_note_edit); - $('#callsign-notes').show(); - } else if (state == 1) { - // Callsign, no note yet - $icon.show(); - $icon.attr('data-bs-original-title', lang_qso_note_add); - $('#callsign-notes').show(); - } else { - // No callsign - hide icon - $icon.hide(); - $icon.attr('data-bs-original-title', lang_qso_note_no_callsign); - $('#callsign-notes').hide(); + $icon.removeAttr('data-bs-original-title title'); + var $noteCard = $('#callsign-notes'); + var $saveBtn = $('#callsign-note-save-btn'); + var $editorElem = $('#callsign_note_content'); + var noteEditor = $editorElem.data('easymde'); + var $editBtn = $('#callsign-note-edit-btn'); + + // Initialize EasyMDE if not already done + if (!noteEditor && typeof EasyMDE !== 'undefined') { + noteEditor = new EasyMDE({ + element: $editorElem[0], + spellChecker: false, + toolbar: [ + "bold", "italic", "heading", "|","preview", "|", + "quote", "unordered-list", "ordered-list", "|", + "link", "image", "|", + "guide" + ], + forceSync: true, + status: false, + maxHeight: '250px', + autoDownloadFontAwesome: false, + autoRefresh: { delay: 250 }, + }); + $editorElem.data('easymde', noteEditor); } + if (state === 0) { + // No callsign + $icon.hide().attr('data-bs-original-title', lang_qso_note_no_callsign); + + // Hide note card + $noteCard.hide(); + + } else if (state === 1) { + // Callsign, no note yet + $icon.show().attr('data-bs-original-title', lang_qso_note_add); + + // Show note card + $noteCard.show(); + + // Hide editor toolbar, set value and show preview + document.querySelector('.EasyMDEContainer .editor-toolbar').style.display = 'none'; + noteEditor.value('No notes found for this callsign - click Edit Note to add notes.'); + noteEditor.togglePreview(); + noteEditor.codemirror.setOption('readOnly', true); + + } else if (state === 2) { + // Callsign with existing note + $icon.show().addClass('text-info').attr('data-bs-original-title', lang_qso_note_edit); + + // Show note card + $noteCard.show(); + + // Hide editor toolbar, set value and show preview + document.querySelector('.EasyMDEContainer .editor-toolbar').style.display = 'none'; + noteEditor.value(noteText); + noteEditor.togglePreview(); + noteEditor.codemirror.setOption('readOnly', true); + } + + // Show Edit button for states 1 and 2 + if (state === 1 || state === 2) { + $editBtn.removeClass('d-none').show(); + } else { + $editBtn.addClass('d-none').hide(); + } + // If Bootstrap tooltip is initialized, update it if ($icon.data('bs.tooltip')) { $icon.tooltip('dispose').tooltip(); @@ -923,7 +985,7 @@ function reset_fields() { setNotesVisibility(0); // Always gray out note icon on reset } -// Set note icon state: 0 = gray, 1 = empty, 2 = filled based on callsign +// Get status of notes for this callsign function get_note_icon(callsign){ $.get( window.base_url + 'index.php/notes/check_duplicate', @@ -935,8 +997,23 @@ function get_note_icon(callsign){ if (typeof data === 'string') { try { data = JSON.parse(data); } catch (e) { data = {}; } } - if (data && data.exists === true) { - setNotesVisibility(2); + if (data && data.exists === true && data.id) { + // Get the note content using the note ID + $.get( + window.base_url + 'index.php/notes/get/' + data.id, + function(noteData) { + if (typeof noteData === 'string') { + try { noteData = JSON.parse(noteData); } catch (e) { noteData = {}; } + } + if (noteData && noteData.content) { + setNotesVisibility(2, noteData.content); + } else { + setNotesVisibility(2,'Error'); + } + } + ).fail(function() { + setNotesVisibility(2,'Error'); + }); } else { setNotesVisibility(1); } @@ -2490,25 +2567,6 @@ $(document).ready(function () { ); }); - if (document.getElementById('callsign_note_content')) { - if (typeof EasyMDE !== 'undefined') { - new EasyMDE({ - element: document.getElementById('callsign_note_content'), - spellChecker: false, - toolbar: [ - "bold", "italic", "heading", "|","preview", "|", - "quote", "unordered-list", "ordered-list", "|", - "link", "image", "|", - "guide" - ], - forceSync: true, - status: false, - maxHeight: '250px', - autoDownloadFontAwesome: false, - }); - } - } - // everything loaded and ready 2 go bc.postMessage('ready');