mirror of
https://github.com/perstarkse/minne.git
synced 2026-03-13 05:45:35 +01:00
feat: content reader modal
This commit is contained in:
@@ -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 },
|
||||
))
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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" %}
|
||||
|
||||
42
html-router/templates/content/read_content_modal.html
Normal file
42
html-router/templates/content/read_content_modal.html
Normal 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 %}
|
||||
5
html-router/templates/icons/read_icon.html
Normal file
5
html-router/templates/icons/read_icon.html
Normal 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 |
@@ -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>
|
||||
Reference in New Issue
Block a user