dcae228a24
- 모든 관리자 페이지에서 DB 데이터를 서버에서 직접 HTML에 주입 - __INIT__ 글로벌 변수로 초기 데이터 전달 (fetch 불필요) - 대시보드/사이트관리/AdSense/도메인/로그/사이트상세 전부 적용 - trust proxy 설정 (Traefik 뒤 동작) - 저장/삭제/크롤링 등 액션은 여전히 API fetch 사용 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
79 lines
4.5 KiB
Plaintext
79 lines
4.5 KiB
Plaintext
<%- include('layout', { page: 'adsense', pageTitle: 'AdSense 관리', body: `
|
|
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h2>AdSense 설정 목록</h2>
|
|
<button class="btn btn-primary" onclick="openModal()">+ AdSense 추가</button>
|
|
</div>
|
|
<table>
|
|
<thead><tr><th>ID</th><th>이름</th><th>Client ID</th><th>상단 슬롯</th><th>중간 슬롯</th><th>하단 슬롯</th><th>상태</th><th>액션</th></tr></thead>
|
|
<tbody id="ads-tbody"></tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="modal-overlay" id="adsModal">
|
|
<div class="modal">
|
|
<h3 id="ads-modal-title">AdSense 추가</h3>
|
|
<input type="hidden" id="ads-edit-id">
|
|
<div class="form-group"><label>이름 (구분용)</label><input id="ads-name" placeholder="예: 메인사이트 애드센스"></div>
|
|
<div class="form-group"><label>Client ID (ca-pub-XXXX)</label><input id="ads-client" placeholder="ca-pub-1234567890123456"></div>
|
|
<div class="form-row">
|
|
<div class="form-group"><label>상단 광고 슬롯 ID (선택)</label><input id="ads-slot-top" placeholder="비워두면 자동광고"></div>
|
|
<div class="form-group"><label>중간 광고 슬롯 ID (선택)</label><input id="ads-slot-mid" placeholder="비워두면 자동광고"></div>
|
|
</div>
|
|
<div class="form-group"><label>하단 광고 슬롯 ID (선택)</label><input id="ads-slot-bot" placeholder="비워두면 자동광고"></div>
|
|
<div class="flex" style="justify-content:flex-end;gap:.5rem;margin-top:1rem">
|
|
<button class="btn btn-outline" onclick="closeModal()">취소</button>
|
|
<button class="btn btn-primary" onclick="saveAds()">저장</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
var adsList = Array.isArray(__INIT__) ? __INIT__ : [];
|
|
|
|
function renderAds(){
|
|
document.getElementById('ads-tbody').innerHTML = adsList.map(function(a){
|
|
var slots=a.slots||{};
|
|
return '<tr><td>'+a.id+'</td><td><strong>'+a.name+'</strong></td><td class="text-muted">'+a.client_id+'</td>'+
|
|
'<td>'+(slots.top||'-')+'</td><td>'+(slots.middle||'-')+'</td><td>'+(slots.bottom||'-')+'</td>'+
|
|
'<td><span class="badge badge-'+(a.is_active?'success">활성':'danger">비활성')+'</span></td>'+
|
|
'<td class="flex"><button class="btn btn-outline btn-sm" onclick="editAds('+a.id+')">수정</button>'+
|
|
'<button class="btn btn-danger btn-sm" onclick="deleteAds('+a.id+')">삭제</button></td></tr>';
|
|
}).join('') || '<tr><td colspan="8" class="text-muted" style="text-align:center;padding:2rem">AdSense 설정을 추가하세요</td></tr>';
|
|
}
|
|
renderAds();
|
|
|
|
async function reloadAds(){var d=await api('GET','/api/adsense');if(d&&d.length!==undefined)adsList=d;renderAds();}
|
|
|
|
function openModal(){
|
|
document.getElementById('ads-modal-title').textContent='AdSense 추가';
|
|
document.getElementById('ads-edit-id').value='';
|
|
['ads-name','ads-client','ads-slot-top','ads-slot-mid','ads-slot-bot'].forEach(function(id){document.getElementById(id).value='';});
|
|
document.getElementById('adsModal').classList.add('active');
|
|
}
|
|
function editAds(id){
|
|
var a=adsList.find(function(x){return x.id===id});if(!a)return;
|
|
document.getElementById('ads-modal-title').textContent='AdSense 수정';
|
|
document.getElementById('ads-edit-id').value=a.id;
|
|
document.getElementById('ads-name').value=a.name;
|
|
document.getElementById('ads-client').value=a.client_id;
|
|
document.getElementById('ads-slot-top').value=(a.slots&&a.slots.top)||'';
|
|
document.getElementById('ads-slot-mid').value=(a.slots&&a.slots.middle)||'';
|
|
document.getElementById('ads-slot-bot').value=(a.slots&&a.slots.bottom)||'';
|
|
document.getElementById('adsModal').classList.add('active');
|
|
}
|
|
function closeModal(){document.getElementById('adsModal').classList.remove('active');}
|
|
async function saveAds(){
|
|
var data={name:document.getElementById('ads-name').value,client_id:document.getElementById('ads-client').value,
|
|
slots:{top:document.getElementById('ads-slot-top').value,middle:document.getElementById('ads-slot-mid').value,bottom:document.getElementById('ads-slot-bot').value},is_active:true};
|
|
if(!data.name||!data.client_id){toast('이름과 Client ID는 필수','error');return;}
|
|
var editId=document.getElementById('ads-edit-id').value;
|
|
if(editId){await api('PUT','/api/adsense/'+editId,data);toast('수정 완료');}
|
|
else{await api('POST','/api/adsense',data);toast('추가 완료');}
|
|
closeModal();await reloadAds();
|
|
}
|
|
async function deleteAds(id){if(!confirm('삭제하시겠습니까?'))return;await api('DELETE','/api/adsense/'+id);toast('삭제 완료');await reloadAds();}
|
|
</script>
|
|
` }) %>
|