simplify extension ui
This commit is contained in:
@@ -2,7 +2,7 @@ import * as vscode from 'vscode';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as cp from 'child_process';
|
||||
import { singletonPanel } from './shared';
|
||||
import { getToolWebviewStyles, singletonPanel } from './shared';
|
||||
|
||||
const store: { panel: vscode.WebviewPanel | null } = { panel: null };
|
||||
|
||||
@@ -324,119 +324,98 @@ function getHtml(): string {
|
||||
];
|
||||
|
||||
const checkboxRows = networks.map(n => `
|
||||
<label class="net-row">
|
||||
<input type="checkbox" class="net-cb" data-tag="${n.tag}" checked />
|
||||
<span class="net-label">${n.label} <span class="net-tag">${n.tag}</span></span>
|
||||
<span class="net-note">${n.note}</span>
|
||||
</label>`).join('');
|
||||
<tr>
|
||||
<td style="width:70px;"><input type="checkbox" class="net-cb" data-tag="${n.tag}"${n.tag === 'tt' ? '' : ' checked'} /></td>
|
||||
<td style="width:160px;"><span class="net-label">${n.label}</span> <span class="net-tag">${n.tag}</span></td>
|
||||
<td><span class="net-note">${n.note}</span></td>
|
||||
</tr>`).join('');
|
||||
|
||||
return `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<style>
|
||||
body { font-family: var(--vscode-font-family); color: var(--vscode-foreground); padding: 12px 10px; font-size: 13px; }
|
||||
h2 { font-size: 14px; margin: 0 0 14px 0; font-weight: 600; }
|
||||
.section { margin-bottom: 14px; }
|
||||
.section-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px; opacity: 0.65; margin-bottom: 5px; }
|
||||
.row { display: flex; gap: 6px; align-items: center; }
|
||||
input[type=text] {
|
||||
flex: 1; padding: 4px 7px;
|
||||
background: var(--vscode-input-background);
|
||||
color: var(--vscode-input-foreground);
|
||||
border: 1px solid var(--vscode-input-border, #555);
|
||||
border-radius: 2px; font-size: 12px;
|
||||
}
|
||||
button {
|
||||
padding: 4px 10px; cursor: pointer; font-size: 12px; border-radius: 2px;
|
||||
background: var(--vscode-button-secondaryBackground);
|
||||
color: var(--vscode-button-secondaryForeground);
|
||||
border: 1px solid var(--vscode-panel-border, #444);
|
||||
}
|
||||
button:hover { background: var(--vscode-button-secondaryHoverBackground); }
|
||||
button.primary {
|
||||
background: var(--vscode-button-background);
|
||||
color: var(--vscode-button-foreground);
|
||||
border: none; padding: 6px 18px; font-size: 13px;
|
||||
}
|
||||
button.primary:hover { background: var(--vscode-button-hoverBackground); }
|
||||
button:disabled { opacity: 0.45; cursor: default; }
|
||||
.net-grid { display: flex; flex-direction: column; gap: 4px; }
|
||||
.net-row { display: flex; align-items: center; gap: 8px; padding: 3px 0; cursor: pointer; user-select: none; }
|
||||
${getToolWebviewStyles()}
|
||||
.net-label { min-width: 100px; font-weight: 500; }
|
||||
.net-tag { font-size: 10px; opacity: 0.6; font-weight: 400; }
|
||||
.net-note { font-size: 11px; opacity: 0.6; }
|
||||
.toggle-row { display: flex; gap: 8px; margin-bottom: 6px; }
|
||||
.toggle-row button { font-size: 11px; padding: 2px 8px; }
|
||||
.actions { display: flex; gap: 10px; align-items: center; margin-top: 16px; }
|
||||
#status { margin-top: 12px; font-size: 12px; opacity: 0.75; min-height: 16px; }
|
||||
.results { margin-top: 10px; display: flex; flex-direction: column; gap: 3px; }
|
||||
.res-row { display: flex; align-items: center; gap: 8px; font-size: 12px; font-family: var(--vscode-editor-font-family); }
|
||||
.mark { font-weight: bold; width: 14px; flex-shrink: 0; }
|
||||
.ok { color: #3fb950; }
|
||||
.bad { color: #f85149; }
|
||||
.res-net { min-width: 70px; font-weight: 500; }
|
||||
.res-file { opacity: 0.65; word-break: break-all; }
|
||||
.res-err { color: #f85149; opacity: 0.9; }
|
||||
hr { border: none; border-top: 1px solid var(--vscode-panel-border, #444); margin: 14px 0; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Playworks Converter</h2>
|
||||
<main class="tool-page">
|
||||
<header class="tool-header">
|
||||
<h2 class="tool-title">Playworks Converter</h2>
|
||||
<p class="tool-description">Convert a Playworks HTML export into network-specific playable outputs.</p>
|
||||
</header>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-label">Source HTML (Playworks export)</div>
|
||||
<div class="row">
|
||||
<input id="src" type="text" placeholder="Path to Playworks HTML..." readonly />
|
||||
<button id="pickSrc">Browse...</button>
|
||||
<section class="tool-panel input-panel">
|
||||
<div class="panel-header">
|
||||
<h3 class="panel-title">Inputs</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-label">Base Filename</div>
|
||||
<div class="row">
|
||||
<input id="baseName" type="text" placeholder="Base filename..." />
|
||||
<div class="panel-body">
|
||||
<div class="control-group">
|
||||
<div class="control-label">Source HTML (Playworks export)</div>
|
||||
<div class="field-row">
|
||||
<input id="src" type="hidden" />
|
||||
<button id="pickSrc" class="secondary">Select File</button>
|
||||
<span id="srcName" class="file-name">(no file)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="control-label">Base Filename</div>
|
||||
<div class="field-row">
|
||||
<input id="baseName" type="text" placeholder="Base filename..." />
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="control-label">Output Folder</div>
|
||||
<div class="field-row">
|
||||
<input id="outDir" type="text" placeholder="Output folder..." />
|
||||
<button id="pickOut" class="secondary">Browse...</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="control-label">Networks to Generate</div>
|
||||
<div class="toggle-row">
|
||||
<button id="selectAll" class="secondary">Select All</button>
|
||||
<button id="selectNone" class="secondary">Select None</button>
|
||||
</div>
|
||||
<div class="results-panel" style="margin-top:0;">
|
||||
<table class="data-table">
|
||||
<thead><tr><th style="width:70px;">Use</th><th style="width:160px;">Network</th><th>Output behavior</th></tr></thead>
|
||||
<tbody>${checkboxRows}</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-row">
|
||||
<button id="convert" disabled>Convert</button>
|
||||
</div>
|
||||
<div id="status" class="status-panel"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div id="outputPanel" class="is-hidden">
|
||||
<div id="results" class="results-panel"></div>
|
||||
<div class="action-row">
|
||||
<button id="openOut" class="secondary" style="display:none">Open Output Folder</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
<div class="section-label">Output Folder</div>
|
||||
<div class="row">
|
||||
<input id="outDir" type="text" placeholder="Output folder..." />
|
||||
<button id="pickOut">Browse...</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="section">
|
||||
<div class="section-label">Networks to generate</div>
|
||||
<div class="toggle-row">
|
||||
<button id="selectAll">All</button>
|
||||
<button id="selectNone">None</button>
|
||||
</div>
|
||||
<div class="net-grid">${checkboxRows}</div>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<button class="primary" id="convert" disabled>Convert</button>
|
||||
<button id="openOut" style="display:none">Open Output Folder</button>
|
||||
</div>
|
||||
|
||||
<div id="status"></div>
|
||||
<div class="results" id="results"></div>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
const vscode = acquireVsCodeApi();
|
||||
let outputDir = '';
|
||||
|
||||
const srcEl = document.getElementById('src');
|
||||
const srcNameEl = document.getElementById('srcName');
|
||||
const outEl = document.getElementById('outDir');
|
||||
const baseNameEl = document.getElementById('baseName');
|
||||
const convertBtn = document.getElementById('convert');
|
||||
const openOutBtn = document.getElementById('openOut');
|
||||
const statusEl = document.getElementById('status');
|
||||
const resultsEl = document.getElementById('results');
|
||||
const outputPanel = document.getElementById('outputPanel');
|
||||
|
||||
function updateConvertBtn() {
|
||||
const hasNet = [...document.querySelectorAll('.net-cb')].some(c => c.checked);
|
||||
@@ -446,7 +425,7 @@ function getHtml(): string {
|
||||
document.getElementById('pickSrc').addEventListener('click', () => vscode.postMessage({ type: 'pickSource' }));
|
||||
document.getElementById('pickOut').addEventListener('click', () => vscode.postMessage({ type: 'pickOutput' }));
|
||||
document.getElementById('selectAll').addEventListener('click', () => {
|
||||
document.querySelectorAll('.net-cb').forEach(c => c.checked = true);
|
||||
document.querySelectorAll('.net-cb').forEach(c => c.checked = c.dataset.tag !== 'tt');
|
||||
updateConvertBtn();
|
||||
});
|
||||
document.getElementById('selectNone').addEventListener('click', () => {
|
||||
@@ -472,6 +451,7 @@ function getHtml(): string {
|
||||
statusEl.textContent = 'Converting...';
|
||||
resultsEl.innerHTML = '';
|
||||
openOutBtn.style.display = 'none';
|
||||
outputPanel.classList.add('is-hidden');
|
||||
convertBtn.disabled = true;
|
||||
vscode.postMessage({
|
||||
type: 'convert',
|
||||
@@ -488,6 +468,7 @@ function getHtml(): string {
|
||||
const msg = event.data;
|
||||
if (msg.type === 'sourcePicked') {
|
||||
srcEl.value = msg.path;
|
||||
srcNameEl.textContent = msg.path.split(/[\\\\/]/).filter(Boolean).pop() || msg.path;
|
||||
baseNameEl.value = msg.baseName || '';
|
||||
if (!outEl.value && msg.dir) {
|
||||
outEl.value = msg.dir;
|
||||
@@ -503,31 +484,46 @@ function getHtml(): string {
|
||||
updateConvertBtn();
|
||||
if (msg.error) {
|
||||
statusEl.textContent = 'Error: ' + msg.error;
|
||||
outputPanel.classList.add('is-hidden');
|
||||
return;
|
||||
}
|
||||
const results = msg.results || [];
|
||||
const ok = results.filter(r => r.ok).length;
|
||||
statusEl.textContent = ok + ' of ' + results.length + ' network(s) converted.';
|
||||
resultsEl.innerHTML = '';
|
||||
if (!results.length) {
|
||||
resultsEl.innerHTML = '';
|
||||
outputPanel.classList.add('is-hidden');
|
||||
return;
|
||||
}
|
||||
outputPanel.classList.remove('is-hidden');
|
||||
resultsEl.innerHTML =
|
||||
'<table class="data-table">' +
|
||||
'<thead><tr><th style="width:120px;">Network</th><th style="width:90px;">Status</th><th style="width:90px;">Output</th><th>Path</th><th>Error</th></tr></thead>' +
|
||||
'<tbody></tbody>' +
|
||||
'</table>';
|
||||
const tbody = resultsEl.querySelector('tbody');
|
||||
for (const r of results) {
|
||||
const row = document.createElement('div');
|
||||
row.className = 'res-row';
|
||||
const mark = document.createElement('span');
|
||||
mark.className = 'mark ' + (r.ok ? 'ok' : 'bad');
|
||||
mark.textContent = r.ok ? '✓' : '✗';
|
||||
const net = document.createElement('span');
|
||||
net.className = 'res-net';
|
||||
const row = document.createElement('tr');
|
||||
const net = document.createElement('td');
|
||||
net.textContent = r.network;
|
||||
const detail = document.createElement('span');
|
||||
const status = document.createElement('td');
|
||||
status.innerHTML = r.ok ? '<span class="badge ok">Done</span>' : '<span class="badge err">Failed</span>';
|
||||
const outputType = document.createElement('td');
|
||||
const detail = document.createElement('td');
|
||||
detail.className = 'mono wrap';
|
||||
const error = document.createElement('td');
|
||||
error.className = 'err wrap';
|
||||
if (r.ok) {
|
||||
detail.className = 'res-file';
|
||||
outputType.textContent = /\\.zip$/i.test(r.file) ? 'ZIP' : 'HTML';
|
||||
detail.textContent = outputDisplayName(r.file);
|
||||
} else {
|
||||
detail.className = 'res-err';
|
||||
detail.textContent = r.error || 'Unknown error';
|
||||
outputType.textContent = '-';
|
||||
detail.innerHTML = '<span class="muted">-</span>';
|
||||
error.textContent = r.error || 'Unknown error';
|
||||
}
|
||||
row.append(mark, net, detail);
|
||||
resultsEl.appendChild(row);
|
||||
if (r.ok) error.innerHTML = '<span class="muted">-</span>';
|
||||
row.append(net, status, outputType, detail, error);
|
||||
tbody.appendChild(row);
|
||||
}
|
||||
if (ok > 0) {
|
||||
outputDir = outEl.value;
|
||||
|
||||
Reference in New Issue
Block a user