Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bd53cf96dc | |||
| 66c3b1e7b7 | |||
| 494f04d9a7 |
@@ -1,5 +1,18 @@
|
||||
# 의사결정 이력
|
||||
|
||||
## 2026-04-02 v1.3.75
|
||||
- 관리자 공용 모달은 기본 카드 여백을 계속 쓰되, 내부에 자체 셸을 가진 대형 상세 모달까지 같은 패딩을 강제로 받으면 오히려 레이아웃이 무너지므로 예외 클래스로 분리하는 편이 맞다고 정리했다.
|
||||
- 관리자 표기 링크는 텍스트만 두기보다, 추후 주소 변경이 쉬운 한 곳짜리 상수와 새 창 링크로 관리하는 편이 운영 측면에서 더 낫다고 판단했다.
|
||||
- 왼쪽 사이드 레일 접힘 상태는 요소를 좁히는 것만으로는 높이와 정렬 문제가 계속 남으므로, 메타 텍스트는 실제로 숨기고 아이콘 중심 문법으로 따로 정리하는 편이 맞다고 판단했다.
|
||||
|
||||
## 2026-04-02 v1.3.74
|
||||
- 관리자 공용 게임 선택 모달은 단순 검색만 제공하기보다, 현재 문맥에서 이미 선택 불가능한 대상을 `이미 추가됨`으로 명시하고 막아 주는 편이 운영 실수를 줄이는 데 더 효과적이라고 정리했다.
|
||||
- 프로젝트 표기는 관리자 헤더 상단보다 사이드바 최하단의 작은 카피라이트 문구로 빼는 편이 정보 밀도를 덜 방해한다고 판단했다.
|
||||
|
||||
## 2026-04-02 v1.3.73
|
||||
- 게임 선택이 여러 관리자 화면에 퍼지기 시작한 시점에서는 일부 화면만 셀렉트나 내부 리스트를 유지하기보다, 공용 검색 모달 하나로 통일하는 편이 장기적으로 더 일관되고 확장에 강하다고 정리했다.
|
||||
- 검색 입력과 실행 버튼은 세로로 같은 문법으로 쌓기보다, 입력은 입력끼리 실행은 액션으로 읽히게 한 줄 배치로 적당히 구분해주는 편이 운영 화면에서 덜 답답하다고 판단했다.
|
||||
|
||||
## 2026-04-02 v1.3.72
|
||||
- 라우트 복원용 watcher가 composable 반환값 초기화보다 먼저 돌 수 있는 구간에서는 직접 함수를 즉시 호출하기보다, 초기화 완료 뒤 실행되도록 한 템포 미루는 편이 안전하다고 정리했다.
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
# 할 일 및 이슈
|
||||
|
||||
## 단기 확인
|
||||
- 앱 왼쪽 사이드 레일은 접힘 상태 레이아웃을 다시 손봤으므로, 데스크톱에서 접기/펼치기 반복 시 아바타 영역 높이, 아이콘 중앙 정렬, 검색 버튼 간격, 네비게이션 히트 영역이 모두 자연스러운지 한 번 더 QA한다.
|
||||
- 관리자 우측 사이드바 하단 카피라이트 링크는 새 창 외부 링크로 바꿨으므로, 실제 클릭 시 `zenn.town` 연결과 hover 대비가 자연스러운지 한 번 더 QA한다.
|
||||
- 관리자 아이템 상세 모달은 공통 패딩 예외 처리를 다시 넣었으므로, 대형 상세 모달과 일반 게임 선택 모달이 각각 기대한 크기로 보이는지 한 번 더 QA한다.
|
||||
- 아이템 관리 모달의 공용 게임 선택기에서는 이미 연결된 게임이 비활성화되므로, 실제 운영 데이터에서 중복 연결 방지와 `이미 추가됨` 표시가 기대대로 읽히는지 한 번 더 QA한다.
|
||||
- 공용 게임 선택 모달을 아이템 관리 모달에도 붙였으므로, 관리자 `게임 관리 / 전체 티어표 관리 / 아이템 관리` 세 흐름에서 같은 검색/선택 UX가 자연스럽게 느껴지는지 한 번 더 QA한다.
|
||||
- 관리자 `/admin/games?gameId=...` 직접 진입과 새로고침에서 선택 게임이 정상 복원되고 콘솔 오류가 없는지 한 번 더 QA한다.
|
||||
- 공용 `게임 선택` 검색 모달은 새로 붙였으므로, 게임 관리 선택/전체 티어표 관리 필터 양쪽에서 검색어 입력, 선택, 해제, 뒤로가기 흐름을 한 번 더 QA한다.
|
||||
- 관리자 `전체 티어표 관리`의 게임 필터와 관리 모달은 새로 붙였으므로, 실제 운영 데이터에서 필터 전환 후 공개/비공개 집계, 제목 수정, 비공개 전환, 삭제 흐름이 자연스럽게 이어지는지 한 번 더 QA한다.
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# 업데이트 로그
|
||||
|
||||
## 2026-04-02 v1.3.75
|
||||
- 관리자 공용 모달 카드의 기본 `padding: 20px`는 그대로 두되, 아이템 상세처럼 내부 레이아웃이 이미 큰 셸을 가진 모달은 `modalCard--customItem`에서 다시 덮어쓰지 않도록 분리해 상세 모달 크기와 내부 배치가 무너지지 않게 정리함.
|
||||
- 관리자 우측 사이드바 최하단의 카피라이트 문구는 이제 별도 상수 URL을 참조하는 외부 링크로 바꿔 새 창에서 열리게 했고, 추후 주소를 바꿔야 할 때 한 곳만 수정하면 되도록 정리함.
|
||||
- 앱 왼쪽 사이드 레일의 접힘 상태는 메타 텍스트를 단순히 투명하게 남겨두는 대신 실제로 숨기고, 아바타/검색/내비 아이콘을 다시 중앙 정렬해 접었을 때 높이가 비정상적으로 늘어나거나 간격이 남아 보이던 레이아웃을 정리함.
|
||||
|
||||
## 2026-04-02 v1.3.74
|
||||
- 아이템 관리 상세에서 템플릿 추가 대상 게임을 고를 때, 이미 해당 이미지가 연결된 게임은 공용 게임 선택 모달에서 `이미 추가됨`으로 표시하고 비활성화해 중복 추가 실수를 미리 막도록 정리함.
|
||||
- 관리자 우측 사이드바 최하단에는 작은 카피라이트 문구를 추가해, 헤더에 관리 정보만 남기고 프로젝트 표기는 하단에서 조용히 보이도록 정리함.
|
||||
|
||||
## 2026-04-02 v1.3.73
|
||||
- 전체 티어표 관리 카드 썸네일은 `draggable="false"`로 바꿔, 미리보기 진입 시 브라우저 기본 이미지 드래그가 클릭을 방해하지 않도록 정리함.
|
||||
- 관리자 사이드바의 검색 입력과 검색 버튼은 한 줄로 묶어, 입력/선택/실행 버튼이 모두 같은 크기의 세로 스택처럼 보이던 답답함을 조금 줄이고 역할 구분을 더 분명하게 함.
|
||||
- 아이템 관리 상세 모달의 템플릿 추가 대상 선택도 내부 전용 게임 리스트 대신 공용 `게임 선택` 검색 모달을 쓰도록 바꿔, 향후 게임 수가 많아져도 같은 선택 문법으로 이어지게 정리함.
|
||||
|
||||
## 2026-04-02 v1.3.72
|
||||
- 관리자 화면 초기화 중 `/admin/games?gameId=...` 경로를 즉시 처리하는 watcher가 `loadGame` 초기화보다 먼저 실행되어 브라우저 콘솔에 `Cannot access 'loadGame' before initialization` 오류가 나던 문제를 수정함.
|
||||
- 게임 라우트 진입 시 실제 게임 로딩 호출은 컴포넌트 초기화가 끝난 뒤 microtask로 미뤄 실행하도록 바꿔, 첫 진입/새로고침에서도 게임 선택 복원 흐름이 안전하게 이어지게 정리함.
|
||||
|
||||
@@ -953,21 +953,22 @@ function submitGlobalSearch() {
|
||||
}
|
||||
|
||||
.appShell--leftCollapsed .appUserCard {
|
||||
min-height: auto;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.appShell--leftCollapsed .appUserCard__button,
|
||||
.appShell--leftCollapsed .appUserCard__guest {
|
||||
min-height: 44px;
|
||||
padding: 0;
|
||||
gap: 0;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.appShell--leftCollapsed .appUserCard__meta,
|
||||
.appShell--leftCollapsed .leftNav__label,
|
||||
.appShell--leftCollapsed .searchStub__input {
|
||||
opacity: 0;
|
||||
max-width: 0;
|
||||
transform: translateX(-4px);
|
||||
pointer-events: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.appShell--leftCollapsed .appUserCard__avatar {
|
||||
@@ -976,11 +977,13 @@ function submitGlobalSearch() {
|
||||
}
|
||||
|
||||
.appShell--leftCollapsed .searchStub {
|
||||
padding: 11px 0;
|
||||
gap: 0;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.appShell--leftCollapsed .searchStub__iconButton {
|
||||
width: auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.appShell--leftCollapsed .leftNav {
|
||||
@@ -988,14 +991,25 @@ function submitGlobalSearch() {
|
||||
}
|
||||
|
||||
.appShell--leftCollapsed .leftNav__item {
|
||||
padding: 11px 0;
|
||||
gap: 0;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.appShell--leftCollapsed .leftNav__glyph {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
.appShell--leftCollapsed .leftRail__bottom {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.appShell--leftCollapsed .leftRail__content {
|
||||
display: grid;
|
||||
align-content: start;
|
||||
justify-items: stretch;
|
||||
gap: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ const props = defineProps({
|
||||
<article v-for="request in props.templateRequests" :key="request.id" class="tierAdminCard templateRequestCard templateRequestCard--aligned">
|
||||
<div class="templateRequestCard__side">
|
||||
<button class="tierAdminCard__preview templateRequestCard__preview" type="button" @click="props.openTemplateRequestPreview(request)">
|
||||
<img v-if="request.thumbnailSrc" class="tierAdminCard__thumb" :src="toApiUrl(request.thumbnailSrc)" :alt="request.sourceTierListTitle" />
|
||||
<img v-if="request.thumbnailSrc" class="tierAdminCard__thumb" :src="toApiUrl(request.thumbnailSrc)" :alt="request.sourceTierListTitle" draggable="false" />
|
||||
<div v-else class="tierAdminCard__thumb tierAdminCard__thumb--empty"></div>
|
||||
</button>
|
||||
<div class="templateRequestCard__thumbMeta">
|
||||
@@ -142,7 +142,7 @@ const props = defineProps({
|
||||
<div v-else class="tierAdminList">
|
||||
<article v-for="tierList in props.adminTierLists" :key="tierList.id" class="tierAdminCard">
|
||||
<button class="tierAdminCard__preview" type="button" @click="props.openAdminTierList(tierList)">
|
||||
<img v-if="props.tierListThumbUrl(tierList)" class="tierAdminCard__thumb" :src="props.tierListThumbUrl(tierList)" :alt="tierList.title" />
|
||||
<img v-if="props.tierListThumbUrl(tierList)" class="tierAdminCard__thumb" :src="props.tierListThumbUrl(tierList)" :alt="tierList.title" draggable="false" />
|
||||
<div v-else class="tierAdminCard__thumb tierAdminCard__thumb--empty"></div>
|
||||
</button>
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@ export function useAdminCustomItems({
|
||||
customItemModalDraftLabel,
|
||||
customItemModalLabelSaving,
|
||||
customItemModalTargetGameId,
|
||||
customItemModalGameQuery,
|
||||
customItemModalGameSort,
|
||||
games,
|
||||
selectedGameId,
|
||||
refreshCustomItems,
|
||||
@@ -62,8 +60,6 @@ export function useAdminCustomItems({
|
||||
modalTargetCustomItem.value = item || null
|
||||
customItemModalDraftLabel.value = item?.label || ''
|
||||
customItemModalTargetGameId.value = ''
|
||||
customItemModalGameQuery.value = ''
|
||||
customItemModalGameSort.value = 'recent'
|
||||
customItemModalOpen.value = true
|
||||
pushCustomItemModalHistoryState()
|
||||
}
|
||||
@@ -75,8 +71,6 @@ export function useAdminCustomItems({
|
||||
customItemModalDraftLabel.value = ''
|
||||
customItemModalLabelSaving.value = false
|
||||
customItemModalTargetGameId.value = ''
|
||||
customItemModalGameQuery.value = ''
|
||||
customItemModalGameSort.value = 'recent'
|
||||
|
||||
if (fromPopState) {
|
||||
customItemModalHistoryActive.value = false
|
||||
|
||||
@@ -26,6 +26,7 @@ const router = useRouter()
|
||||
const globalRightRailOpen = inject('rightRailOpen', ref(true))
|
||||
const localRightRailTarget = inject('localRightRailTarget', '#local-right-rail-root')
|
||||
const isAdmin = computed(() => !!auth.user?.isAdmin)
|
||||
const ADMIN_COPYRIGHT_URL = 'https://zenn.town/@murabito'
|
||||
|
||||
const activeTab = ref('featured')
|
||||
const tierlistsMode = ref('requests')
|
||||
@@ -46,8 +47,6 @@ const customItemLimit = ref(50)
|
||||
const customItemTotal = ref(0)
|
||||
const customItemFilter = ref('all')
|
||||
const customItemModalTargetGameId = ref('')
|
||||
const customItemModalGameQuery = ref('')
|
||||
const customItemModalGameSort = ref('recent')
|
||||
|
||||
const adminTierLists = ref([])
|
||||
const adminTierListQuery = ref('')
|
||||
@@ -212,6 +211,7 @@ const filteredGamePickerGames = computed(() => {
|
||||
return Number(b.createdAt || 0) - Number(a.createdAt || 0)
|
||||
})
|
||||
})
|
||||
const customItemTargetGame = computed(() => games.value.find((game) => game.id === customItemModalTargetGameId.value) || null)
|
||||
const importModalItemCount = computed(() => importModalItems.value.length)
|
||||
const activeTabTitle = computed(() => {
|
||||
if (activeTab.value === 'featured') return '목록 관리'
|
||||
@@ -490,7 +490,6 @@ watch(
|
||||
customItemQuery.value = ''
|
||||
customItemFilter.value = 'all'
|
||||
customItemPage.value = 1
|
||||
customItemModalGameQuery.value = ''
|
||||
await refreshCustomItems()
|
||||
return
|
||||
}
|
||||
@@ -622,21 +621,7 @@ const imageDiagnosticsCards = computed(() => {
|
||||
const visibleLinkedGames = computed(() =>
|
||||
(modalTargetCustomItem.value?.linkedGames || []).filter((game) => game?.id && game.id !== 'freeform')
|
||||
)
|
||||
const filteredCustomItemModalGames = computed(() => {
|
||||
const query = customItemModalGameQuery.value.trim().toLowerCase()
|
||||
const linkedIds = new Set(visibleLinkedGames.value.map((game) => game.id))
|
||||
const list = games.value.filter((game) => {
|
||||
if (!query) return true
|
||||
return `${game.name || ''} ${game.id || ''}`.toLowerCase().includes(query)
|
||||
})
|
||||
|
||||
return list.slice().sort((a, b) => {
|
||||
const linkedDelta = Number(linkedIds.has(a.id)) - Number(linkedIds.has(b.id))
|
||||
if (linkedDelta !== 0) return linkedDelta
|
||||
if (customItemModalGameSort.value === 'oldest') return Number(a.createdAt || 0) - Number(b.createdAt || 0)
|
||||
return Number(b.createdAt || 0) - Number(a.createdAt || 0)
|
||||
})
|
||||
})
|
||||
const linkedCustomItemGameIds = computed(() => new Set(visibleLinkedGames.value.map((game) => game.id).filter(Boolean)))
|
||||
|
||||
const imageStatsPeriodLabel = computed(() => (imageStatsMonth.value ? `${imageStatsMonth.value} 기준` : '전체 기간'))
|
||||
const imageStatsYearOptions = computed(() => {
|
||||
@@ -1040,8 +1025,6 @@ const {
|
||||
customItemModalDraftLabel,
|
||||
customItemModalLabelSaving,
|
||||
customItemModalTargetGameId,
|
||||
customItemModalGameQuery,
|
||||
customItemModalGameSort,
|
||||
games,
|
||||
selectedGameId,
|
||||
refreshCustomItems,
|
||||
@@ -1327,6 +1310,12 @@ async function chooseGameFromPicker(gameId) {
|
||||
closeGamePickerModal()
|
||||
return
|
||||
}
|
||||
if (gamePickerMode.value === 'custom-item-target') {
|
||||
if (linkedCustomItemGameIds.value.has(gameId)) return
|
||||
customItemModalTargetGameId.value = gameId
|
||||
closeGamePickerModal()
|
||||
return
|
||||
}
|
||||
|
||||
await selectAdminGame(gameId)
|
||||
closeGamePickerModal()
|
||||
@@ -1963,32 +1952,16 @@ function userAvatarFallback(user) {
|
||||
<div class="customItemModal__pickerHead">
|
||||
<div class="customItemModal__pickerEyebrow">GAME PICKER</div>
|
||||
<div class="customItemModal__pickerTitle">템플릿으로 추가할 게임</div>
|
||||
</div>
|
||||
<div class="adminSelectionCard">
|
||||
<div class="adminSelectionCard__label">선택한 게임</div>
|
||||
<div class="adminSelectionCard__title">{{ customItemTargetGame?.name || '아직 선택하지 않음' }}</div>
|
||||
<div class="adminSelectionCard__meta">{{ customItemTargetGame?.id || '게임을 골라 주세요.' }}</div>
|
||||
</div>
|
||||
<div class="customItemModal__pickerActions">
|
||||
<button class="btn btn--ghost" type="button" @click="openGamePickerModal('custom-item-target')">게임 선택</button>
|
||||
<button class="btn btn--ghost btn--small customItemModal__createGameButton" type="button" @click="openGameCreateModal">새 템플릿 만들기</button>
|
||||
</div>
|
||||
<div class="customItemModal__pickerControls">
|
||||
<input v-model="customItemModalGameQuery" class="input input--dense" placeholder="게임 이름, ID 검색" />
|
||||
<select v-model="customItemModalGameSort" class="select">
|
||||
<option value="recent">최신순</option>
|
||||
<option value="oldest">오래된순</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="customItemModal__gameList">
|
||||
<button
|
||||
v-for="game in filteredCustomItemModalGames"
|
||||
:key="game.id"
|
||||
type="button"
|
||||
class="customItemModal__gameItem"
|
||||
:class="{
|
||||
'customItemModal__gameItem--active': customItemModalTargetGameId === game.id,
|
||||
'customItemModal__gameItem--linked': visibleLinkedGames.some((entry) => entry.id === game.id),
|
||||
}"
|
||||
@click="customItemModalTargetGameId = game.id"
|
||||
>
|
||||
<span class="customItemModal__gameName">{{ game.name }}</span>
|
||||
<span class="customItemModal__gameMeta">{{ game.id }}</span>
|
||||
<span v-if="visibleLinkedGames.some((entry) => entry.id === game.id)" class="customItemModal__gameState">이미 포함됨</span>
|
||||
</button>
|
||||
</div>
|
||||
</aside>
|
||||
<div class="customItemModal__body">
|
||||
<button class="customItemModal__close" type="button" @click="closeCustomItemModal">닫기</button>
|
||||
@@ -2065,12 +2038,21 @@ function userAvatarFallback(user) {
|
||||
v-for="game in filteredGamePickerGames"
|
||||
:key="game.id"
|
||||
class="adminGamePicker__item"
|
||||
:class="{ 'adminGamePicker__item--active': gamePickerMode === 'tierlists-filter' ? adminTierListGameId === game.id : selectedGameId === game.id }"
|
||||
:class="{
|
||||
'adminGamePicker__item--active': gamePickerMode === 'tierlists-filter'
|
||||
? adminTierListGameId === game.id
|
||||
: gamePickerMode === 'custom-item-target'
|
||||
? customItemModalTargetGameId === game.id
|
||||
: selectedGameId === game.id,
|
||||
'adminGamePicker__item--disabled': gamePickerMode === 'custom-item-target' && linkedCustomItemGameIds.has(game.id),
|
||||
}"
|
||||
type="button"
|
||||
:disabled="gamePickerMode === 'custom-item-target' && linkedCustomItemGameIds.has(game.id)"
|
||||
@click="chooseGameFromPicker(game.id)"
|
||||
>
|
||||
<span class="adminGamePicker__name">{{ game.name }}</span>
|
||||
<span class="adminGamePicker__meta">{{ game.id }}</span>
|
||||
<span v-if="gamePickerMode === 'custom-item-target' && linkedCustomItemGameIds.has(game.id)" class="adminGamePicker__state">이미 추가됨</span>
|
||||
</button>
|
||||
<div v-if="!filteredGamePickerGames.length" class="hint hint--tight">검색 결과가 없어요.</div>
|
||||
</div>
|
||||
@@ -2244,8 +2226,10 @@ function userAvatarFallback(user) {
|
||||
<section v-else-if="activeTab === 'items'" class="adminSidebar__panel">
|
||||
<div class="adminSidebar__label">Filters</div>
|
||||
<div class="adminSidebar__group">
|
||||
<input v-model="customItemQuery" class="input" placeholder="파일명, 라벨, 업로더 검색" @keydown.enter.prevent="submitCustomItemSearch" />
|
||||
<button class="btn btn--ghost" @click="submitCustomItemSearch">검색</button>
|
||||
<div class="adminSidebar__inlineRow">
|
||||
<input v-model="customItemQuery" class="input" placeholder="파일명, 라벨, 업로더 검색" @keydown.enter.prevent="submitCustomItemSearch" />
|
||||
<button class="btn btn--ghost" @click="submitCustomItemSearch">검색</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="adminSidebar__group">
|
||||
<select :value="customItemLimit" class="select" @change="changeCustomItemLimit(Number($event.target.value))">
|
||||
@@ -2290,13 +2274,15 @@ function userAvatarFallback(user) {
|
||||
<template v-if="tierlistsMode === 'requests'"></template>
|
||||
<template v-else>
|
||||
<div class="adminSidebar__group">
|
||||
<input
|
||||
v-model="adminTierListQuery"
|
||||
class="input"
|
||||
placeholder="제목, 작성자, 게임 이름 검색"
|
||||
@keydown.enter.prevent="submitAdminTierListSearch"
|
||||
/>
|
||||
<button class="btn btn--ghost" @click="submitAdminTierListSearch">검색</button>
|
||||
<div class="adminSidebar__inlineRow">
|
||||
<input
|
||||
v-model="adminTierListQuery"
|
||||
class="input"
|
||||
placeholder="제목, 작성자, 게임 이름 검색"
|
||||
@keydown.enter.prevent="submitAdminTierListSearch"
|
||||
/>
|
||||
<button class="btn btn--ghost" @click="submitAdminTierListSearch">검색</button>
|
||||
</div>
|
||||
<button class="btn btn--ghost" @click="openGamePickerModal('tierlists-filter')">게임 선택</button>
|
||||
<div v-if="adminTierListGameId" class="adminSelectionCard">
|
||||
<div class="adminSelectionCard__label">필터된 게임</div>
|
||||
@@ -2404,6 +2390,11 @@ function userAvatarFallback(user) {
|
||||
</div>
|
||||
</section>
|
||||
</aside>
|
||||
<div v-show="globalRightRailOpen" class="adminSidebarFooter adminUiScope">
|
||||
<span>Copyright © 2026 </span>
|
||||
<a :href="ADMIN_COPYRIGHT_URL" target="_blank" rel="noreferrer">zenn</a>
|
||||
<span>. All rights reserved.</span>
|
||||
</div>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
@@ -2482,6 +2473,23 @@ function userAvatarFallback(user) {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
.adminUiScope.adminSidebarFooter {
|
||||
margin-top: 6px;
|
||||
padding: 0 4px 2px;
|
||||
font-size: 9px;
|
||||
line-height: 1.4;
|
||||
text-align: center;
|
||||
color: var(--theme-text-faint);
|
||||
opacity: 0.72;
|
||||
}
|
||||
.adminUiScope.adminSidebarFooter a {
|
||||
color: #00ffff;
|
||||
text-decoration: none;
|
||||
}
|
||||
.adminUiScope.adminSidebarFooter a:hover {
|
||||
color: #00ffff;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.adminUiScope .adminSidebar__panel {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
@@ -2538,6 +2546,15 @@ function userAvatarFallback(user) {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
.adminUiScope .adminSidebar__inlineRow {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
.adminUiScope .adminSidebar__inlineRow .btn {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.adminUiScope .adminSidebar__group--monthPicker {
|
||||
align-items: start;
|
||||
}
|
||||
@@ -2589,6 +2606,11 @@ function userAvatarFallback(user) {
|
||||
border-color: rgba(77, 127, 233, 0.58);
|
||||
background: rgba(77, 127, 233, 0.12);
|
||||
}
|
||||
.adminUiScope .adminGamePicker__item--disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.58;
|
||||
border-style: dashed;
|
||||
}
|
||||
.adminUiScope .adminGamePicker__name {
|
||||
font-size: 13px;
|
||||
font-weight: 800;
|
||||
@@ -2600,6 +2622,11 @@ function userAvatarFallback(user) {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.adminUiScope .adminGamePicker__state {
|
||||
margin-top: 4px;
|
||||
font-size: 11px;
|
||||
color: var(--theme-text-faint);
|
||||
}
|
||||
.adminUiScope .gamePickerModalList {
|
||||
margin-top: 14px;
|
||||
display: grid;
|
||||
@@ -3463,46 +3490,13 @@ function userAvatarFallback(user) {
|
||||
font-size: 18px;
|
||||
font-weight: 900;
|
||||
}
|
||||
.adminUiScope .customItemModal__pickerControls {
|
||||
.adminUiScope .customItemModal__pickerActions {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
.adminUiScope .customItemModal__gameList {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
max-height: 440px;
|
||||
overflow: auto;
|
||||
}
|
||||
.adminUiScope .customItemModal__createGameButton {
|
||||
justify-self: start;
|
||||
}
|
||||
.adminUiScope .customItemModal__gameItem {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
padding: 12px 13px;
|
||||
border-radius: 16px;
|
||||
border: 1px solid var(--theme-border);
|
||||
background: var(--theme-surface-soft);
|
||||
color: var(--theme-text);
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
.adminUiScope .customItemModal__gameItem--active {
|
||||
border-color: rgba(96, 165, 250, 0.42);
|
||||
background: rgba(96, 165, 250, 0.12);
|
||||
}
|
||||
.adminUiScope .customItemModal__gameItem--linked {
|
||||
border-style: dashed;
|
||||
}
|
||||
.adminUiScope .customItemModal__gameName {
|
||||
font-size: 13px;
|
||||
font-weight: 800;
|
||||
}
|
||||
.adminUiScope .customItemModal__gameMeta,
|
||||
.adminUiScope .customItemModal__gameState {
|
||||
font-size: 11px;
|
||||
color: var(--theme-text-soft);
|
||||
}
|
||||
.adminUiScope .customItemModal__body {
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
@@ -4320,11 +4314,17 @@ function userAvatarFallback(user) {
|
||||
width: min(560px, 100%);
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
padding: 20px;
|
||||
border-radius: 24px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.12);
|
||||
background: color-mix(in srgb, var(--theme-main-bg) 96%, transparent);
|
||||
}
|
||||
.adminUiScope .modalCard:not(.modalCard--customItem) {
|
||||
padding: 20px;
|
||||
}
|
||||
.adminUiScope .modalCard.modalCard--customItem {
|
||||
gap: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.adminUiScope .modalCard--preview {
|
||||
width: min(1200px, 100%);
|
||||
max-height: calc(100dvh - 40px);
|
||||
|
||||
Reference in New Issue
Block a user