설정 Import Export 영역 접기 정리 v1.5.26

This commit is contained in:
2026-06-02 10:08:34 +09:00
parent 212bd3f34f
commit 5732a27498
9 changed files with 157 additions and 50 deletions

View File

@@ -31,6 +31,7 @@ const postExportDateFrom = ref('')
const postExportDateTo = ref('')
const postExportChunkSize = ref(500)
const postExportMaxFileSizeMb = ref(500)
const postImportExportPanel = ref('')
const errorMessage = ref('')
const toast = ref(null)
const logoInputRef = ref(null)
@@ -254,6 +255,15 @@ const postExportRequestTitle = computed(() => {
return '게시물 Export 작업을 요청합니다.'
})
/**
* Import/Export 상세 패널을 전환한다.
* @param {'import'|'export'} panelName - 열 패널 이름
* @returns {void}
*/
const togglePostImportExportPanel = (panelName) => {
postImportExportPanel.value = postImportExportPanel.value === panelName ? '' : panelName
}
/**
* Export 요청 범위 입력을 만든다.
* @returns {Object} Export 범위 입력
@@ -1299,19 +1309,22 @@ onBeforeUnmount(() => {
</template>
</nav>
<label class="admin-settings-screen__nav-jump mt-4 lg:hidden">
<label class="admin-settings-screen__nav-jump mt-4 grid gap-1 lg:hidden">
<span class="mb-1 block text-xs font-medium text-[#657080]">구역 이동</span>
<select
class="w-full rounded-md border border-[#dce0e5] bg-white px-2 py-2 text-sm"
:value="activeSectionId"
@change="onMobileNavChange"
>
<optgroup v-for="group in settingsNavGroups" :key="group.heading" :label="group.heading">
<option v-for="item in group.items" :key="item.id" :value="item.id">
{{ item.label }}
</option>
</optgroup>
</select>
<span class="relative">
<select
class="w-full appearance-none rounded-md border border-[#dce0e5] bg-white px-2 py-2 pr-10 text-sm"
:value="activeSectionId"
@change="onMobileNavChange"
>
<optgroup v-for="group in settingsNavGroups" :key="group.heading" :label="group.heading">
<option v-for="item in group.items" :key="item.id" :value="item.id">
{{ item.label }}
</option>
</optgroup>
</select>
<svg class="pointer-events-none absolute right-3 top-1/2 size-4 -translate-y-1/2 text-[#394047]" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6" /></svg>
</span>
</label>
</div>
</aside>
@@ -2033,7 +2046,57 @@ onBeforeUnmount(() => {
</p>
</div>
<div class="admin-settings-screen__export-actions mt-5 grid gap-4 rounded-lg border border-[#e6e8eb] bg-[#fbfcfd] p-4">
<div class="admin-settings-screen__import-export-actions mt-5 grid gap-3 md:grid-cols-2">
<button
class="admin-settings-screen__import-export-action flex min-h-20 cursor-pointer items-center justify-between gap-4 rounded-lg border border-[#e6e8eb] bg-[#fbfcfd] p-4 text-left transition hover:border-[#c5cbd3] hover:bg-white"
type="button"
:aria-expanded="postImportExportPanel === 'export'"
aria-controls="admin-settings-export-panel"
@click="togglePostImportExportPanel('export')"
>
<span class="min-w-0">
<span class="block text-sm font-semibold text-[#15171a]">Export 요청</span>
<span class="mt-1 block text-sm leading-relaxed text-[#657080]">
기간과 분할 기준을 정해 백업을 만듭니다.
</span>
</span>
<span
class="grid size-8 shrink-0 place-items-center rounded-full border border-[#dce0e5] text-[#394047] transition"
:class="postImportExportPanel === 'export' ? 'rotate-180 bg-white' : 'bg-[#f4f6f8]'"
aria-hidden="true"
>
<svg xmlns="http://www.w3.org/2000/svg" class="size-4" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</span>
</button>
<button
class="admin-settings-screen__import-export-action flex min-h-20 cursor-pointer items-center justify-between gap-4 rounded-lg border border-[#e6e8eb] bg-[#fbfcfd] p-4 text-left transition hover:border-[#c5cbd3] hover:bg-white"
type="button"
:aria-expanded="postImportExportPanel === 'import'"
aria-controls="admin-settings-import-panel"
@click="togglePostImportExportPanel('import')"
>
<span class="min-w-0">
<span class="block text-sm font-semibold text-[#15171a]">Import 하기</span>
<span class="mt-1 block text-sm leading-relaxed text-[#657080]">
백업 ZIP 가져오기 영역을 엽니다.
</span>
</span>
<span
class="grid size-8 shrink-0 place-items-center rounded-full border border-[#dce0e5] text-[#394047] transition"
:class="postImportExportPanel === 'import' ? 'rotate-180 bg-white' : 'bg-[#f4f6f8]'"
aria-hidden="true"
>
<svg xmlns="http://www.w3.org/2000/svg" class="size-4" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6" /></svg>
</span>
</button>
</div>
<div
v-if="postImportExportPanel === 'export'"
id="admin-settings-export-panel"
class="admin-settings-screen__export-actions mt-4 grid gap-4 rounded-lg border border-[#e6e8eb] bg-[#fbfcfd] p-4"
>
<div class="min-w-0">
<p class="text-sm font-semibold text-[#15171a]">
Obsidian 호환 백업 준비
@@ -2046,51 +2109,60 @@ onBeforeUnmount(() => {
<div class="admin-settings-screen__export-range grid gap-2 md:grid-cols-4">
<label class="grid gap-1 text-xs font-semibold text-[#5d6673]">
범위
<select
v-model="postExportDateRangeMode"
class="h-10 rounded-md border border-[#dce0e5] bg-white px-3 text-sm font-semibold text-[#15171a] outline-none focus:border-[#15171a] focus:ring-1 focus:ring-[#15171a]"
>
<option value="all">전체</option>
<option value="year">특정년</option>
<option value="month">특정</option>
<option value="custom">직접 지정</option>
</select>
<span class="relative">
<select
v-model="postExportDateRangeMode"
class="h-10 w-full appearance-none rounded-md border border-[#dce0e5] bg-white px-3 pr-10 text-sm font-semibold text-[#15171a] outline-none focus:border-[#15171a] focus:ring-1 focus:ring-[#15171a]"
>
<option value="all">전체</option>
<option value="year">특정</option>
<option value="month">특정월</option>
<option value="custom">직접 지정</option>
</select>
<svg class="pointer-events-none absolute right-3 top-1/2 size-4 -translate-y-1/2 text-[#394047]" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6" /></svg>
</span>
</label>
<label
v-if="postExportDateRangeMode === 'year' || postExportDateRangeMode === 'month'"
class="grid gap-1 text-xs font-semibold text-[#5d6673]"
>
연도
<select
v-model.number="postExportYear"
class="h-10 rounded-md border border-[#dce0e5] bg-white px-3 text-sm font-semibold text-[#15171a] outline-none focus:border-[#15171a] focus:ring-1 focus:ring-[#15171a]"
>
<option
v-for="year in postExportYearOptions"
:key="year"
:value="year"
<span class="relative">
<select
v-model.number="postExportYear"
class="h-10 w-full appearance-none rounded-md border border-[#dce0e5] bg-white px-3 pr-10 text-sm font-semibold text-[#15171a] outline-none focus:border-[#15171a] focus:ring-1 focus:ring-[#15171a]"
>
{{ year }}
</option>
</select>
<option
v-for="year in postExportYearOptions"
:key="year"
:value="year"
>
{{ year }}
</option>
</select>
<svg class="pointer-events-none absolute right-3 top-1/2 size-4 -translate-y-1/2 text-[#394047]" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6" /></svg>
</span>
</label>
<label
v-if="postExportDateRangeMode === 'month'"
class="grid gap-1 text-xs font-semibold text-[#5d6673]"
>
<select
v-model.number="postExportMonth"
class="h-10 rounded-md border border-[#dce0e5] bg-white px-3 text-sm font-semibold text-[#15171a] outline-none focus:border-[#15171a] focus:ring-1 focus:ring-[#15171a]"
>
<option
v-for="month in postExportMonthOptions"
:key="month"
:value="month"
<span class="relative">
<select
v-model.number="postExportMonth"
class="h-10 w-full appearance-none rounded-md border border-[#dce0e5] bg-white px-3 pr-10 text-sm font-semibold text-[#15171a] outline-none focus:border-[#15171a] focus:ring-1 focus:ring-[#15171a]"
>
{{ month }}
</option>
</select>
<option
v-for="month in postExportMonthOptions"
:key="month"
:value="month"
>
{{ month }}
</option>
</select>
<svg class="pointer-events-none absolute right-3 top-1/2 size-4 -translate-y-1/2 text-[#394047]" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 9 6 6 6-6" /></svg>
</span>
</label>
<label
v-if="postExportDateRangeMode === 'custom'"
@@ -2153,6 +2225,24 @@ onBeforeUnmount(() => {
</div>
</div>
<div
v-if="postImportExportPanel === 'import'"
id="admin-settings-import-panel"
class="admin-settings-screen__import-actions mt-4 grid gap-4 rounded-lg border border-dashed border-[#dce0e5] bg-[#fbfcfd] p-4"
>
<div class="min-w-0">
<p class="text-sm font-semibold text-[#15171a]">
백업 ZIP 가져오기
</p>
<p class="mt-1 text-sm leading-relaxed text-[#657080]">
Export ZIP 구조를 다시 게시물로 가져오는 기능은 다음 단계에서 연결합니다.
</p>
</div>
<div class="rounded-md border border-[#e6e8eb] bg-white px-4 py-5 text-sm text-[#657080]">
Import 구현 전까지는 영역만 접힌 상태로 보관합니다.
</div>
</div>
<div class="admin-settings-screen__export-list mt-5">
<div class="mb-3 flex items-center justify-between gap-3">
<h3 class="text-sm font-semibold text-[#15171a]">