mirror of
https://github.com/tcsenpai/pensieve.git
synced 2025-06-07 03:35:24 +00:00
198 lines
5.3 KiB
Svelte
198 lines
5.3 KiB
Svelte
<!-- Modal.svelte -->
|
|
<script>
|
|
import { ScrollArea } from "$lib/components/ui/scroll-area";
|
|
import CopyToClipboard from "$lib/components/CopyToClipboard.svelte"
|
|
import OCRTable from './OCRTable.svelte';
|
|
import { marked } from 'marked';
|
|
|
|
/**
|
|
* @type {string}
|
|
*/
|
|
export let id;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
export let library_id;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
export let created_at;
|
|
/**
|
|
* @type {number}
|
|
*/
|
|
export let folder_id;
|
|
/**
|
|
* @type {any}
|
|
*/
|
|
export let image;
|
|
/**
|
|
* @type {string}
|
|
*/
|
|
export let video;
|
|
/**
|
|
* @type {string}
|
|
*/
|
|
export let filepath;
|
|
/**
|
|
* @type {string}
|
|
*/
|
|
export let title;
|
|
/**
|
|
* @type {Array<string>}
|
|
*/
|
|
export let tags = [];
|
|
|
|
/**
|
|
* @type {Array<{key: string, source: string, value: any}>}
|
|
*/
|
|
export let metadata_entries = [];
|
|
/**
|
|
* @type {any}
|
|
*/
|
|
export let onClose;
|
|
/**
|
|
* @type {any}
|
|
*/
|
|
export let onNext;
|
|
/**
|
|
* @type {any}
|
|
*/
|
|
export let onPrevious;
|
|
|
|
/**
|
|
* @param {any} data
|
|
* @returns {boolean}
|
|
*/
|
|
function isValidOCRDataStructure(data) {
|
|
if (!Array.isArray(data)) return false;
|
|
|
|
for (const item of data) {
|
|
if (
|
|
!item.hasOwnProperty('dt_boxes') ||
|
|
!item.hasOwnProperty('rec_txt') ||
|
|
!item.hasOwnProperty('score')
|
|
) {
|
|
return false;
|
|
}
|
|
|
|
if (
|
|
!Array.isArray(item.dt_boxes) ||
|
|
typeof item.rec_txt !== 'string' ||
|
|
typeof item.score !== 'number'
|
|
) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
</script>
|
|
|
|
<div class="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full" id="my-modal">
|
|
<div
|
|
class="relative top-10 mx-auto p-10 border w-11/12 max-w-10xl shadow-lg rounded-md bg-white group h-5/6"
|
|
>
|
|
<!-- Button container -->
|
|
<div class="group">
|
|
<button
|
|
class="absolute left-5 top-1/2 transform -translate-y-1/2 text-white bg-gray-300 hover:bg-gray-400 font-bold rounded-full text-2xl w-12 h-12 opacity-0 group-hover:opacity-100"
|
|
on:click={onPrevious}
|
|
>
|
|
<
|
|
</button>
|
|
<button
|
|
class="absolute right-5 top-1/2 transform -translate-y-1/2 text-white bg-gray-300 hover:bg-gray-400 font-bold rounded-full text-2xl w-12 h-12 opacity-0 group-hover:opacity-100"
|
|
on:click={onNext}
|
|
>
|
|
>
|
|
</button>
|
|
<!-- Your modal content goes here -->
|
|
</div>
|
|
<div class="flex flex-col md:flex-row h-full">
|
|
<!-- Image container -->
|
|
<div class="flex-none w-full md:w-1/2 h-full">
|
|
<a href={video} target="_blank" rel="noopener noreferrer">
|
|
<img class="w-full h-full object-contain" src={image} alt={title} />
|
|
</a>
|
|
</div>
|
|
<!-- Description container -->
|
|
<ScrollArea class="mt-4 md:mt-0 md:ml-6 overflow-y-auto max-h-full">
|
|
<div class="mb-2 mr-2 pb-2 border-b border-gray-300">
|
|
<span class="uppercase tracking-wide text-sm text-indigo-600 font-bold">ID</span>
|
|
<span class="mt-1 text-sm leading-tight font-medium text-gray-500 font-mono">
|
|
{id}
|
|
</span>
|
|
<span class="uppercase tracking-wide text-sm text-indigo-600 font-bold ml-4"
|
|
>Library ID</span
|
|
>
|
|
<span class="mt-1 text-sm leading-tight font-medium text-gray-500 font-mono">
|
|
{library_id}
|
|
</span>
|
|
<span class="uppercase tracking-wide text-sm text-indigo-600 font-bold ml-4"
|
|
>Folder ID</span
|
|
>
|
|
<span class="mt-1 text-sm leading-tight font-medium text-gray-500 font-mono">
|
|
{folder_id}
|
|
</span>
|
|
<span class="uppercase tracking-wide text-sm text-indigo-600 font-bold ml-4"
|
|
>DATETIME</span
|
|
>
|
|
<span class="mt-1 text-xs leading-tight font-xs text-gray-500 font-mono">
|
|
{new Date(created_at * 1000).toLocaleString()}
|
|
</span>
|
|
<div>
|
|
<span class="mt-1 text-xs leading-tight font-xs text-gray-500 font-mono">
|
|
{filepath}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="uppercase tracking-wide text-sm text-indigo-600 font-bold">Image Title</div>
|
|
<p class="block mt-1 text-lg leading-tight font-medium text-black hover:underline">
|
|
{title}
|
|
</p>
|
|
<div class="uppercase tracking-wide text-sm text-indigo-600 font-bold">TAGS</div>
|
|
<div class="mt-2 text-gray-600">
|
|
{#each tags as tag}
|
|
<span class="text-base text-gray-500 inline-block">{tag}</span>
|
|
{/each}
|
|
</div>
|
|
<div class="uppercase tracking-wide text-sm text-indigo-600 font-bold">METADATA</div>
|
|
<div class="mt-2 text-gray-600">
|
|
{#each metadata_entries as entry}
|
|
<div class="mb-2">
|
|
<span class="font-bold flex items-center">
|
|
{entry.key}
|
|
<CopyToClipboard text={entry.value} />
|
|
</span>
|
|
{#if typeof entry.value === 'object'}
|
|
{#if isValidOCRDataStructure(entry.value)}
|
|
<OCRTable ocrData={entry.value} />
|
|
{:else}
|
|
<pre class="bg-gray-100 p-2 rounded overflow-y-auto max-h-96">{JSON.stringify(
|
|
entry.value,
|
|
null,
|
|
2
|
|
)}</pre>
|
|
{/if}
|
|
{:else}
|
|
<!-- Render markdown content -->
|
|
<div class="prose">
|
|
{@html marked(entry.value)}
|
|
</div>
|
|
{/if}
|
|
<span class="text-sm text-gray-500">({entry.source})</span>
|
|
</div>
|
|
{/each}
|
|
</div>
|
|
</ScrollArea>
|
|
</div>
|
|
<div class="absolute top-0 right-0 pt-4 pr-4">
|
|
<button class="text-gray-400 hover:text-gray-600" on:click={onClose}>
|
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
|
<span class="text-2xl">×</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|