feat: 수동 편집 URL — 정보 패널에서 Synology Drive 링크 입력/관리
- edit_url 컬럼 추가 (migration 006) - PreviewPanel: 편집 링크 입력/수정/표시 UI - DocumentViewer: edit_url 있으면 편집 버튼에서 해당 URL로 새 탭 - API: DocumentResponse/DocumentUpdate에 edit_url 필드 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -37,6 +37,7 @@ class DocumentResponse(BaseModel):
|
|||||||
ai_tags: list | None
|
ai_tags: list | None
|
||||||
ai_summary: str | None
|
ai_summary: str | None
|
||||||
user_note: str | None
|
user_note: str | None
|
||||||
|
edit_url: str | None
|
||||||
preview_status: str | None
|
preview_status: str | None
|
||||||
source_channel: str | None
|
source_channel: str | None
|
||||||
data_origin: str | None
|
data_origin: str | None
|
||||||
@@ -63,6 +64,7 @@ class DocumentUpdate(BaseModel):
|
|||||||
ai_sub_group: str | None = None
|
ai_sub_group: str | None = None
|
||||||
ai_tags: list | None = None
|
ai_tags: list | None = None
|
||||||
user_note: str | None = None
|
user_note: str | None = None
|
||||||
|
edit_url: str | None = None
|
||||||
source_channel: str | None = None
|
source_channel: str | None = None
|
||||||
data_origin: str | None = None
|
data_origin: str | None = None
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ class Document(Base):
|
|||||||
# 사용자 메모
|
# 사용자 메모
|
||||||
user_note: Mapped[str | None] = mapped_column(Text)
|
user_note: Mapped[str | None] = mapped_column(Text)
|
||||||
|
|
||||||
|
# 외부 편집 URL
|
||||||
|
edit_url: Mapped[str | None] = mapped_column(Text)
|
||||||
|
|
||||||
# 미리보기
|
# 미리보기
|
||||||
preview_status: Mapped[str | None] = mapped_column(String(20), default="none")
|
preview_status: Mapped[str | None] = mapped_column(String(20), default="none")
|
||||||
preview_hash: Mapped[str | None] = mapped_column(String(64))
|
preview_hash: Mapped[str | None] = mapped_column(String(64))
|
||||||
|
|||||||
@@ -26,12 +26,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getEditUrl(doc) {
|
function getEditUrl(doc) {
|
||||||
if (['odoc', 'osheet', 'docx', 'xlsx', 'pptx', 'odt', 'ods', 'odp'].includes(doc.file_format)) {
|
// DB에 저장된 편집 URL 우선
|
||||||
return `https://link.hyungi.net`;
|
if (doc.edit_url) return doc.edit_url;
|
||||||
}
|
// CAD는 AutoCAD Web
|
||||||
if (['dwg', 'dxf'].includes(doc.file_format)) {
|
if (['dwg', 'dxf'].includes(doc.file_format)) return 'https://web.autocad.com';
|
||||||
return 'https://web.autocad.com';
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,12 +16,18 @@
|
|||||||
let newTag = $state('');
|
let newTag = $state('');
|
||||||
let tagEditing = $state(false);
|
let tagEditing = $state(false);
|
||||||
|
|
||||||
// doc 변경 시 메모 초기화
|
// 편집 URL
|
||||||
|
let editUrlText = $state('');
|
||||||
|
let editUrlEditing = $state(false);
|
||||||
|
|
||||||
|
// doc 변경 시 초기화
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
if (doc) {
|
if (doc) {
|
||||||
noteText = doc.user_note || '';
|
noteText = doc.user_note || '';
|
||||||
|
editUrlText = doc.edit_url || '';
|
||||||
noteEditing = false;
|
noteEditing = false;
|
||||||
tagEditing = false;
|
tagEditing = false;
|
||||||
|
editUrlEditing = false;
|
||||||
newTag = '';
|
newTag = '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -43,6 +49,20 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function saveEditUrl() {
|
||||||
|
try {
|
||||||
|
await api(`/documents/${doc.id}`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
body: JSON.stringify({ edit_url: editUrlText.trim() || null }),
|
||||||
|
});
|
||||||
|
doc.edit_url = editUrlText.trim() || null;
|
||||||
|
editUrlEditing = false;
|
||||||
|
addToast('success', '편집 URL 저장됨');
|
||||||
|
} catch (err) {
|
||||||
|
addToast('error', '편집 URL 저장 실패');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function addTag() {
|
async function addTag() {
|
||||||
const tag = newTag.trim();
|
const tag = newTag.trim();
|
||||||
if (!tag) return;
|
if (!tag) return;
|
||||||
@@ -138,6 +158,32 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 편집 URL -->
|
||||||
|
<div>
|
||||||
|
<h4 class="text-xs font-semibold text-[var(--text-dim)] uppercase mb-1.5">편집 링크</h4>
|
||||||
|
{#if editUrlEditing}
|
||||||
|
<div class="flex gap-1">
|
||||||
|
<input
|
||||||
|
bind:value={editUrlText}
|
||||||
|
placeholder="Synology Drive URL 붙여넣기..."
|
||||||
|
class="flex-1 px-2 py-1 bg-[var(--bg)] border border-[var(--border)] rounded text-xs text-[var(--text)] outline-none focus:border-[var(--accent)]"
|
||||||
|
/>
|
||||||
|
<button onclick={saveEditUrl} class="px-2 py-1 text-xs bg-[var(--accent)] text-white rounded">저장</button>
|
||||||
|
<button onclick={() => { editUrlEditing = false; editUrlText = doc.edit_url || ''; }} class="px-2 py-1 text-xs text-[var(--text-dim)]">취소</button>
|
||||||
|
</div>
|
||||||
|
{:else if doc.edit_url}
|
||||||
|
<div class="flex items-center gap-1">
|
||||||
|
<a href={doc.edit_url} target="_blank" class="text-xs text-[var(--accent)] truncate hover:underline">{doc.edit_url}</a>
|
||||||
|
<button onclick={() => editUrlEditing = true} class="text-[10px] text-[var(--text-dim)] hover:text-[var(--text)]">수정</button>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<button
|
||||||
|
onclick={() => editUrlEditing = true}
|
||||||
|
class="text-xs text-[var(--text-dim)] hover:text-[var(--accent)]"
|
||||||
|
>+ URL 추가</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- 태그 -->
|
<!-- 태그 -->
|
||||||
<div>
|
<div>
|
||||||
<h4 class="text-xs font-semibold text-[var(--text-dim)] uppercase mb-1.5">태그</h4>
|
<h4 class="text-xs font-semibold text-[var(--text-dim)] uppercase mb-1.5">태그</h4>
|
||||||
|
|||||||
2
migrations/006_edit_url.sql
Normal file
2
migrations/006_edit_url.sql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
-- 외부 편집 URL (Synology Drive 공유 링크 등)
|
||||||
|
ALTER TABLE documents ADD COLUMN IF NOT EXISTS edit_url TEXT;
|
||||||
Reference in New Issue
Block a user