사이트 코드와 홈페이지 위젯 추가 v1.5.34
This commit is contained in:
@@ -17,6 +17,7 @@ const savingPost = ref(false)
|
||||
const savingHomeCover = ref(false)
|
||||
const savingAnnouncement = ref(false)
|
||||
const savingSpam = ref(false)
|
||||
const savingSiteCode = ref(false)
|
||||
const uploadingLogo = ref(false)
|
||||
const uploadingHomeCover = ref(false)
|
||||
const uploadingHomeCoverDark = ref(false)
|
||||
@@ -59,6 +60,8 @@ const editHomeCover = ref(false)
|
||||
const customizeAnnouncement = ref(false)
|
||||
/** 스팸 필터 카드 편집 모드 여부 */
|
||||
const editSpam = ref(false)
|
||||
/** 사이트 코드 카드 편집 모드 여부 */
|
||||
const editSiteCode = ref(false)
|
||||
/** 편집 시작 시점의 제목·설명(취소 시 복원용) */
|
||||
const titleDescSnapshot = reactive({
|
||||
title: '',
|
||||
@@ -94,6 +97,12 @@ const announcementSnapshot = reactive({
|
||||
const spamSnapshot = reactive({
|
||||
signupBlockedUsernames: []
|
||||
})
|
||||
/** 편집 시작 시점의 사이트 코드(취소 시 복원용) */
|
||||
const siteCodeSnapshot = reactive({
|
||||
adsTxt: '',
|
||||
customHeadCode: '',
|
||||
customFooterCode: ''
|
||||
})
|
||||
let toastTimer = null
|
||||
let scrollSpyFrame = null
|
||||
let postExportRefreshTimer = null
|
||||
@@ -123,7 +132,10 @@ const form = reactive({
|
||||
announcementText: settings.value?.announcementText || '',
|
||||
announcementUrl: settings.value?.announcementUrl || '',
|
||||
announcementBackgroundColor: settings.value?.announcementBackgroundColor || '#15171a',
|
||||
signupBlockedUsernames: normalizeSignupBlockedUsernames(settings.value?.signupBlockedUsernames)
|
||||
signupBlockedUsernames: normalizeSignupBlockedUsernames(settings.value?.signupBlockedUsernames),
|
||||
adsTxt: settings.value?.adsTxt || '',
|
||||
customHeadCode: settings.value?.customHeadCode || '',
|
||||
customFooterCode: settings.value?.customFooterCode || ''
|
||||
})
|
||||
|
||||
/**
|
||||
@@ -183,6 +195,16 @@ const hasAnnouncementChanges = computed(() => customizeAnnouncement.value && (
|
||||
const hasSpamChanges = computed(() => editSpam.value
|
||||
&& JSON.stringify(form.signupBlockedUsernames) !== JSON.stringify(spamSnapshot.signupBlockedUsernames))
|
||||
|
||||
/**
|
||||
* 사이트 코드 변경 여부
|
||||
* @returns {boolean} 변경 여부
|
||||
*/
|
||||
const hasSiteCodeChanges = computed(() => editSiteCode.value && (
|
||||
form.adsTxt !== siteCodeSnapshot.adsTxt
|
||||
|| form.customHeadCode !== siteCodeSnapshot.customHeadCode
|
||||
|| form.customFooterCode !== siteCodeSnapshot.customFooterCode
|
||||
))
|
||||
|
||||
/**
|
||||
* 최신 게시물 export 작업 목록
|
||||
* @returns {Array} export 작업 목록
|
||||
@@ -449,7 +471,8 @@ const settingsNavGroups = [
|
||||
heading: '사이트',
|
||||
items: [
|
||||
{ id: 'admin-settings-section-home-cover', label: '메인 화면', keywords: 'home cover hero banner image', iconId: 'home-cover' },
|
||||
{ id: 'admin-settings-section-announcement', label: '어나운스 바', keywords: 'announcement banner notice', iconId: 'announcement' }
|
||||
{ id: 'admin-settings-section-announcement', label: '어나운스 바', keywords: 'announcement banner notice', iconId: 'announcement' },
|
||||
{ id: 'admin-settings-section-site-code', label: '사이트 코드', keywords: 'ads ads.txt head footer script code adsense', iconId: 'site-code' }
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -733,6 +756,16 @@ const getSelectedPostExportFileIds = (jobId) => Array.isArray(selectedPostExport
|
||||
*/
|
||||
const isPostExportFileSelected = (job, file) => getSelectedPostExportFileIds(job?.id).includes(file?.id)
|
||||
|
||||
/**
|
||||
* Export 파일 선택 비활성 여부를 확인한다.
|
||||
* @param {Object} job - Export 작업
|
||||
* @param {Object} file - Export 파일
|
||||
* @returns {boolean} 비활성 여부
|
||||
*/
|
||||
const isPostExportFileSelectionDisabled = (job, file) => file.status !== 'ready'
|
||||
|| !file.filePath
|
||||
|| isDownloadingPostExportJob(job.id)
|
||||
|
||||
/**
|
||||
* Export 파일 선택 상태를 변경한다.
|
||||
* @param {Object} job - Export 작업
|
||||
@@ -756,6 +789,16 @@ const setPostExportFileSelected = (job, file, selected) => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export 파일 선택 상태를 반대로 전환한다.
|
||||
* @param {Object} job - Export 작업
|
||||
* @param {Object} file - Export 파일
|
||||
* @returns {void}
|
||||
*/
|
||||
const togglePostExportFileSelection = (job, file) => {
|
||||
setPostExportFileSelected(job, file, !isPostExportFileSelected(job, file))
|
||||
}
|
||||
|
||||
/**
|
||||
* Export 작업에서 선택된 다운로드 가능 파일을 가져온다.
|
||||
* @param {Object} job - Export 작업
|
||||
@@ -1003,7 +1046,10 @@ const buildSiteSettingsPayload = () => ({
|
||||
announcementText: form.announcementText || '',
|
||||
announcementUrl: form.announcementUrl || '',
|
||||
announcementBackgroundColor: form.announcementBackgroundColor || '#15171a',
|
||||
signupBlockedUsernames: normalizeSignupBlockedUsernames(form.signupBlockedUsernames)
|
||||
signupBlockedUsernames: normalizeSignupBlockedUsernames(form.signupBlockedUsernames),
|
||||
adsTxt: form.adsTxt || '',
|
||||
customHeadCode: form.customHeadCode || '',
|
||||
customFooterCode: form.customFooterCode || ''
|
||||
})
|
||||
|
||||
/**
|
||||
@@ -1408,6 +1454,50 @@ const saveSpamSection = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 사이트 코드 편집 모드 진입
|
||||
* @returns {void}
|
||||
*/
|
||||
const beginEditSiteCode = () => {
|
||||
siteCodeSnapshot.adsTxt = form.adsTxt
|
||||
siteCodeSnapshot.customHeadCode = form.customHeadCode
|
||||
siteCodeSnapshot.customFooterCode = form.customFooterCode
|
||||
editSiteCode.value = true
|
||||
}
|
||||
|
||||
/**
|
||||
* 사이트 코드 편집 취소
|
||||
* @returns {void}
|
||||
*/
|
||||
const cancelEditSiteCode = () => {
|
||||
form.adsTxt = siteCodeSnapshot.adsTxt
|
||||
form.customHeadCode = siteCodeSnapshot.customHeadCode
|
||||
form.customFooterCode = siteCodeSnapshot.customFooterCode
|
||||
editSiteCode.value = false
|
||||
}
|
||||
|
||||
/**
|
||||
* 사이트 코드 저장
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const saveSiteCodeSection = async () => {
|
||||
if (!hasSiteCodeChanges.value) {
|
||||
return
|
||||
}
|
||||
|
||||
const ok = await persistSiteSettings({
|
||||
successToast: '사이트 코드 설정이 저장되었습니다.',
|
||||
savingFlag: savingSiteCode
|
||||
})
|
||||
|
||||
if (ok) {
|
||||
siteCodeSnapshot.adsTxt = form.adsTxt
|
||||
siteCodeSnapshot.customHeadCode = form.customHeadCode
|
||||
siteCodeSnapshot.customFooterCode = form.customFooterCode
|
||||
editSiteCode.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Escape 키: 제목·설명 편집 중이면 취소, 아니면 설정 화면 닫기
|
||||
* @param {KeyboardEvent} event - 키보드 이벤트
|
||||
@@ -1447,6 +1537,11 @@ const onGlobalKeydown = (event) => {
|
||||
cancelEditSpam()
|
||||
return
|
||||
}
|
||||
if (editSiteCode.value) {
|
||||
event.preventDefault()
|
||||
cancelEditSiteCode()
|
||||
return
|
||||
}
|
||||
closeSettings()
|
||||
}
|
||||
|
||||
@@ -2340,6 +2435,16 @@ onBeforeUnmount(() => {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<AdminSiteCodeSettingsCard
|
||||
:form="form"
|
||||
:editing="editSiteCode"
|
||||
:saving="savingSiteCode"
|
||||
:has-changes="hasSiteCodeChanges"
|
||||
@begin="beginEditSiteCode"
|
||||
@cancel="cancelEditSiteCode"
|
||||
@save="saveSiteCodeSection"
|
||||
/>
|
||||
|
||||
<h2 class="admin-settings-screen__section-heading z-20 mb-px pt-10 text-2xl font-bold tracking-tight text-[#15171a]">
|
||||
콘텐츠·안전
|
||||
</h2>
|
||||
@@ -2614,7 +2719,7 @@ onBeforeUnmount(() => {
|
||||
:checked="areAllReadyPostExportFilesSelected(job)"
|
||||
:disabled="getReadyPostExportFiles(job).length === 0 || isDownloadingPostExportJob(job.id)"
|
||||
@change="toggleAllPostExportFiles(job)"
|
||||
>
|
||||
/>
|
||||
전체 선택
|
||||
</label>
|
||||
<button
|
||||
@@ -2626,34 +2731,14 @@ onBeforeUnmount(() => {
|
||||
{{ isDownloadingPostExportJob(job.id) ? '다운로드 중' : `선택 파일 다운로드 ${getSelectedReadyPostExportFiles(job).length || ''}` }}
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
<AdminPostExportFileRow
|
||||
v-for="file in job.files"
|
||||
:key="file.id"
|
||||
class="grid grid-cols-[auto_minmax(0,1fr)_auto] items-center gap-3 border-b border-[#edf0f3] px-3 py-2 last:border-b-0"
|
||||
>
|
||||
<input
|
||||
class="size-4 rounded border-[#cfd6de] text-[#15171a] focus:ring-[#15171a] disabled:cursor-not-allowed"
|
||||
type="checkbox"
|
||||
:checked="isPostExportFileSelected(job, file)"
|
||||
:disabled="file.status !== 'ready' || !file.filePath || isDownloadingPostExportJob(job.id)"
|
||||
:aria-label="`${file.fileName} 선택`"
|
||||
@change="setPostExportFileSelected(job, file, $event.target.checked)"
|
||||
>
|
||||
<div class="min-w-0">
|
||||
<p class="truncate text-sm font-medium text-[#15171a]">
|
||||
{{ file.fileName }}
|
||||
</p>
|
||||
<p class="mt-0.5 text-xs text-[#9aa3ad]">
|
||||
{{ file.postStart }}-{{ file.postEnd }}
|
||||
</p>
|
||||
</div>
|
||||
<span
|
||||
v-if="file.status !== 'ready' || !file.filePath"
|
||||
class="inline-flex h-8 items-center justify-center rounded px-2 text-xs font-semibold text-[#a6b0bb]"
|
||||
>
|
||||
{{ file.status === 'processing' ? '생성 중' : file.status === 'failed' ? '실패' : '다운로드 대기' }}
|
||||
</span>
|
||||
</div>
|
||||
:file="file"
|
||||
:selected="isPostExportFileSelected(job, file)"
|
||||
:disabled="isPostExportFileSelectionDisabled(job, file)"
|
||||
@toggle="togglePostExportFileSelection(job, file)"
|
||||
/>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user