내보내기 작업 목록 카드 분리
This commit is contained in:
@@ -564,30 +564,6 @@ const getPostExportStatusClass = (status) => ({
|
||||
expired: 'bg-[#f1f3f5] text-[#657080] ring-[#dce0e5]'
|
||||
}[status] || 'bg-[#f1f3f5] text-[#657080] ring-[#dce0e5]')
|
||||
|
||||
/**
|
||||
* 바이트 값을 읽기 쉬운 용량으로 변환한다.
|
||||
* @param {number} value - 바이트 값
|
||||
* @returns {string} 용량 라벨
|
||||
*/
|
||||
const formatExportFileSize = (value) => {
|
||||
const bytes = Number(value || 0)
|
||||
|
||||
if (!bytes) {
|
||||
return '생성 대기'
|
||||
}
|
||||
|
||||
const units = ['B', 'KB', 'MB', 'GB']
|
||||
let size = bytes
|
||||
let unitIndex = 0
|
||||
|
||||
while (size >= 1024 && unitIndex < units.length - 1) {
|
||||
size /= 1024
|
||||
unitIndex += 1
|
||||
}
|
||||
|
||||
return `${size.toFixed(size >= 10 || unitIndex === 0 ? 0 : 1)} ${units[unitIndex]}`
|
||||
}
|
||||
|
||||
/**
|
||||
* export 작업 진행률을 계산한다.
|
||||
* @param {Object} job - export 작업
|
||||
@@ -3464,143 +3440,30 @@ onBeforeUnmount(() => {
|
||||
@request="requestPostExport"
|
||||
/>
|
||||
|
||||
<section
|
||||
v-if="normalizedPostExportJobs.length > 0"
|
||||
id="admin-settings-section-export-results"
|
||||
class="admin-settings-screen__card admin-settings-screen__card--export-results rounded-xl border border-[#e6e8eb] bg-white p-6 shadow-[0_1px_2px_rgba(15,23,42,0.04)]"
|
||||
>
|
||||
<div class="admin-settings-screen__export-list">
|
||||
<div class="mb-3 flex items-center justify-between gap-3">
|
||||
<h3 class="text-sm font-semibold text-[#15171a]">
|
||||
최근 내보내기 작업
|
||||
</h3>
|
||||
<button
|
||||
class="inline-flex h-8 cursor-pointer items-center justify-center rounded px-3 text-xs font-semibold text-[#5d6673] transition hover:bg-[#eceff2] hover:text-[#15171a]"
|
||||
type="button"
|
||||
@click="refreshPostExportJobs"
|
||||
>
|
||||
새로고침
|
||||
</button>
|
||||
</div>
|
||||
<div class="admin-settings-screen__export-items grid gap-3">
|
||||
<article
|
||||
v-for="job in normalizedPostExportJobs"
|
||||
:key="job.id"
|
||||
class="admin-settings-screen__export-item rounded-lg border border-[#e6e8eb] bg-white p-4"
|
||||
>
|
||||
<div class="flex flex-col gap-3 md:flex-row md:items-start md:justify-between">
|
||||
<div class="min-w-0">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<span
|
||||
v-if="job.status !== 'ready'"
|
||||
class="inline-flex rounded-full px-2 py-1 text-xs font-semibold ring-1 ring-inset"
|
||||
:class="getPostExportStatusClass(job.status)"
|
||||
>
|
||||
{{ getPostExportStatusLabel(job.status) }}
|
||||
</span>
|
||||
<span class="text-sm font-semibold text-[#15171a]">
|
||||
게시물 {{ job.postCount }}개
|
||||
</span>
|
||||
<span class="text-sm text-[#9aa3ad]">
|
||||
{{ job.files.length }}개 파일
|
||||
</span>
|
||||
<span class="text-sm text-[#657080]">
|
||||
{{ job.rangeLabel || '전체' }}
|
||||
</span>
|
||||
</div>
|
||||
<p class="mt-2 text-xs text-[#657080]">
|
||||
만료: {{ formatPostDateTime(job.expiresAt) }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex shrink-0 items-center gap-2">
|
||||
<button
|
||||
v-if="job.status === 'failed'"
|
||||
class="inline-flex h-9 shrink-0 cursor-pointer items-center justify-center rounded-md border border-[#dce0e5] px-3 text-xs font-semibold text-[#15171a] transition hover:bg-[#f4f6f8] disabled:cursor-not-allowed disabled:text-[#a6b0bb]"
|
||||
type="button"
|
||||
:disabled="isRetryingPostExportJob(job.id)"
|
||||
@click="retryPostExportJob(job)"
|
||||
>
|
||||
{{ isRetryingPostExportJob(job.id) ? '재시도 중' : '재시도' }}
|
||||
</button>
|
||||
<button
|
||||
class="inline-flex h-9 shrink-0 cursor-pointer items-center justify-center rounded-md border border-[#ffd5d5] px-3 text-xs font-semibold text-[#d64545] transition hover:bg-[#fff3f3] disabled:cursor-not-allowed disabled:border-[#e1e5ea] disabled:text-[#a6b0bb]"
|
||||
type="button"
|
||||
:disabled="job.status === 'queued' || job.status === 'processing' || isDeletingPostExportJob(job.id)"
|
||||
@click="deletePostExportJob(job)"
|
||||
>
|
||||
{{ isDeletingPostExportJob(job.id) ? '삭제 중' : '삭제' }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="shouldShowPostExportProgress(job)"
|
||||
class="admin-settings-screen__export-progress mt-4 rounded-lg border border-[#edf0f3] bg-[#fbfcfd] p-3"
|
||||
>
|
||||
<div class="mb-2 flex items-center justify-between gap-3 text-xs">
|
||||
<span class="font-semibold text-[#15171a]">
|
||||
진행도 {{ getPostExportProgressLabel(job) }}
|
||||
</span>
|
||||
<span class="text-[#657080]">
|
||||
{{ getPostExportProgressPercent(job) }}%
|
||||
</span>
|
||||
</div>
|
||||
<div class="h-2 overflow-hidden rounded-full bg-[#e8edf2]">
|
||||
<div
|
||||
class="h-full rounded-full bg-[#15171a] transition-[width] duration-500"
|
||||
:style="{ width: `${getPostExportProgressPercent(job)}%` }"
|
||||
/>
|
||||
</div>
|
||||
<div class="mt-2 flex flex-col gap-1 text-xs text-[#657080] md:flex-row md:items-center md:justify-between">
|
||||
<span>{{ getPostExportProgressDescription(job) }}</span>
|
||||
<span>마지막 갱신: {{ formatPostDateTime(job.updatedAt) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<details
|
||||
v-if="job.status === 'failed' && job.errorDetail"
|
||||
class="admin-settings-screen__export-error mt-4 rounded-lg border border-[#ffd5d5] bg-[#fff7f7] p-3 text-xs text-[#8f2d2d]"
|
||||
>
|
||||
<summary class="cursor-pointer font-semibold">
|
||||
실패 원인 보기
|
||||
</summary>
|
||||
<pre class="mt-2 max-h-40 overflow-auto whitespace-pre-wrap break-words font-mono text-[11px] leading-relaxed">{{ job.errorDetail }}</pre>
|
||||
</details>
|
||||
|
||||
<div v-if="job.files.length > 0" class="admin-settings-screen__export-files mt-4 overflow-hidden rounded-md border border-[#edf0f3]">
|
||||
<div class="flex flex-col gap-3 border-b border-[#edf0f3] bg-[#fbfcfd] px-3 py-3 md:flex-row md:items-center md:justify-between">
|
||||
<label class="inline-flex cursor-pointer items-center gap-2 text-xs font-semibold text-[#394047] has-[:disabled]:cursor-not-allowed has-[:disabled]:text-[#a6b0bb]">
|
||||
<input
|
||||
class="size-4 rounded border-[#cfd6de] text-[#15171a] focus:ring-[#15171a] disabled:cursor-not-allowed"
|
||||
type="checkbox"
|
||||
:checked="areAllReadyPostExportFilesSelected(job)"
|
||||
:disabled="getReadyPostExportFiles(job).length === 0 || isDownloadingPostExportJob(job.id)"
|
||||
@change="toggleAllPostExportFiles(job)"
|
||||
/>
|
||||
전체 선택
|
||||
</label>
|
||||
<button
|
||||
class="inline-flex h-9 shrink-0 cursor-pointer items-center justify-center rounded-md border border-[#15171a] bg-[#15171a] px-3 text-xs font-semibold text-white transition hover:bg-black disabled:cursor-not-allowed disabled:border-[#dce0e5] disabled:bg-white disabled:text-[#9aa3ad]"
|
||||
type="button"
|
||||
:disabled="getSelectedReadyPostExportFiles(job).length === 0 || isDownloadingPostExportJob(job.id)"
|
||||
@click="downloadPostExportJobFiles(job)"
|
||||
>
|
||||
{{ isDownloadingPostExportJob(job.id) ? '다운로드 중' : `선택 파일 다운로드 ${getSelectedReadyPostExportFiles(job).length || ''}` }}
|
||||
</button>
|
||||
</div>
|
||||
<AdminPostExportFileRow
|
||||
v-for="file in job.files"
|
||||
:key="file.id"
|
||||
:file="file"
|
||||
:selected="isPostExportFileSelected(job, file)"
|
||||
:disabled="isPostExportFileSelectionDisabled(job, file)"
|
||||
@toggle="togglePostExportFileSelection(job, file)"
|
||||
/>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<AdminPostExportJobList
|
||||
:jobs="normalizedPostExportJobs"
|
||||
:format-date-time="formatPostDateTime"
|
||||
:get-status-label="getPostExportStatusLabel"
|
||||
:get-status-class="getPostExportStatusClass"
|
||||
:should-show-progress="shouldShowPostExportProgress"
|
||||
:get-progress-label="getPostExportProgressLabel"
|
||||
:get-progress-percent="getPostExportProgressPercent"
|
||||
:get-progress-description="getPostExportProgressDescription"
|
||||
:is-retrying="isRetryingPostExportJob"
|
||||
:is-deleting="isDeletingPostExportJob"
|
||||
:is-downloading="isDownloadingPostExportJob"
|
||||
:are-all-ready-files-selected="areAllReadyPostExportFilesSelected"
|
||||
:get-ready-files="getReadyPostExportFiles"
|
||||
:get-selected-ready-files="getSelectedReadyPostExportFiles"
|
||||
:is-file-selected="isPostExportFileSelected"
|
||||
:is-file-selection-disabled="isPostExportFileSelectionDisabled"
|
||||
@refresh="refreshPostExportJobs"
|
||||
@retry="retryPostExportJob"
|
||||
@delete="deletePostExportJob"
|
||||
@toggle-all-files="toggleAllPostExportFiles"
|
||||
@download-files="downloadPostExportJobFiles"
|
||||
@toggle-file="togglePostExportFileSelection"
|
||||
/>
|
||||
|
||||
<AdminPostImportCard
|
||||
:expanded="postImportExportPanel === 'import'"
|
||||
|
||||
Reference in New Issue
Block a user