미디어 선택 요청 흐름 분리
This commit is contained in:
@@ -5,7 +5,10 @@ import {
|
||||
buildMediaPickerPageItems,
|
||||
buildMediaPickerRangeLabel,
|
||||
buildMediaPickerUploadHint,
|
||||
createMediaPickerFetchQuery,
|
||||
createDefaultMediaPickerPagination,
|
||||
createMediaUploadFormData,
|
||||
findUploadSizeLimitError,
|
||||
getGallerySelectionOrder as getGallerySelectionOrderFromSelection,
|
||||
getMediaPickerAcceptForTarget,
|
||||
getMediaPickerKindForTarget,
|
||||
@@ -15,6 +18,7 @@ import {
|
||||
isUploadFileAllowedForMediaTarget,
|
||||
normalizeMediaPickerPage,
|
||||
normalizeMediaPickerResponse,
|
||||
resolveUploadedMediaFiles,
|
||||
resolveSelectedMediaItems,
|
||||
toggleMediaSelectionState
|
||||
} from '../lib/markdown-editor-media.js'
|
||||
@@ -26,11 +30,15 @@ export const ADMIN_MARKDOWN_MEDIA_PICKER_PAGE_SIZE = 50
|
||||
* 관리자 Markdown 에디터의 미디어 선택 모달 상태를 관리한다.
|
||||
* @param {Object} options - 상태 옵션
|
||||
* @param {import('vue').Ref<Object>|import('vue').ComputedRef<Object>} options.uploadSizeLimits - 업로드 한도
|
||||
* @param {import('vue').Ref<number>|import('vue').ComputedRef<number>} [options.uploadMaxFileCount] - 한 번에 업로드 가능한 파일 수
|
||||
* @param {import('vue').Ref<number>|import('vue').ComputedRef<number>} [options.uploadMaxTotalSize] - 한 번에 업로드 가능한 전체 용량
|
||||
* @param {number} [options.pageSize=50] - 페이지 크기
|
||||
* @returns {Object} 미디어 선택 모달 상태와 액션
|
||||
*/
|
||||
export const useAdminMarkdownMediaPicker = ({
|
||||
uploadSizeLimits,
|
||||
uploadMaxFileCount,
|
||||
uploadMaxTotalSize,
|
||||
pageSize = ADMIN_MARKDOWN_MEDIA_PICKER_PAGE_SIZE
|
||||
}) => {
|
||||
const mediaItems = ref([])
|
||||
@@ -143,6 +151,104 @@ export const useAdminMarkdownMediaPicker = ({
|
||||
mediaPickerPage.value = mediaPickerPagination.value.page || 1
|
||||
}
|
||||
|
||||
/**
|
||||
* 미디어 라이브러리 목록을 조회한다.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const fetchMediaItems = async () => {
|
||||
isLoadingMedia.value = true
|
||||
|
||||
try {
|
||||
const response = await $fetch('/admin/api/media', {
|
||||
query: createMediaPickerFetchQuery({
|
||||
page: mediaPickerPage.value,
|
||||
pageSize,
|
||||
kind: mediaPickerKind.value,
|
||||
searchQuery: mediaSearchQuery.value
|
||||
})
|
||||
})
|
||||
|
||||
applyMediaPickerResponse(response)
|
||||
} finally {
|
||||
isLoadingMedia.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 미디어 파일을 업로드한다.
|
||||
* @param {FileList|Array<File>} files - 업로드 파일 목록
|
||||
* @returns {Promise<Object[]>} 업로드된 파일 목록
|
||||
*/
|
||||
const uploadMediaFiles = async (files) => {
|
||||
const sizeLimitError = findUploadSizeLimitError({
|
||||
files,
|
||||
maxFileCount: unref(uploadMaxFileCount),
|
||||
maxTotalSize: unref(uploadMaxTotalSize),
|
||||
uploadSizeLimits: unref(uploadSizeLimits)
|
||||
})
|
||||
|
||||
if (sizeLimitError) {
|
||||
throw new Error(sizeLimitError)
|
||||
}
|
||||
|
||||
const result = await $fetch('/admin/api/uploads', {
|
||||
method: 'POST',
|
||||
body: createMediaUploadFormData(files)
|
||||
})
|
||||
|
||||
return resolveUploadedMediaFiles(result)
|
||||
}
|
||||
|
||||
/**
|
||||
* 업로드 상태를 관리하며 미디어 파일을 업로드한다.
|
||||
* @param {FileList|Array<File>} files - 업로드 파일 목록
|
||||
* @returns {Promise<Object[]>} 업로드된 파일 목록
|
||||
*/
|
||||
const uploadMediaFilesWithState = async (files) => {
|
||||
if (!files?.length || isUploading.value) {
|
||||
return []
|
||||
}
|
||||
|
||||
isUploading.value = true
|
||||
|
||||
try {
|
||||
return await uploadMediaFiles(files)
|
||||
} finally {
|
||||
isUploading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 현재 미디어 선택 모달에서 파일을 업로드하고 선택 상태를 갱신한다.
|
||||
* @param {FileList|Array<File>} files - 업로드 파일 목록
|
||||
* @returns {Promise<Object[]>} 업로드된 파일 목록
|
||||
*/
|
||||
const uploadFilesIntoMediaPicker = async (files) => {
|
||||
if (!files?.length || isUploading.value) {
|
||||
return []
|
||||
}
|
||||
|
||||
isUploading.value = true
|
||||
|
||||
try {
|
||||
const uploadedFiles = await uploadMediaFiles(files)
|
||||
selectUploadedMediaFiles(uploadedFiles)
|
||||
activeMediaPickerTab.value = 'library'
|
||||
mediaSearchQuery.value = ''
|
||||
mediaPickerPage.value = 1
|
||||
|
||||
try {
|
||||
await fetchMediaItems()
|
||||
} catch {
|
||||
prependUploadedMediaItems(uploadedFiles)
|
||||
}
|
||||
|
||||
return uploadedFiles
|
||||
} finally {
|
||||
isUploading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 미디어 선택 페이지를 변경한다.
|
||||
* @param {number} page - 이동할 페이지
|
||||
@@ -261,6 +367,10 @@ export const useAdminMarkdownMediaPicker = ({
|
||||
openMediaPickerState,
|
||||
closeMediaPickerState,
|
||||
applyMediaPickerResponse,
|
||||
fetchMediaItems,
|
||||
uploadMediaFiles,
|
||||
uploadMediaFilesWithState,
|
||||
uploadFilesIntoMediaPicker,
|
||||
setMediaPickerPage,
|
||||
toggleMediaSelection,
|
||||
resolveCurrentSelectedMediaItems,
|
||||
|
||||
Reference in New Issue
Block a user