feat: content reader modal

This commit is contained in:
Per Stark
2025-04-30 12:49:25 +02:00
parent 1230ea6126
commit bcdd3628ef
7 changed files with 80 additions and 11 deletions

View File

@@ -164,3 +164,22 @@ pub async fn delete_text_content(
},
))
}
pub async fn show_content_read_modal(
State(state): State<HtmlState>,
RequireUser(user): RequireUser,
Path(id): Path<String>,
) -> Result<impl IntoResponse, HtmlError> {
// Get and validate the text content
let text_content = User::get_and_validate_text_content(&id, &user.id, &state.db).await?;
#[derive(Serialize)]
pub struct TextContentReadModalData {
pub user: User,
pub text_content: TextContent,
}
Ok(TemplateResponse::new_template(
"content/read_content_modal.html",
TextContentReadModalData { user, text_content },
))
}

View File

@@ -2,7 +2,8 @@ mod handlers;
use axum::{extract::FromRef, routing::get, Router};
use handlers::{
delete_text_content, patch_text_content, show_content_page, show_text_content_edit_form,
delete_text_content, patch_text_content, show_content_page, show_content_read_modal,
show_text_content_edit_form,
};
use crate::html_state::HtmlState;
@@ -14,6 +15,7 @@ where
{
Router::new()
.route("/content", get(show_content_page))
.route("/content/{id}/read", get(show_content_read_modal))
.route(
"/content/{id}",
get(show_text_content_edit_form)

View File

@@ -18,15 +18,9 @@ use crate::{
use common::{
error::AppError,
storage::types::{
conversation::Conversation,
file_info::{FileError, FileInfo},
ingestion_task::IngestionTask,
knowledge_entity::KnowledgeEntity,
knowledge_relationship::KnowledgeRelationship,
text_chunk::TextChunk,
text_content::TextContent,
user::User,
StoredObject,
conversation::Conversation, file_info::FileInfo, ingestion_task::IngestionTask,
knowledge_entity::KnowledgeEntity, knowledge_relationship::KnowledgeRelationship,
text_chunk::TextChunk, text_content::TextContent, user::User,
},
};

View File

@@ -29,6 +29,10 @@
</p>
<div class="badge badge-soft badge-secondary mr-2">{{ text_content.category }}</div>
<div class="flex gap-2">
<button hx-get="/content/{{ text_content.id }}/read" hx-target="#modal" hx-swap="innerHTML"
class="btn btn-square btn-ghost btn-sm">
{% include "icons/read_icon.html" %}
</button>
<button hx-get="/content/{{ text_content.id }}" hx-target="#modal" hx-swap="innerHTML"
class="btn btn-square btn-ghost btn-sm">
{% include "icons/edit_icon.html" %}

View File

@@ -0,0 +1,42 @@
{% extends "modal_base.html" %}
{% block modal_class %}w-11/12 max-w-[90ch] max-h-[95%]{% endblock %}
{% block modal_content %}
{% if text_content.url_info.image_id %}
<img class="rounded-t-md overflow-clip" src="/file/{{text_content.url_info.image_id}}" />
{% endif %}
<div class="markdown-content prose" data-content="{{text_content.text | escape }}">
{{text_content.text | escape }}
</div>
<script src="/assets/marked.min.js"></script>
<script>
function initialize() {
marked.setOptions({
breaks: true, gfm: true, headerIds: false, mangle: false,
smartLists: true, smartypants: true, xhtml: false
});
console.log('initialized');
}
function renderStaticMarkdown() {
document.querySelectorAll('.markdown-content').forEach(el => {
console.log('hello');
const raw = el.getAttribute('data-content') || '';
el.innerHTML = marked.parse(raw);
});
}
function processMarkdown() {
initialize();
renderStaticMarkdown();
}
document.body.addEventListener('htmx:afterSettle', processMarkdown);
</script>
{% endblock %}
{% block primary_actions %}
{% endblock %}

View File

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
class="size-6">
<path stroke-linecap="round" stroke-linejoin="round"
d="M12 6.042A8.967 8.967 0 0 0 6 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 0 1 6 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 0 1 6-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0 0 18 18a8.967 8.967 0 0 0-6 2.292m0-14.25v14.25" />
</svg>

After

Width:  |  Height:  |  Size: 446 B

View File

@@ -1,5 +1,5 @@
<dialog id="body_modal" class="modal">
<div class="modal-box">
<div class="modal-box {% block modal_class %}{% endblock %} ">
<form id="modal_form" {% block form_attributes %}{% endblock %}>
<div class="flex flex-col space-y-4">
{% block modal_content %} <!-- Form fields go here in child templates -->
@@ -35,4 +35,7 @@
evt.target.innerHTML = '';
});
</script>
<form method="dialog" class="modal-backdrop">
<button>close</button>
</form>
</dialog>