Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
73 lines
6.1 KiB
JavaScript
73 lines
6.1 KiB
JavaScript
'use strict';
|
|
/* ============================================================================
|
|
* 관리 탭 오른쪽 "사이트 관리 창" (v1.4.14, 요구 2)
|
|
*
|
|
* 관리 탭을 고르면 오른쪽 미리보기(iframe·소스 편집기) 대신 이 창이 보인다. 두 가지 보기:
|
|
* - 사이트 관리자 : 사이트 관리자 페이지(/site-admin/<ID>/?embed=1)를 iframe 으로 — 회원·게시판·문의·예약·갤러리 등
|
|
* 모듈 데이터와 사이트 관리자 계정을 여기서 바로 다룬다. 빌더 소유자 세션으로 자동 로그인된다(embed 모드).
|
|
* - 사이트 현황 : 접속 통계(오늘·7일·누적)·네트워크·저장 공간, 문의 접수 건수, 켜진 모듈, 메일, 배포·발행 상태,
|
|
* 수정 횟수, 버전 수, 사용 캐시를 한 화면에 요약한다. 자료는 app.js 가 이미 받아 둔 것(statsData·current)과
|
|
* 문의 목록 응답을 그대로 쓰고, 모듈 상태만 /api/sites/<ID>/modules 로 받는다.
|
|
*
|
|
* app.js 와의 연결점(전역): current(현재 사이트), statsData(접속 통계), krwFmt/fmt/fmtBytes(표시), T/TF(조각 번역), api().
|
|
* - ManageUI.show(site) : 관리 탭이 보일 때 — iframe 을 (아직 안 열었으면) 열고 현황을 그린다
|
|
* - ManageUI.onSiteOpened(site): 사이트가 바뀌면 iframe 주소를 바꾸고(관리 탭이 보일 때만 바로 로드) 현황을 다시 그린다
|
|
* - ManageUI.onStats(st) / onInquiries(r): 통계·문의 자료가 갱신되면 현황 숫자만 다시 그린다
|
|
* ========================================================================== */
|
|
(() => {
|
|
const el = (tag, cls, text) => { const e = document.createElement(tag); if (cls) e.className = cls; if (text !== undefined) e.textContent = text; return e; };
|
|
let view = 'admin'; // 'admin' | 'info' — 마지막으로 고른 보기 (localStorage 에 기억). v1.7.2: 'status'(현황) 는 '사이트 정보'(info) 페이지로 합쳐졌다
|
|
let frameSiteId = null; // iframe 에 지금 열려 있는 사이트 ID (사이트가 바뀌었을 때만 다시 로드)
|
|
let inquiries = null; // 마지막 문의 목록 응답 (renderInquiries 가 넘겨 준다)
|
|
let modules = null; // { enabled, counts, catalog } — 모듈 상태 (사이트마다 한 번 받는다)
|
|
let modulesFor = null; // modules 를 받은 사이트 ID
|
|
try { view = ['status', 'info'].includes(localStorage.getItem('manageView')) ? 'info' : 'admin'; } catch (_) {}
|
|
|
|
/** 지금 관리 탭이 화면에 보이는지 (보이지 않을 때는 iframe 을 미리 로드하지 않아 불필요한 요청을 막는다) */
|
|
const visible = () => !$('manageView').classList.contains('hidden');
|
|
|
|
/** 보기 전환 버튼 상태와 본문(iframe / 현황 / 빈 안내) 표시 */
|
|
function layout() {
|
|
const site = current;
|
|
$('mvTabAdmin').classList.toggle('active', view === 'admin'); $('mvTabStatus').classList.toggle('active', view === 'info');
|
|
$('mvEmpty').classList.toggle('hidden', !!site);
|
|
$('mvAdminFrame').classList.toggle('hidden', !site || view !== 'admin');
|
|
$('mvStatus').classList.toggle('hidden', !site || view !== 'info');
|
|
$('mvReload').disabled = !site; $('mvOpen').classList.toggle('disabled', !site);
|
|
$('mvTitle').textContent = site ? `${T('사이트 관리')} · ${site.title}` : T('사이트 관리');
|
|
if (site) $('mvOpen').href = view === 'admin' ? `/site-admin/${site.id}/` : (site.liveUrl || site.url);
|
|
}
|
|
/** 사이트 관리자 페이지 iframe 로드 (사이트가 바뀌었거나 강제 새로고침일 때만) */
|
|
function loadFrame(force) {
|
|
const site = current; const f = $('mvAdminFrame'); if (!site) { f.removeAttribute('src'); frameSiteId = null; return; }
|
|
if (!force && frameSiteId === site.id && f.getAttribute('src')) return;
|
|
frameSiteId = site.id; f.src = `/site-admin/${site.id}/?embed=1`;
|
|
}
|
|
/** 모듈 상태를 받아 현황에 쓴다 (사이트마다 한 번, 새로고침 때 다시) */
|
|
async function loadModules(force) {
|
|
const site = current; if (!site) { modules = null; modulesFor = null; return; }
|
|
if (!force && modulesFor === site.id && modules) return;
|
|
try { modules = await api(`/api/sites/${site.id}/modules`); modulesFor = site.id; } catch (_) { modules = null; modulesFor = site.id; }
|
|
}
|
|
|
|
/**
|
|
* 사이트 정보 페이지 (v1.7.2 요구 2): 그리기는 public/site-info.js 가 맡는다 — 상태 타일·접속 통계 그래프·네트워크 선/막대 그래프·디스크 사용량·페이지/유입.
|
|
* 1.6.40 까지의 "사이트 현황" 요약은 이 페이지의 맨 위 타일로 들어갔다.
|
|
*/
|
|
function renderStatus() { const root = $('mvStatus'); if (!current) { root.innerHTML = ''; return; } if (window.SiteInfoUI) SiteInfoUI.render(root, { site: current, stats: typeof statsData !== 'undefined' ? statsData : null, inquiries, modules }); }
|
|
|
|
function show(site) { layout(); if (!site) return; if (view === 'admin') loadFrame(false); else { loadModules(false).then(renderStatus); renderStatus(); } }
|
|
function setView(v) { view = v; try { localStorage.setItem('manageView', v); } catch (_) {} show(current); }
|
|
$('mvTabAdmin').onclick = () => setView('admin'); $('mvTabStatus').onclick = () => setView('info');
|
|
$('mvReload').onclick = () => { if (!current) return; if (view === 'admin') loadFrame(true); else { loadModules(true).then(renderStatus); if (typeof loadStats === 'function') loadStats(); if (typeof renderInquiries === 'function') renderInquiries(); } };
|
|
|
|
window.ManageUI = {
|
|
show,
|
|
onSiteOpened(site) { if (!site || site.id !== frameSiteId) { frameSiteId = null; $('mvAdminFrame').removeAttribute('src'); } if (!site || site.id !== modulesFor) { modules = null; modulesFor = null; inquiries = null; } if (visible()) show(site); else layout(); },
|
|
onStats() { if (visible() && view === 'info') renderStatus(); },
|
|
onInquiries(r) { inquiries = r; if (visible() && view === 'info') renderStatus(); },
|
|
/** v1.7.2: 가운데 칸의 "사이트 정보" 요약 카드에서 '자세히 보기' → 운영 화면 + 사이트 정보 페이지 */
|
|
openInfo() { setView('info'); },
|
|
};
|
|
})();
|