edit existing note, editor state

This commit is contained in:
catto 2024-04-14 11:50:12 +02:00
parent a5e6806aca
commit c4de94d395
6 changed files with 146 additions and 21 deletions

View File

@ -23,26 +23,29 @@
<div class="menu" id="contextMenu">
<button id="deleteButton">Delete</button>
</div>
<h1>Snotes Deck</h1>
<h1>Maid Notes</h1>
<div id="button-row">
<button class="row" id="show-notes-button">Refresh Notes</button>
<button type="submit" id="save-button">Save</button>
<button class="row" id="new-button">New</button>
</div>
</div>
<div class="container">
<div class="sidebar">
<div class="note-sidebar-container" id="note-sidebar-container">
<!--
<!-- This is how the generated notes will look like:
<div class="sidebar-note rightclick-element">
<span class="sidebar-note-id">1</span>
<span class="sidebar-note-content">Lorem ipsum dolor sit amet...</span>
<span class="sidebar-note-tag">Tag</span>
</div>
-->
</div>
</div>
<div class="editor">
<input id="create-tag" placeholder="Tag..." />
<textarea id="create-input" placeholder="Note..."></textarea>
<textarea id="create-input" placeholder="Type your note here..."></textarea>
<p id="create-msg"></p>
<p style="white-space: pre-line" id="notes-list"></p>

View File

@ -124,6 +124,18 @@ pub fn delete_specific_note(id: i32) -> Result<(), String> {
}
}
pub fn edit_specific_note(id: i32, tag: &str, content: &str) -> Result<(), String> {
let home = home_dir().unwrap().join(".snotes.db");
let connection = Connection::open(home).map_err(|e| format!("Database Error: {}", e))?;
let query = "UPDATE notes SET tag = ?1, content = ?2 WHERE nid = ?3";
match connection.execute(query, [&tag, &content, &id.to_string().as_str()]) {
Ok(1) => Ok(()), // 1 row affected means the note was updated successfully
Ok(_) => Err("No note with the provided ID found.".to_string()),
Err(e) => Err(format!("Edit Error: {}", e)),
}
}
#[cfg(test)]
mod tests {
use super::*;

View File

@ -9,9 +9,10 @@ fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name)
}
/// get ALL notes in the Database. If you don't want this, set show_notes(false)
#[tauri::command]
fn get_notes_list() -> String {
let notes = show_notes(false, "").unwrap();
let notes = show_notes(true, "").unwrap();
notes.to_string()
}
@ -30,9 +31,22 @@ fn delete_specific_note(id: u32) -> bool {
libsnotes::delete_specific_note(id.try_into().unwrap()).is_ok()
}
#[tauri::command]
fn update_specific_note(id: u32, content: &str, tag: &str) -> bool {
println!("update specific note");
libsnotes::edit_specific_note(id.try_into().unwrap(), tag, content).is_ok()
}
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet, get_notes_list, create_note, delete_specific_note])
.invoke_handler(tauri::generate_handler![
greet,
get_notes_list,
create_note,
delete_specific_note,
update_specific_note
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}

View File

@ -8,7 +8,7 @@
},
"package": {
"productName": "snotes-deck",
"version": "0.0.2"
"version": "0.0.3"
},
"tauri": {
"allowlist": {

View File

@ -11,19 +11,54 @@ let noteSidebarContainerEl: HTMLDivElement | null;
let noteArray: Note[] = []
// create
async function createNote() {
console.log("reached ssssjs")
/** ID of current note, if we're editing an existing note */
let currentNoteId: number | null = null;
enum EditorState {
NEW,
EDITING
}
/** Editor always initializes in the NEW state */
let editorState = EditorState.NEW
/**
* Saves the note.
* Or updates an existing note depending on editor state
*/
async function saveNote() {
if (createNoteContentEl && createNoteTagEl) {
console.log("reached js")
await invoke("create_note", {
content: createNoteContentEl.value,
tag: createNoteTagEl.value
});
switch (editorState) {
case EditorState.NEW:
console.log("creating new note..")
await invoke("create_note", {
content: createNoteContentEl.value,
tag: createNoteTagEl.value
});
clearEditor();
break;
case EditorState.EDITING:
console.log("updating existing note..")
if (currentNoteId !== null) {
await invoke("update_specific_note", {
id: currentNoteId,
content: createNoteContentEl.value,
tag: createNoteTagEl.value
});
clearEditor();
} else {
console.error("No note is currently being edited");
}
break;
}
}
}
// read
/**
* Retrieve Notes from DB and fill the sidebar with them
*/
async function showNotes() {
if (notesMsgEl) {
const array: Array<any> = await retrieveNotes();
@ -56,9 +91,14 @@ window.addEventListener("DOMContentLoaded", () => {
showNotes();
document.querySelector("#save-button")?.addEventListener("click", (e) => {
e.preventDefault();
createNote();
saveNote();
showNotes();
});
document.querySelector("#new-button")?.addEventListener("click", (e) => {
e.preventDefault();
clearEditor();
showNotes();
})
document.querySelector("#show-notes-button")?.addEventListener("click", (e) => {
e.preventDefault();
showNotes();
@ -94,14 +134,13 @@ function refreshContextMenuElements() {
let posY = mouseY + menuHeight > viewportHeight ? mouseY - menuHeight : mouseY;
contextMenu.style.display = 'block'; // Show the custom context menu
contextMenu.style.display = 'block';
contextMenu.style.left = `${posX}px`;
contextMenu.style.top = `${posY}px`;
const noteIdElement = element.querySelector('.sidebar-note-id');
if (noteIdElement) {
const noteIdStr = noteIdElement.textContent;
//console.log('Right-clicked note id:', noteId);
if (noteIdStr) {
const noteId: Number = parseInt(noteIdStr);
showNoteSidebarContextMenu(noteId);
@ -177,8 +216,7 @@ function handleSidebarNoteClick(id: Number): any {
});
if (n) {
createNoteContentEl.value = n.content as string;
createNoteTagEl.value = n.tag as string;
openNote(n);
} else {
// don't destory currently editing note if this fails
console.error("Error fetching note");
@ -211,3 +249,28 @@ function showNoteSidebarContextMenu(noteId: Number) {
}
}
/**
* When a note is opened, the editor will switch to the EDITING state and get filled with
* Note content
*/
function openNote(note: Note) {
if (createNoteContentEl && createNoteTagEl) {
createNoteContentEl.value = note.content as string;
createNoteTagEl.value = note.tag as string;
currentNoteId = note.id as number;
// switch state
editorState = EditorState.EDITING;
}
}
/**
* When new note is clicked, clear the editor content and switch Editor state
*/
function clearEditor() {
if (createNoteContentEl && createNoteTagEl) {
createNoteContentEl.value = "";
createNoteTagEl.value = "";
currentNoteId = null;
editorState = EditorState.NEW;
}
}

View File

@ -35,7 +35,7 @@
}
.editor {
background-color: #24c8db;
background-color: #41005a;
margin-left: 1em;
width: 100%;
height: 100%;
@ -109,6 +109,10 @@ button:active {
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
resize: none;
font-family: Inter, Avenir, Helvetica, Arial, sans-serif;
background-color: #252525;
color: #f0f0f0
}
#create-input:focus {
@ -140,6 +144,11 @@ button {
padding: 20px;
}
.note-sidebar-container {
max-height: 100%;
overflow-y: scroll;
}
.sidebar-note {
display: flex;
flex-direction: row;
@ -192,4 +201,28 @@ button {
.menu button:hover {
background-color: #770079;
}
/* MISC */
/* Fancier Scrollbar */
/* Hide scrollbar track */
::-webkit-scrollbar {
width: 4px;
visibility: hidden;
}
::-webkit-scrollbar:hover {
visibility: visible;
/* Show the scrollbar when hovered */
}
::-webkit-scrollbar-thumb {
background: #888;
}
::-webkit-scrollbar-thumb:hover {
background: #555;
}