|
|
|
|
@@ -92,6 +92,7 @@ const userDeleteModalOpen = ref(false)
|
|
|
|
|
const userRoleModalOpen = ref(false)
|
|
|
|
|
const customItemModalOpen = ref(false)
|
|
|
|
|
const customItemDeleteModalOpen = ref(false)
|
|
|
|
|
const templateItemDeleteModalOpen = ref(false)
|
|
|
|
|
const customItemModalHistoryActive = ref(false)
|
|
|
|
|
const modalTargetUser = ref(null)
|
|
|
|
|
const modalPasswordDraft = ref('')
|
|
|
|
|
@@ -100,6 +101,8 @@ const modalUserDraftEmail = ref('')
|
|
|
|
|
const modalUserDraftNickname = ref('')
|
|
|
|
|
const modalUserDraftIsAdmin = ref(false)
|
|
|
|
|
const modalTargetCustomItem = ref(null)
|
|
|
|
|
const modalTargetTemplateItem = ref(null)
|
|
|
|
|
const modalTargetTemplateItemUsage = ref({ totalCount: 0, publicCount: 0, privateCount: 0 })
|
|
|
|
|
const customItemModalDraftLabel = ref('')
|
|
|
|
|
const customItemModalDraftTags = ref([])
|
|
|
|
|
const customItemModalLabelSaving = ref(false)
|
|
|
|
|
@@ -373,6 +376,7 @@ const isAnyModalOpen = computed(
|
|
|
|
|
templatePickerModalOpen.value ||
|
|
|
|
|
customItemModalOpen.value ||
|
|
|
|
|
customItemDeleteModalOpen.value ||
|
|
|
|
|
templateItemDeleteModalOpen.value ||
|
|
|
|
|
adminTierListManageModalOpen.value ||
|
|
|
|
|
imageResetModalOpen.value ||
|
|
|
|
|
previewModalOpen.value
|
|
|
|
|
@@ -1420,12 +1424,26 @@ async function toggleSelectedTemplateVisibility(nextValue) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function removeTemplateItem(itemId) {
|
|
|
|
|
function closeTemplateItemDeleteModal() {
|
|
|
|
|
templateItemDeleteModalOpen.value = false
|
|
|
|
|
modalTargetTemplateItem.value = null
|
|
|
|
|
modalTargetTemplateItemUsage.value = { totalCount: 0, publicCount: 0, privateCount: 0 }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function templateItemDeleteImpactText() {
|
|
|
|
|
const usage = modalTargetTemplateItemUsage.value || { totalCount: 0, publicCount: 0, privateCount: 0 }
|
|
|
|
|
if (usage.totalCount) {
|
|
|
|
|
return `이 아이템은 이미 저장된 티어표 ${usage.totalCount}개(공개 ${usage.publicCount}개, 비공개 ${usage.privateCount}개)에서 사용 중이에요. 기존 저장 티어표에는 영향을 주지 않고, 이후 새로 만드는 티어표에서만 제외됩니다.`
|
|
|
|
|
}
|
|
|
|
|
return '이 기본 아이템을 삭제할까요? 기존 저장 티어표에는 영향을 주지 않고, 이후 새로 만드는 티어표에서만 제외됩니다.'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function removeTemplateItem(item) {
|
|
|
|
|
resetMessages()
|
|
|
|
|
if (!selectedTemplateId.value) return
|
|
|
|
|
if (!selectedTemplateId.value || !item?.id) return
|
|
|
|
|
try {
|
|
|
|
|
const usageRes = await fetch(
|
|
|
|
|
toApiUrl(`/api/admin/templates/${encodeURIComponent(selectedTemplateId.value)}/items/${encodeURIComponent(itemId)}/usage`),
|
|
|
|
|
toApiUrl(`/api/admin/templates/${encodeURIComponent(selectedTemplateId.value)}/items/${encodeURIComponent(item.id)}/usage`),
|
|
|
|
|
{
|
|
|
|
|
credentials: 'include',
|
|
|
|
|
}
|
|
|
|
|
@@ -1433,16 +1451,22 @@ async function removeTemplateItem(itemId) {
|
|
|
|
|
if (!usageRes.ok) throw new Error('usage_failed')
|
|
|
|
|
|
|
|
|
|
const usageData = await usageRes.json()
|
|
|
|
|
const usage = usageData?.usage || { totalCount: 0, publicCount: 0, privateCount: 0 }
|
|
|
|
|
const impactMessage = usage.totalCount
|
|
|
|
|
? `이 아이템은 이미 저장된 티어표 ${usage.totalCount}개(공개 ${usage.publicCount}개, 비공개 ${usage.privateCount}개)에서 사용 중이에요.\n기존 티어표에는 영향을 주지 않고, 이후 새로 만드는 티어표에서만 제외됩니다.\n정말 삭제할까요?`
|
|
|
|
|
: '이 기본 아이템을 삭제할까요?\n기존 저장 티어표에는 영향을 주지 않고, 이후 새로 만드는 티어표에서만 제외됩니다.'
|
|
|
|
|
const ok = window.confirm(impactMessage)
|
|
|
|
|
if (!ok) return
|
|
|
|
|
modalTargetTemplateItem.value = item
|
|
|
|
|
modalTargetTemplateItemUsage.value = usageData?.usage || { totalCount: 0, publicCount: 0, privateCount: 0 }
|
|
|
|
|
templateItemDeleteModalOpen.value = true
|
|
|
|
|
} catch (e) {
|
|
|
|
|
error.value = '템플릿 기본 아이템 삭제에 실패했어요.'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function confirmTemplateItemDelete() {
|
|
|
|
|
resetMessages()
|
|
|
|
|
if (!selectedTemplateId.value || !modalTargetTemplateItem.value?.id) return
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const previousScrollY = window.scrollY
|
|
|
|
|
const res = await fetch(
|
|
|
|
|
toApiUrl(`/api/admin/templates/${encodeURIComponent(selectedTemplateId.value)}/items/${encodeURIComponent(itemId)}`),
|
|
|
|
|
toApiUrl(`/api/admin/templates/${encodeURIComponent(selectedTemplateId.value)}/items/${encodeURIComponent(modalTargetTemplateItem.value.id)}`),
|
|
|
|
|
{
|
|
|
|
|
method: 'DELETE',
|
|
|
|
|
credentials: 'include',
|
|
|
|
|
@@ -1450,6 +1474,7 @@ async function removeTemplateItem(itemId) {
|
|
|
|
|
)
|
|
|
|
|
if (!res.ok) throw new Error('failed')
|
|
|
|
|
|
|
|
|
|
closeTemplateItemDeleteModal()
|
|
|
|
|
await loadTemplate()
|
|
|
|
|
await nextTick()
|
|
|
|
|
window.scrollTo({ top: previousScrollY, behavior: 'auto' })
|
|
|
|
|
@@ -2649,6 +2674,20 @@ function openUserProfile(user) {
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div v-if="templateItemDeleteModalOpen" class="modalOverlay" @click.self="closeTemplateItemDeleteModal">
|
|
|
|
|
<div class="modalCard" role="dialog" aria-modal="true">
|
|
|
|
|
<div class="modalCard__title">기본 아이템 삭제</div>
|
|
|
|
|
<div class="modalCard__desc">
|
|
|
|
|
<strong>{{ modalTargetTemplateItem?.label || '선택한 아이템' }}</strong>
|
|
|
|
|
{{ ' ' }}{{ templateItemDeleteImpactText() }}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="modalCard__actions">
|
|
|
|
|
<button class="btn btn--ghost" @click="closeTemplateItemDeleteModal">취소</button>
|
|
|
|
|
<button class="btn btn--danger" @click="confirmTemplateItemDelete">삭제</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div v-if="adminTierListManageModalOpen" class="modalOverlay" @click.self="closeAdminTierListManageModal">
|
|
|
|
|
<div class="modalCard" role="dialog" aria-modal="true">
|
|
|
|
|
<div class="modalCard__title">티어표 관리</div>
|
|
|
|
|
@@ -3683,6 +3722,12 @@ function openUserProfile(user) {
|
|
|
|
|
}
|
|
|
|
|
.adminUiScope .templateSettingsCard__actions > .btn {
|
|
|
|
|
flex: 0 0 auto;
|
|
|
|
|
height: auto;
|
|
|
|
|
max-width: 100%;
|
|
|
|
|
white-space: normal;
|
|
|
|
|
}
|
|
|
|
|
.adminUiScope .templateSettingsCard__actions > a.btn {
|
|
|
|
|
height: auto;
|
|
|
|
|
max-width: 100%;
|
|
|
|
|
white-space: normal;
|
|
|
|
|
}
|
|
|
|
|
@@ -3958,8 +4003,8 @@ function openUserProfile(user) {
|
|
|
|
|
}
|
|
|
|
|
.adminUiScope .thumbCard__deleteBtn {
|
|
|
|
|
position: absolute;
|
|
|
|
|
top: 8px;
|
|
|
|
|
right: 8px;
|
|
|
|
|
top: -24px;
|
|
|
|
|
right: -24px;
|
|
|
|
|
width: 28px;
|
|
|
|
|
height: 28px;
|
|
|
|
|
display: grid;
|
|
|
|
|
|