릴리스: v1.3.35 라이트모드와 아이템 모달 보정
This commit is contained in:
@@ -56,6 +56,7 @@ const userDeleteModalOpen = ref(false)
|
||||
const userRoleModalOpen = ref(false)
|
||||
const customItemModalOpen = ref(false)
|
||||
const customItemDeleteModalOpen = ref(false)
|
||||
const customItemModalHistoryActive = ref(false)
|
||||
const modalTargetUser = ref(null)
|
||||
const modalPasswordDraft = ref('')
|
||||
const modalRoleNextAdmin = ref(false)
|
||||
@@ -194,13 +195,26 @@ const adminOverviewStats = computed(() => {
|
||||
]
|
||||
})
|
||||
|
||||
function handleAdminPopState() {
|
||||
if (customItemDeleteModalOpen.value) {
|
||||
customItemDeleteModalOpen.value = false
|
||||
if (customItemModalOpen.value) pushCustomItemModalHistoryState()
|
||||
return
|
||||
}
|
||||
if (customItemModalOpen.value) {
|
||||
closeCustomItemModal({ fromPopState: true })
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
if (typeof window !== 'undefined') window.addEventListener('popstate', handleAdminPopState)
|
||||
await auth.refresh()
|
||||
await Promise.all([refreshGames(), refreshCustomItems(), refreshAdminTierLists(), refreshUsers(), refreshTemplateRequests(), refreshImageDiagnostics()])
|
||||
await syncFeaturedSortable()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (typeof window !== 'undefined') window.removeEventListener('popstate', handleAdminPopState)
|
||||
clearPreviewUrl('item')
|
||||
clearPreviewUrl('thumb')
|
||||
destroyFeaturedSortable()
|
||||
@@ -1048,26 +1062,44 @@ function moveCustomItemPage(direction) {
|
||||
refreshCustomItems()
|
||||
}
|
||||
|
||||
function pushCustomItemModalHistoryState() {
|
||||
if (typeof window === 'undefined') return
|
||||
window.history.pushState({ ...(window.history.state || {}), adminCustomItemModal: true }, '', window.location.href)
|
||||
customItemModalHistoryActive.value = true
|
||||
}
|
||||
|
||||
function openCustomItemModal(item) {
|
||||
modalTargetCustomItem.value = item || null
|
||||
customItemModalTargetGameId.value = ''
|
||||
customItemModalGameQuery.value = ''
|
||||
customItemModalGameSort.value = 'recent'
|
||||
customItemModalOpen.value = true
|
||||
pushCustomItemModalHistoryState()
|
||||
}
|
||||
|
||||
function closeCustomItemModal() {
|
||||
function closeCustomItemModal({ fromPopState = false } = {}) {
|
||||
customItemModalOpen.value = false
|
||||
customItemDeleteModalOpen.value = false
|
||||
modalTargetCustomItem.value = null
|
||||
customItemModalTargetGameId.value = ''
|
||||
customItemModalGameQuery.value = ''
|
||||
customItemModalGameSort.value = 'recent'
|
||||
|
||||
if (fromPopState) {
|
||||
customItemModalHistoryActive.value = false
|
||||
return
|
||||
}
|
||||
|
||||
if (customItemModalHistoryActive.value && typeof window !== 'undefined') {
|
||||
customItemModalHistoryActive.value = false
|
||||
window.history.back()
|
||||
}
|
||||
}
|
||||
|
||||
function openCustomItemDeleteModal(item) {
|
||||
if (!item) return
|
||||
if (item.usageCount > 0) {
|
||||
error.value = '사용 중인 사용자 업로드 이미지는 먼저 참조를 정리해야 삭제할 수 있어요.'
|
||||
if (item.sourceType === 'user' && (item.usageCount > 0 || item.linkedGames.length > 0)) {
|
||||
error.value = '사용 중이거나 템플릿에 연결된 사용자 업로드 이미지는 먼저 참조를 정리해야 삭제할 수 있어요.'
|
||||
return
|
||||
}
|
||||
modalTargetCustomItem.value = item
|
||||
@@ -1081,8 +1113,8 @@ function closeCustomItemDeleteModal() {
|
||||
async function removeCustomItem(item = modalTargetCustomItem.value) {
|
||||
resetMessages()
|
||||
if (!item) return
|
||||
if (item.usageCount > 0) {
|
||||
error.value = '사용 중인 사용자 업로드 이미지는 먼저 참조를 정리해야 삭제할 수 있어요.'
|
||||
if (item.sourceType === 'user' && (item.usageCount > 0 || item.linkedGames.length > 0)) {
|
||||
error.value = '사용 중이거나 템플릿에 연결된 사용자 업로드 이미지는 먼저 참조를 정리해야 삭제할 수 있어요.'
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1091,9 +1123,9 @@ async function removeCustomItem(item = modalTargetCustomItem.value) {
|
||||
closeCustomItemDeleteModal()
|
||||
closeCustomItemModal()
|
||||
await refreshCustomItems()
|
||||
success.value = '미사용 사용자 업로드 이미지를 삭제했어요.'
|
||||
success.value = item.sourceType === 'template' ? '선택한 템플릿 아이템을 제거했어요.' : '사용자 업로드 이미지를 삭제했어요.'
|
||||
} catch (e) {
|
||||
error.value = '커스텀 이미지 삭제에 실패했어요.'
|
||||
error.value = item.sourceType === 'template' ? '템플릿 아이템 제거에 실패했어요.' : '사용자 업로드 이미지 삭제에 실패했어요.'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1939,7 +1971,7 @@ async function saveFeaturedOrder() {
|
||||
<div v-if="modalTargetCustomItem" class="customItemModal">
|
||||
<aside class="customItemModal__pickerPanel">
|
||||
<div class="customItemModal__pickerHead">
|
||||
<div class="customItemModal__pickerEyebrow">GAME LIBRARY</div>
|
||||
<div class="customItemModal__pickerEyebrow">GAME PICKER</div>
|
||||
<div class="customItemModal__pickerTitle">템플릿으로 추가할 게임</div>
|
||||
</div>
|
||||
<div class="customItemModal__pickerControls">
|
||||
@@ -1993,7 +2025,7 @@ async function saveFeaturedOrder() {
|
||||
<button class="btn btn--ghost customItemModal__action" :disabled="!customItemModalTargetGameId || modalTargetCustomItem.isPromoting" @click="promoteCustomItem(modalTargetCustomItem)">
|
||||
{{ modalTargetCustomItem.isPromoting ? '추가중...' : '기본 템플릿에 추가' }}
|
||||
</button>
|
||||
<button v-if="modalTargetCustomItem.canDelete" class="btn btn--danger customItemModal__action" :disabled="modalTargetCustomItem.usageCount > 0 || visibleLinkedGames.length > 0" @click="openCustomItemDeleteModal(modalTargetCustomItem)">삭제</button>
|
||||
<button v-if="modalTargetCustomItem.canDelete" class="btn btn--danger customItemModal__action" :disabled="modalTargetCustomItem.sourceType === 'user' && (modalTargetCustomItem.usageCount > 0 || visibleLinkedGames.length > 0)" @click="openCustomItemDeleteModal(modalTargetCustomItem)">삭제</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -2002,8 +2034,8 @@ async function saveFeaturedOrder() {
|
||||
|
||||
<div v-if="customItemDeleteModalOpen" class="modalOverlay" @click.self="closeCustomItemDeleteModal">
|
||||
<div class="modalCard" role="dialog" aria-modal="true">
|
||||
<div class="modalCard__title">커스텀 아이템 삭제</div>
|
||||
<div class="modalCard__desc">{{ modalTargetCustomItem ? '"' + modalTargetCustomItem.label + '" 이미지를 삭제할까요? 사용자 업로드이면서 어디에도 연결되지 않은 이미지에만 삭제를 허용합니다.' : '' }}</div>
|
||||
<div class="modalCard__title">아이템 삭제</div>
|
||||
<div class="modalCard__desc">{{ !modalTargetCustomItem ? '' : modalTargetCustomItem.sourceType === 'template' ? '"' + modalTargetCustomItem.label + '" 항목을 현재 템플릿에서 제거할까요? 이미 저장된 같은 게임의 티어표에서도 함께 빠질 수 있어요.' : '"' + modalTargetCustomItem.label + '" 이미지를 삭제할까요? 사용자 업로드이면서 어디에도 연결되지 않은 이미지에만 삭제를 허용합니다.' }}</div>
|
||||
<div class="modalCard__actions">
|
||||
<button class="btn btn--ghost" @click="closeCustomItemDeleteModal">취소</button>
|
||||
<button class="btn btn--danger" @click="removeCustomItem()">삭제</button>
|
||||
@@ -2894,6 +2926,7 @@ async function saveFeaturedOrder() {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
color: var(--theme-text-soft);
|
||||
background: var(--theme-card-bg);
|
||||
}
|
||||
.selectedThumb--sidebar {
|
||||
width: 100%;
|
||||
@@ -3134,12 +3167,12 @@ async function saveFeaturedOrder() {
|
||||
font-weight: 800;
|
||||
font-size: 13px;
|
||||
line-height: 1.3;
|
||||
color: #ffffff;
|
||||
color: var(--theme-text);
|
||||
}
|
||||
.customItemModal {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(220px, 260px) minmax(0, 1fr);
|
||||
gap: 18px;
|
||||
grid-template-columns: minmax(280px, 320px) minmax(0, 1fr);
|
||||
gap: 24px;
|
||||
align-items: start;
|
||||
}
|
||||
.customItemModal__pickerPanel {
|
||||
@@ -3275,7 +3308,7 @@ async function saveFeaturedOrder() {
|
||||
text-align: center;
|
||||
}
|
||||
.modalCard--customItem {
|
||||
width: min(980px, 100%);
|
||||
width: min(1160px, calc(100vw - 48px));
|
||||
}
|
||||
.pager {
|
||||
margin-top: 16px;
|
||||
|
||||
Reference in New Issue
Block a user