릴리스: v1.3.13 템플릿 요청 스냅샷과 저장 분리
This commit is contained in:
@@ -44,6 +44,7 @@ const isTemplateRequestModalOpen = ref(false)
|
||||
const isTemplateUpdateModalOpen = ref(false)
|
||||
const templateRequestDraftTitle = ref('')
|
||||
const templateRequestDraftDescription = ref('')
|
||||
const templateRequestSaveToMyTierList = ref(true)
|
||||
const isDeleteModalOpen = ref(false)
|
||||
const isGroupDeleteModalOpen = ref(false)
|
||||
const pendingRemoveGroupId = ref('')
|
||||
@@ -119,14 +120,7 @@ const canRequestTemplateCreate = computed(
|
||||
const canRequestTemplateUpdate = computed(
|
||||
() => canEdit.value && !isNewTierList.value && gameId.value !== 'freeform' && customItems.value.length > 0
|
||||
)
|
||||
const templateRequestChecks = computed(() => [
|
||||
{
|
||||
id: 'title',
|
||||
label: '티어표 이름(게임 이름)을 직접 입력했는지',
|
||||
passed: !!(title.value || '').trim() && (title.value || '').trim() !== (gameName.value || '').trim(),
|
||||
},
|
||||
])
|
||||
const canSubmitTemplateCreateRequest = computed(() => templateRequestChecks.value.every((item) => item.passed) && !!templateRequestDraftTitle.value.trim() && !!templateRequestDraftDescription.value.trim())
|
||||
const canSubmitTemplateCreateRequest = computed(() => !!templateRequestDraftTitle.value.trim() && !!templateRequestDraftDescription.value.trim())
|
||||
const canSubmitTemplateUpdateRequest = computed(() => !!templateRequestDraftTitle.value.trim() && !!templateRequestDraftDescription.value.trim())
|
||||
const templateRequestTargetLabel = computed(() => (gameId.value === 'freeform' ? '새로운 템플릿' : (gameName.value || gameId.value || '선택한 게임')))
|
||||
|
||||
@@ -547,8 +541,9 @@ function closeSaveModal() {
|
||||
}
|
||||
|
||||
function resetTemplateRequestDrafts() {
|
||||
templateRequestDraftTitle.value = ''
|
||||
templateRequestDraftDescription.value = ''
|
||||
templateRequestDraftTitle.value = (title.value || '').trim()
|
||||
templateRequestDraftDescription.value = (description.value || '').trim()
|
||||
templateRequestSaveToMyTierList.value = true
|
||||
}
|
||||
|
||||
function openTemplateRequestModal() {
|
||||
@@ -624,27 +619,54 @@ async function toggleFavorite() {
|
||||
}
|
||||
|
||||
async function requestTemplate(type) {
|
||||
if (isNewTierList.value) {
|
||||
toast.error('요청 전에 먼저 티어표를 저장해주세요.')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
isRequestingTemplate.value = true
|
||||
const persisted = await persistTierList({ showModal: false })
|
||||
await api.requestTierListTemplate(persisted.savedTierListId, {
|
||||
await uploadPendingCustomItems()
|
||||
const uploadedThumbnailSrc = await uploadPendingThumbnail()
|
||||
const response = await api.requestTierListTemplate({
|
||||
type,
|
||||
sourceTierListId: tierListId.value !== 'new' ? tierListId.value : '',
|
||||
gameId: gameId.value,
|
||||
requestTitle: templateRequestDraftTitle.value.trim(),
|
||||
requestDescription: templateRequestDraftDescription.value.trim(),
|
||||
thumbnailSrc: uploadedThumbnailSrc || thumbnailSrc.value || '',
|
||||
isPublic: !!isPublic.value,
|
||||
showCharacterNames: !!showCharacterNames.value,
|
||||
saveToMyTierList: !!templateRequestSaveToMyTierList.value,
|
||||
groups: groups.value.map((group) => ({
|
||||
id: group.id,
|
||||
name: group.name,
|
||||
itemIds: [...group.itemIds],
|
||||
})),
|
||||
boardItems: Object.values(itemsById.value),
|
||||
})
|
||||
|
||||
const savedTierList = response?.savedTierList
|
||||
if (savedTierList) {
|
||||
title.value = savedTierList.title || title.value
|
||||
description.value = savedTierList.description || ''
|
||||
updatedAt.value = Number(savedTierList.updatedAt || Date.now())
|
||||
authorName.value = savedTierList.authorName || effectiveAuthorName.value
|
||||
authorAccountName.value = savedTierList.authorAccountName || authorAccountName.value
|
||||
favoriteCount.value = Number(savedTierList.favoriteCount || favoriteCount.value || 0)
|
||||
isFavorited.value = !!savedTierList.isFavorited
|
||||
if (tierListId.value === 'new' && savedTierList.id) {
|
||||
await router.replace(`/editor/${gameId.value}/${savedTierList.id}`)
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'create') closeTemplateRequestModal()
|
||||
if (type === 'update') closeTemplateUpdateModal()
|
||||
toast.success(type === 'create' ? '템플릿 등록 요청을 보냈어요.' : '템플릿 업데이트 요청을 보냈어요.')
|
||||
toast.success(
|
||||
type === 'create'
|
||||
? templateRequestSaveToMyTierList.value
|
||||
? '템플릿 등록 요청과 내 티어표 저장을 함께 완료했어요.'
|
||||
: '템플릿 등록 요청을 보냈어요.'
|
||||
: templateRequestSaveToMyTierList.value
|
||||
? '템플릿 업데이트 요청과 내 티어표 저장을 함께 완료했어요.'
|
||||
: '템플릿 업데이트 요청을 보냈어요.'
|
||||
)
|
||||
} catch (e) {
|
||||
if (e?.status === 400 && e?.data?.error === 'title_required') {
|
||||
toast.error('템플릿 등록 요청 전에는 티어표 이름을 직접 입력해주세요.')
|
||||
return
|
||||
}
|
||||
if (e?.status === 409) {
|
||||
toast.error('이미 처리 대기 중인 같은 요청이 있어요.')
|
||||
return
|
||||
@@ -773,18 +795,7 @@ onUnmounted(() => {
|
||||
<div class="modalCard" role="dialog" aria-modal="true" aria-labelledby="templateRequestTitle">
|
||||
<div id="templateRequestTitle" class="modalCard__title">템플릿 등록 요청</div>
|
||||
<div class="modalCard__desc">
|
||||
여러 사용자가 비슷한 주제로 요청할 수 있으니, 관리자에게 전달되기 전에 아래 조건을 먼저 확인해주세요.
|
||||
</div>
|
||||
<div class="requestChecklist">
|
||||
<div
|
||||
v-for="check in templateRequestChecks"
|
||||
:key="check.id"
|
||||
class="requestChecklist__item"
|
||||
:class="{ 'requestChecklist__item--passed': check.passed }"
|
||||
>
|
||||
<span class="requestChecklist__label">{{ check.label }}</span>
|
||||
<span class="requestChecklist__icon">{{ check.passed ? '완료' : '확인 필요' }}</span>
|
||||
</div>
|
||||
티어표에 적어둔 제목과 설명이 있다면 그대로 가져와 두었어요. 비어 있다면 여기서 바로 작성해도 괜찮아요.
|
||||
</div>
|
||||
<div class="requestChecklist__hint">
|
||||
제목과 설명을 함께 적어두면 관리자가 어떤 신규 템플릿인지 훨씬 빠르게 파악할 수 있어요.
|
||||
@@ -792,15 +803,23 @@ onUnmounted(() => {
|
||||
</div>
|
||||
<div class="templateRequestDraft">
|
||||
<label class="templateRequestDraft__field">
|
||||
<span class="templateRequestDraft__label">요청 제목</span>
|
||||
<input v-model="templateRequestDraftTitle" class="templateRequestDraft__input" maxlength="80" placeholder="예: 템플릿 등록 요청" />
|
||||
<span class="templateRequestDraft__hint">{{ templateRequestDraftTitle.length }}/80자</span>
|
||||
<span class="templateRequestDraft__label">티어표 제목</span>
|
||||
<input v-model="templateRequestDraftTitle" class="templateRequestDraft__input" maxlength="120" placeholder="예: 템플릿 등록 요청" />
|
||||
<span class="templateRequestDraft__hint">{{ templateRequestDraftTitle.length }}/120자</span>
|
||||
</label>
|
||||
<label class="templateRequestDraft__field">
|
||||
<span class="templateRequestDraft__label">요청 설명</span>
|
||||
<textarea v-model="templateRequestDraftDescription" class="templateRequestDraft__input templateRequestDraft__textarea" maxlength="240" placeholder="예: 여름 이벤트 한정 캐릭터 추가용으로 신규 템플릿이 필요합니다." />
|
||||
<span class="templateRequestDraft__hint">{{ templateRequestDraftDescription.length }}/240자</span>
|
||||
<span class="templateRequestDraft__label">티어표 설명</span>
|
||||
<textarea v-model="templateRequestDraftDescription" class="templateRequestDraft__input templateRequestDraft__textarea" maxlength="1000" placeholder="예: 여름 이벤트 한정 캐릭터 추가용으로 신규 템플릿이 필요합니다." />
|
||||
<span class="templateRequestDraft__hint">{{ templateRequestDraftDescription.length }}/1000자</span>
|
||||
</label>
|
||||
<label class="toggleSwitch">
|
||||
<input v-model="templateRequestSaveToMyTierList" type="checkbox" />
|
||||
<span class="toggleSwitch__label">내 티어 리스트에도 저장</span>
|
||||
<span class="toggleSwitch__track"><span class="toggleSwitch__thumb"></span></span>
|
||||
</label>
|
||||
<div class="templateRequestDraft__note">
|
||||
저장을 끄면 요청 시점 스냅샷만 관리자에게 전달되고, 내 티어 리스트에는 별도로 남기지 않아요.
|
||||
</div>
|
||||
</div>
|
||||
<div class="modalCard__actions">
|
||||
<button class="btn btn--ghost" @click="closeTemplateRequestModal">취소</button>
|
||||
@@ -815,7 +834,7 @@ onUnmounted(() => {
|
||||
<div class="modalCard" role="dialog" aria-modal="true" aria-labelledby="templateUpdateTitle">
|
||||
<div id="templateUpdateTitle" class="modalCard__title">템플릿 요청하기</div>
|
||||
<div class="modalCard__desc">
|
||||
{{ templateRequestTargetLabel }}에 직접 추가한 아이템을 포함해 달라고 관리자에게 요청을 보냅니다.
|
||||
{{ templateRequestTargetLabel }}에 직접 추가한 아이템을 포함해 달라고 관리자에게 요청합니다. 현재 티어표 제목과 설명은 그대로 가져와 두었어요.
|
||||
</div>
|
||||
<div class="modalCard__note">
|
||||
모두가 사용하는 기본 템플릿이니 개인적인 항목이 아닌 공통된 항목만 추가한 뒤 신청해주세요.
|
||||
@@ -823,15 +842,23 @@ onUnmounted(() => {
|
||||
</div>
|
||||
<div class="templateRequestDraft">
|
||||
<label class="templateRequestDraft__field">
|
||||
<span class="templateRequestDraft__label">요청 제목</span>
|
||||
<input v-model="templateRequestDraftTitle" class="templateRequestDraft__input" maxlength="80" placeholder="예: 템플릿 업데이트 요청" />
|
||||
<span class="templateRequestDraft__hint">{{ templateRequestDraftTitle.length }}/80자</span>
|
||||
<span class="templateRequestDraft__label">티어표 제목</span>
|
||||
<input v-model="templateRequestDraftTitle" class="templateRequestDraft__input" maxlength="120" placeholder="예: 템플릿 업데이트 요청" />
|
||||
<span class="templateRequestDraft__hint">{{ templateRequestDraftTitle.length }}/120자</span>
|
||||
</label>
|
||||
<label class="templateRequestDraft__field">
|
||||
<span class="templateRequestDraft__label">요청 설명</span>
|
||||
<textarea v-model="templateRequestDraftDescription" class="templateRequestDraft__input templateRequestDraft__textarea" maxlength="240" placeholder="예: 여름 이벤트 한정 캐릭터 추가" />
|
||||
<span class="templateRequestDraft__hint">{{ templateRequestDraftDescription.length }}/240자</span>
|
||||
<span class="templateRequestDraft__label">티어표 설명</span>
|
||||
<textarea v-model="templateRequestDraftDescription" class="templateRequestDraft__input templateRequestDraft__textarea" maxlength="1000" placeholder="예: 여름 이벤트 한정 캐릭터 추가" />
|
||||
<span class="templateRequestDraft__hint">{{ templateRequestDraftDescription.length }}/1000자</span>
|
||||
</label>
|
||||
<label class="toggleSwitch">
|
||||
<input v-model="templateRequestSaveToMyTierList" type="checkbox" />
|
||||
<span class="toggleSwitch__label">내 티어 리스트에도 저장</span>
|
||||
<span class="toggleSwitch__track"><span class="toggleSwitch__thumb"></span></span>
|
||||
</label>
|
||||
<div class="templateRequestDraft__note">
|
||||
저장을 끄면 관리자 확인용 요청 스냅샷만 남고, 현재 작업 중인 티어표는 따로 저장하지 않아요.
|
||||
</div>
|
||||
</div>
|
||||
<div class="modalCard__actions">
|
||||
<button class="btn btn--ghost" @click="closeTemplateUpdateModal">요청 취소</button>
|
||||
@@ -1449,6 +1476,11 @@ onUnmounted(() => {
|
||||
font-size: 12px;
|
||||
color: rgba(255, 255, 255, 0.46);
|
||||
}
|
||||
.templateRequestDraft__note {
|
||||
font-size: 12px;
|
||||
line-height: 1.6;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
}
|
||||
.templateRequestDraft__input {
|
||||
width: 100%;
|
||||
padding: 14px 0;
|
||||
|
||||
Reference in New Issue
Block a user