Files
AriWeb-Suite/modules/webmaker/public/import.js

75 lines
7.4 KiB
JavaScript

'use strict';
// 기존 사이트로 시작하기
// - 사이트 복사하기(v1.2.0~): 웹 주소만 입력 → 서버가 웹으로 접속해 화면(HTML·CSS·JS·이미지)만 복사해 새 사이트로 만든다.
// 기능(로그인·게시판·신청·결제 등 서버 프로그램)은 복사하지 않는다. 기존 사이트의 모양을 최대한 살려 새 사이트를 만들 때 쓴다.
// - 사이트 관리하기(서버 접속으로 가져오기)는 v1.3.4 에서 새로 시작하는 기능을 없앴다(사용자 요청).
// 이미 가져온 사이트는 관리 탭의 "원본 서버 반영" 카드(onSiteOpened)로 계속 수정·반영할 수 있다.
(() => {
// v1.3.4: "사이트 관리하기(서버 접속으로 가져오기)" 새로 시작하기는 없앴다. 이전에 가져온 사이트의 반영 카드(아래 onSiteOpened)는 그대로 동작한다.
const el = (tag, cls, text) => { const e = document.createElement(tag); if (cls) e.className = cls; if (text !== undefined) e.textContent = text; return e; };
// ---------- 사이트 복사하기 (v1.2.0): 웹 주소만으로 화면 코드(HTML·CSS·JS·이미지)를 복사 ----------
function showCopyStart() { $('copyStartCard').classList.remove('hidden'); $('cpStart').disabled = false; setTimeout(() => $('cpUrl').focus(), 0); }
$('cpStart').onclick = async () => {
let url = $('cpUrl').value.trim(); if (!url) return alert('복사할 사이트 주소를 입력하세요.');
if (!/^https?:\/\//i.test(url)) url = 'https://' + url; // "example.com" 처럼 입력해도 https 로 시도
$('cpStart').disabled = true;
try {
const site = await api('/api/sites/copy', { method: 'POST', body: JSON.stringify({ url, title: $('cpTitle').value.trim(), contactEmail: $('cpEmail').value.trim(), tier: $('tierSelect').value || '', optimize: seoOptsOf('copyStartCard') }) });
$('cpUrl').value = ''; $('cpTitle').value = ''; $('cpEmail').value = '';
await openSite(site.id); await refreshSiteList();
} catch (e) { alert('복사 시작 실패: ' + e.message); $('cpStart').disabled = false; }
};
// ---------- 가져온 사이트: 반영(배포) 카드 ----------
function onSiteOpened(site) {
const card = $('importCard');
if (!site || site.mode !== 'import' || !site.source) { card.classList.add('hidden'); return; }
card.classList.remove('hidden'); $('imCredsBox').classList.add('hidden');
const s = site.source; const last = site.deploy && site.deploy.last;
const importing = site.status === 'importing' || (site.running && !s.importedAt);
const pill = $('imState');
if (importing) { pill.textContent = '가져오는 중'; pill.className = 'pill running'; }
else if (!s.importedAt) { pill.textContent = site.importError ? '가져오기 실패' : '가져오기 전'; pill.className = 'pill ' + (site.importError ? 'error' : 'idle'); }
else if (last && last.ok && s.lastPushAt && (!site.versions || site.versions.length <= 1)) { pill.textContent = '반영 완료'; pill.className = 'pill done'; }
else { pill.textContent = '반영 대기'; pill.className = 'pill idle'; }
const info = $('imInfo'); info.innerHTML = '';
const lines = [
`원본: ${s.url ? s.url + ' · ' : ''}${s.type === 'ssh' ? 'SSH 키' : (s.protocol === 'ftp' ? 'FTP' : 'SSH/SFTP 비밀번호')} · ${s.user}@${s.host}:${s.port} · 경로 ${s.docroot}${s.shell === false ? ' · 파일 전송 방식' : ''}`,
s.importedAt ? `가져옴: ${new Date(s.importedAt).toLocaleString(uiLocale())} · 파일 ${s.fileCount}개${site.importInfo && site.importInfo.dynamic ? ' · 서버 스크립트 포함(PHP 등)' : ''}` : (site.importError ? `가져오기 실패: ${site.importError}` : '가져오기 진행 중…'),
s.lastPushAt ? `마지막 반영: ${new Date(s.lastPushAt).toLocaleString(uiLocale())}${s.backupNote ? ' · ' + s.backupNote : ''}` : '아직 원본 서버에 반영한 적이 없습니다.',
];
for (const l of lines) info.appendChild(el('div', '', l));
if (site.importError && !s.importedAt) { const b = el('button', 'ghost small-btn', '다시 가져오기'); b.onclick = () => reimport(false); info.appendChild(b); }
$('imBtnDeploy').disabled = importing || !s.importedAt || !!site.running;
const msg = $('imDeployMsg'); msg.className = 'small'; msg.textContent = '';
if (last) { msg.className = 'small ' + (last.ok ? 'ok' : 'fail'); msg.textContent = `${new Date(last.at).toLocaleString(uiLocale())} ${last.ok ? '반영 완료' : '반영 실패'} — ${last.detail || ''}`; const acc = (last.access && last.access.items) || []; for (const it of acc) { const d = el('div', ''); const a = el('a'); a.href = it.url; a.target = '_blank'; a.rel = 'noopener'; a.textContent = it.url; d.appendChild(a); d.appendChild(document.createTextNode(` — ${it.ok ? it.note : '접속 불가: ' + it.note}`)); msg.appendChild(d); } }
$('imcUser').value = s.user; $('imcPort').value = s.port; $('imcDocroot').value = s.docroot; $('imcUrl').value = s.url || ''; $('imcPw').value = ''; $('imcPw').parentElement.classList.toggle('hidden', s.type !== 'password'); $('imcMsg').textContent = '';
}
async function reimport(force) {
try { await api(`/api/sites/${current.id}/reimport`, { method: 'POST', body: JSON.stringify({ force }) }); setStatus('running', '기존 사이트 가져오기'); }
catch (e) { alert(e.message); }
}
$('imBtnDeploy').onclick = async () => {
if (!current || !current.source) return;
const first = !((current.deploy && current.deploy.history) || []).some((d) => d.ok);
const s = current.source;
if (!confirm(`${first ? '처음으로 ' : ''}수정 내용을 원본 서버에 반영합니다.\n\n서버: ${s.user}@${s.host}:${s.port}\n경로: ${s.docroot}\n${s.url ? '주소: ' + s.url + '\n' : ''}\n서버의 같은 이름 파일이 덮어써집니다${s.type !== 'password' || s.protocol !== 'ftp' ? ' (반영 전 서버에 백업을 만듭니다)' : ''}. 계속할까요?`)) return;
$('imBtnDeploy').disabled = true; $('imDeployMsg').className = 'small'; $('imDeployMsg').textContent = '반영 중… 아래 "진행 상태" 상자에서 단계와 결과를 확인할 수 있습니다.';
try { const r = await api(`/api/sites/${current.id}/deploy`, { method: 'POST', body: '{}' }); if (r.site) { current = r.site; renderGit(current); } onSiteOpened(current); }
catch (e) { $('imDeployMsg').className = 'small fail'; $('imDeployMsg').textContent = '반영 실패: ' + e.message; $('imBtnDeploy').disabled = false; try { const s2 = await api(`/api/sites/${current.id}`); current = s2; onSiteOpened(current); } catch (_) {} }
};
$('imBtnCreds').onclick = () => $('imCredsBox').classList.toggle('hidden');
$('imcSave').onclick = async () => {
if (!current) return; $('imcSave').disabled = true; $('imcMsg').textContent = '연결 확인 중…';
try {
const b = { user: $('imcUser').value.trim(), port: $('imcPort').value.trim(), docroot: $('imcDocroot').value.trim(), url: $('imcUrl').value.trim() };
if ($('imcPw').value) b.password = $('imcPw').value;
const r = await api(`/api/sites/${current.id}/source`, { method: 'PUT', body: JSON.stringify(b) });
current.source = r.source; onSiteOpened(current); $('imCredsBox').classList.remove('hidden'); $('imcMsg').textContent = '저장되었습니다 — ' + r.detail;
} catch (e) { $('imcMsg').textContent = e.message; }
$('imcSave').disabled = false;
};
window.Importer = { showCopyStart, onSiteOpened };
})();