Skip to content

Commit

Permalink
Add button styling and disable empty note submission (#23)
Browse files Browse the repository at this point in the history
* Add button styling and disable empty note submission
* Delete notes button
  • Loading branch information
freetonik authored Nov 17, 2024
1 parent 76c7ef2 commit cd4dddb
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 31 deletions.
88 changes: 61 additions & 27 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,18 @@
<link rel="shortcut icon" href="{{FAVICON}}" />
<style>
@media (prefers-color-scheme: light) {
time {
color: #666;
}

.note code {
background-color: #dedcd1;
}

.note pre {
background-color: #dedcd1;
:root {
--color-secondary: #666;
--color-text-secondary: white;
--color-bg-secondary: #dedcd1;
}
}

@media (prefers-color-scheme: dark) {
time {
color: #BBB;
}

.note code {
background-color: #3a3a3a;
}

.note pre {
background-color: #3a3a3a;
:root {
--color-secondary: #BBB;
--color-text-secondary: black;
--color-bg-secondary: #3a3a3a;
}
}

Expand All @@ -48,13 +36,26 @@
#editor {
width: 100%;
height: 200px;
margin-bottom: 2em;
font-family: monospace;
padding: 1em;
resize: vertical;
box-sizing: border-box
}

#submitContainer {
margin-bottom: 1.5em;
text-align: right;
}

#submitButton {
font-family: monospace;
padding: 0.4em 1em;
background-color: var(--color-secondary);
color: var(--color-text-secondary);
border: none;
cursor: pointer;
}

.note> :first-child {
margin-top: 0;
}
Expand All @@ -68,12 +69,29 @@
padding-top: 0.25em;
}

.note .noteMetadata {
font-size: 0.9em;
font-family: monospace;
color: var(--color-secondary);
}

.note .noteMetadata a {
color: var(--color-secondary);
text-decoration: none;
}

.note .noteMetadata a:hover {
text-decoration: underline;
}

.note code {
padding: 0.25em;
background-color: var(--color-bg-secondary);
}

.note pre {
padding: 0.5em;
background-color: var(--color-bg-secondary);
}

.note pre code {
Expand All @@ -90,19 +108,14 @@
max-width: 100%;
}

time {
font-size: 0.9em;
margin-bottom: 0.25em;
font-family: monospace;
}
</style>
</head>

<body>

<textarea id="editor"
placeholder="Ctrl+Enter to save.&#10;Type / to search.&#10;Drag & drop files to attach.&#10;Start links with + to save local copies."></textarea>
<button id="submitButton">Submit</button>
<div id="submitContainer"><button id="submitButton">Submit</button></div>
<div id="notes">{{NOTES}}</div>

<script>
Expand Down Expand Up @@ -131,6 +144,9 @@
}

async function saveNotes() {
if (!editor.value) {
return;
}
const response = await fetch('/save', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
Expand All @@ -154,6 +170,24 @@
}
}

async function deleteNote(event, element) {
event.preventDefault();
if (!confirm('Are you sure you want to delete this note?')) {
return;
}

const timestamp = element.getAttribute('data-timestamp');
const response = await fetch(`/delete/${timestamp}`, {
method: 'DELETE',
});

if (response.ok) {
element.closest('.note').remove();
} else {
alert('Failed to delete note');
}
}

editor.addEventListener('input', async (e) => {
const text = editor.value;
if (text.startsWith('/')) {
Expand Down
36 changes: 32 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use axum::{
extract::{Path, State},
http::StatusCode,
response::Html,
routing::{get, post},
routing::{delete, get, post},
Json, Router,
};
use base64::{display::Base64Display, engine::general_purpose::STANDARD};
Expand Down Expand Up @@ -76,6 +76,7 @@ async fn main() {
.route("/save", post(save_note))
.route("/search/:query", get(search_notes))
.route("/upload", post(upload_file))
.route("/delete/:timestamp", delete(delete_note))
.layer(DefaultBodyLimit::max(CONTENT_LENGTH_LIMIT))
.nest_service("/attachments", ServeDir::new("attachments"))
.with_state(state);
Expand Down Expand Up @@ -136,8 +137,8 @@ async fn index(State(state): State<AppState>) -> Html<String> {
.rev()
.map(|note| {
format!(
"<div class=\"note\">{}<time datetime=\"{}\">{}</time></div>",
note.html, note.timestamp, note.timestamp
"<div class=\"note\">{}<div class=\"noteMetadata\"><time datetime=\"{}\">{}</time> [<a href=\"#\" data-timestamp=\"{}\" onclick=\"deleteNote(event, this)\">delete</a>]</div></div>",
note.html, note.timestamp, note.timestamp, note.timestamp
)
})
.collect::<Vec<_>>()
Expand Down Expand Up @@ -187,7 +188,7 @@ async fn save_note(
.open("notes.md")
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

writeln!(file, "{}\n{}\n\n---\n", timestamp, content)
write!(file, "{}\n{}\n\n---\n\n", timestamp, content)
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

info!("Note created: {}", timestamp);
Expand Down Expand Up @@ -250,6 +251,33 @@ async fn save_note(
Ok(())
}

// route DELETE /delete/{timestamp}
async fn delete_note(
State(state): State<AppState>,
Path(timestamp): Path<String>,
) -> Result<(), StatusCode> {
let mut notes = state.notes.lock().unwrap();

// Find and remove the note with matching timestamp
if let Some(index) = notes.iter().position(|note| note.timestamp == timestamp) {
notes.remove(index);

// Update the notes.md file
let content = notes
.iter()
.map(|note| format!("{}\n{}\n\n---\n\n", note.timestamp, note.content))
.collect::<String>();

fs::write("notes.md", content).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

info!("Note deleted: {}", timestamp);
Ok(())
} else {
error!("Note not found: {}", timestamp);
Err(StatusCode::NOT_FOUND)
}
}

// route GET /search/{query}
async fn search_notes(State(state): State<AppState>, Path(query): Path<String>) -> Json<Vec<Note>> {
let notes = state.notes.lock().unwrap();
Expand Down

0 comments on commit cd4dddb

Please sign in to comment.