devportal2 / static /js /projects.js
Akay Borana
Complete Android-first UI rebuild with mobile-first design system
81552f4
Raw
History Blame Contribute Delete
5.84 kB
// static/js/projects.js v7
async function loadPublishedProjects() {
if (!currentToken) return;
try {
var res = await fetch('/api/projects', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({token: currentToken}) });
var data = await res.json();
var grid = document.getElementById('projects-grid');
if (!grid) return;
grid.innerHTML = '';
if (data.projects && data.projects.length) {
data.projects.forEach(function(p) {
var card = document.createElement('div');
card.style.cssText = 'background:var(--bg-elevated);border:1px solid var(--border);border-radius:var(--r-lg);padding:var(--sp-4);display:flex;flex-direction:column;gap:var(--sp-3)';
var date = new Date(p.created_at).toLocaleDateString();
var url = location.origin + p.url;
card.innerHTML = '<div style="display:flex;justify-content:space-between;align-items:center"><h3 style="font-size:15px;font-weight:600;color:var(--accent);margin:0">' + p.name + '</h3><span style="font-size:11px;color:var(--text-3)">' + date + '</span></div><div style="font-size:12px;color:var(--text-2);background:rgba(255,255,255,0.03);padding:8px;border-radius:var(--r-sm);word-break:break-all"><a href="' + url + '" target="_blank" style="color:var(--info);text-decoration:none">' + url + '</a></div><div style="display:flex;gap:var(--sp-2)"><button class="ed-btn" onclick="window.open(\'' + url + '\',\'_blank\')" style="flex:1;justify-content:center"><i class="fa-solid fa-external-link"></i> Visit</button><button class="ed-btn success" onclick="publishCurrentWorkspace(\'' + p.name + '\',\'' + p.id + '\')" style="flex:1;justify-content:center"><i class="fa-solid fa-rotate"></i> Update</button></div>';
grid.appendChild(card);
});
} else {
grid.innerHTML = '<div style="text-align:center;color:var(--text-3);padding:var(--sp-8);background:var(--bg-elevated);border-radius:var(--r-lg);border:1px solid var(--border)"><i class="fa-solid fa-box-open" style="font-size:2rem;margin-bottom:var(--sp-3);opacity:0.4"></i><p>No projects yet</p><p style="font-size:12px">Tap Publish to deploy your code</p></div>';
}
} catch (e) { showToast('Error loading projects', 'error'); }
}
var publishingProjectID = null;
async function publishCurrentWorkspace(existingName, existingId) {
publishingProjectID = existingId || null;
var modal = document.getElementById('publish-modal');
modal.style.display = 'flex';
document.getElementById('publish-project-name').value = existingName || '';
var list = document.getElementById('publish-file-list');
list.innerHTML = '<i class="fa-solid fa-spinner fa-spin"></i> Loading...';
try {
var wsRes = await fetch('/api/files', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({token: currentToken}) });
var wsData = await wsRes.json();
var prev = [];
if (existingId) {
var pubRes = await fetch('/api/project/files', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({token: currentToken, project_id: existingId}) });
var pubData = await pubRes.json();
if (pubData.files) prev = pubData.files;
}
list.innerHTML = '';
if (wsData.files && wsData.files.length) {
wsData.files.forEach(function(f) {
var lbl = document.createElement('label');
lbl.style.cssText = 'display:flex;align-items:center;gap:8px;color:var(--text-1);cursor:pointer;font-size:13px;font-family:var(--font-mono);min-height:var(--touch-min)';
var cb = document.createElement('input');
cb.type = 'checkbox'; cb.value = f; cb.className = 'publish-cb';
if (!existingId || prev.includes(f)) cb.checked = true;
lbl.appendChild(cb);
lbl.appendChild(document.createTextNode(f));
list.appendChild(lbl);
});
} else { list.innerHTML = '<span style="color:var(--error)">Workspace is empty</span>'; }
} catch (e) { list.innerHTML = '<span style="color:var(--error)">Failed to load files</span>'; }
}
function closePublishModal() {
document.getElementById('publish-modal').style.display = 'none';
}
async function confirmPublish() {
var name = document.getElementById('publish-project-name').value.trim();
if (!name) { showToast('Enter project name', 'warning'); return; }
var checks = document.querySelectorAll('.publish-cb');
var files = Array.from(checks).filter(function(c) { return c.checked; }).map(function(c) { return c.value; });
if (!files.length) { showToast('Select at least one file', 'warning'); return; }
var htmlFiles = files.filter(function(f) { return f.endsWith('.html'); });
var mainHtml = htmlFiles.includes('index.html') ? 'index.html' : (htmlFiles[0] || 'index.html');
var btn = document.getElementById('publish-confirm-btn');
btn.innerHTML = '<i class="fa-solid fa-spinner fa-spin"></i> Publishing...';
btn.disabled = true;
try {
var res = await fetch('/api/publish', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({ token: currentToken, project_name: name, project_id: publishingProjectID, files: files, main_html_file: mainHtml }) });
var data = await res.json();
if (data.success) { showToast('Published!', 'success'); closePublishModal(); loadPublishedProjects(); }
else showToast(data.error || 'Failed', 'error');
} catch (e) { showToast('Network error', 'error'); }
btn.innerHTML = '<i class="fa-solid fa-cloud-arrow-up"></i> Publish';
btn.disabled = false;
}