feat(konten): muat versi server & buang draft (poin 1)
Simpan source draft/file, tambah discardAndReload(), badge Draft aktif, dan tombol muat dari server.
This commit is contained in:
parent
72d30351e5
commit
6971d0a3c3
|
|
@ -1,11 +1,13 @@
|
|||
import { tick } from 'svelte';
|
||||
import { getDraft, saveDraft, publishDraft, type DraftResponse } from './contentEditor';
|
||||
import { getDraft, saveDraft, publishDraft, discardDraft, type DraftResponse } from './contentEditor';
|
||||
import { renderMarkdownPreview } from './markdown';
|
||||
|
||||
export class ContentEditorManager {
|
||||
activePath = $state<string | null>(null);
|
||||
body = $state('');
|
||||
draftId = $state<string | null>(null);
|
||||
/** Asal konten yang sedang dimuat: draft server atau file published. */
|
||||
source = $state<'draft' | 'file'>('file');
|
||||
baseMtime = $state<number | null>(null);
|
||||
dirty = $state(false);
|
||||
loading = $state(false);
|
||||
|
|
@ -60,6 +62,7 @@ export class ContentEditorManager {
|
|||
if (res.success) {
|
||||
this.body = res.body ?? '';
|
||||
this.draftId = res.draft_id;
|
||||
this.source = res.source === 'draft' ? 'draft' : 'file';
|
||||
this.baseMtime = res.base_mtime ?? null;
|
||||
this.dirty = false;
|
||||
// Trigger preview
|
||||
|
|
@ -118,6 +121,37 @@ export class ContentEditorManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Buang draft server lalu muat ulang file published terbaru.
|
||||
* Hanya relevan saat `source === 'draft'`.
|
||||
*/
|
||||
async discardAndReload() {
|
||||
if (!this.activePath || this.loading) return;
|
||||
if (this.dirty && !window.confirm('Perubahan yang belum disimpan akan hilang. Muat versi server terbaru?')) {
|
||||
return;
|
||||
}
|
||||
const draftId = this.draftId;
|
||||
if (!draftId) {
|
||||
await this.loadDraft(this.activePath);
|
||||
return;
|
||||
}
|
||||
this.loading = true;
|
||||
try {
|
||||
const res = await discardDraft(draftId);
|
||||
if (!res.success) {
|
||||
this.showMessage('error', res.message || 'Gagal membuang draft');
|
||||
return;
|
||||
}
|
||||
await this.loadDraft(this.activePath);
|
||||
this.showMessage('success', 'Draft dibuang — menampilkan versi server');
|
||||
} catch (err) {
|
||||
console.error('[contentEditor] discardAndReload error:', err);
|
||||
this.showMessage('error', 'Gagal terhubung ke server');
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
async handleSave() {
|
||||
if (!this.activePath || this.saving) return;
|
||||
this.saving = true;
|
||||
|
|
@ -125,6 +159,7 @@ export class ContentEditorManager {
|
|||
const res = await saveDraft(this.activePath, this.body, this.baseMtime);
|
||||
if (res.success) {
|
||||
this.draftId = res.draft_id;
|
||||
this.source = 'draft';
|
||||
this.dirty = false;
|
||||
this.showMessage('success', 'Draft tersimpan');
|
||||
} else {
|
||||
|
|
@ -149,6 +184,7 @@ export class ContentEditorManager {
|
|||
return;
|
||||
}
|
||||
this.draftId = saveRes.draft_id;
|
||||
this.source = 'draft';
|
||||
this.dirty = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -223,6 +223,7 @@
|
|||
mgr.activePath = path;
|
||||
mgr.body = '';
|
||||
mgr.draftId = null;
|
||||
mgr.source = 'file';
|
||||
mgr.dirty = false;
|
||||
// Clear preview since assets don't have markdown
|
||||
mgr.previewHtml = '';
|
||||
|
|
@ -768,6 +769,7 @@
|
|||
mgr.activePath = null;
|
||||
mgr.body = '';
|
||||
mgr.draftId = null;
|
||||
mgr.source = 'file';
|
||||
mgr.previewSlides = [];
|
||||
mgr.previewActiveTabs = [];
|
||||
}
|
||||
|
|
@ -780,6 +782,7 @@
|
|||
mgr.activePath = null;
|
||||
mgr.body = '';
|
||||
mgr.draftId = null;
|
||||
mgr.source = 'file';
|
||||
}
|
||||
} else {
|
||||
alert(forceRes.message || 'Gagal menghapus');
|
||||
|
|
@ -1038,6 +1041,18 @@
|
|||
<!-- Save / Publish actions (shared across all header modes) -->
|
||||
{#snippet saveActions()}
|
||||
{#if mgr.activePath && !isAssetFile}
|
||||
{#if mgr.source === 'draft'}
|
||||
<span class="draft-badge" title="File ini sedang memakai draft tersimpan di server">Draft aktif</span>
|
||||
<button
|
||||
class="panel-btn discard-btn"
|
||||
use:preserveFocus
|
||||
onclick={() => mgr.discardAndReload()}
|
||||
disabled={mgr.loading || mgr.saving || mgr.publishing}
|
||||
title="Muat dari server (buang draft)"
|
||||
>
|
||||
{mgr.loading ? '⏳' : '↩️'}
|
||||
</button>
|
||||
{/if}
|
||||
<button
|
||||
class="panel-btn edit-btn"
|
||||
use:preserveFocus
|
||||
|
|
@ -1469,6 +1484,17 @@
|
|||
.panel-btn:disabled { opacity: 0.45; cursor: not-allowed; }
|
||||
.panel-btn.save-btn { color: var(--color-text-muted); }
|
||||
.panel-btn.publish-btn { color: var(--color-primary, #339af0); font-weight: 600; }
|
||||
.draft-badge {
|
||||
align-self: center;
|
||||
font-size: 0.68rem;
|
||||
font-weight: 600;
|
||||
padding: 0.12rem 0.4rem;
|
||||
border-radius: 999px;
|
||||
background: rgba(245, 159, 0, 0.14);
|
||||
border: 1px solid rgba(245, 159, 0, 0.45);
|
||||
color: #b35c00;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.ie-progress {
|
||||
font-size: 0.75rem;
|
||||
color: var(--color-text-muted);
|
||||
|
|
|
|||
Loading…
Reference in New Issue