generate outside generated
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
buenosairesam
2026-01-21 23:26:47 -03:00
parent 423909d391
commit 6e18324a43
4 changed files with 2 additions and 69 deletions

512
generate.html Normal file
View File

@@ -0,0 +1,512 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Soleprint - Generate Configuration</title>
<style>
:root {
--bg: #1a1a2e;
--surface: #16213e;
--primary: #e94560;
--text: #eaeaea;
--text-muted: #8892b0;
--border: #0f3460;
--success: #4ecca3;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: "Segoe UI", system-ui, sans-serif;
background: var(--bg);
color: var(--text);
min-height: 100vh;
padding: 2rem;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
header {
text-align: center;
margin-bottom: 2rem;
}
header h1 {
font-size: 2rem;
margin-bottom: 0.5rem;
}
header p {
color: var(--text-muted);
}
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
}
@media (max-width: 900px) {
.grid {
grid-template-columns: 1fr;
}
}
.card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 8px;
padding: 1.5rem;
}
.card h2 {
font-size: 1.2rem;
margin-bottom: 1rem;
color: var(--primary);
}
.form-group {
margin-bottom: 1rem;
}
.form-group label {
display: block;
margin-bottom: 0.3rem;
font-size: 0.9rem;
color: var(--text-muted);
}
.form-group input,
.form-group select {
width: 100%;
padding: 0.6rem;
border: 1px solid var(--border);
border-radius: 4px;
background: var(--bg);
color: var(--text);
font-size: 0.95rem;
}
.form-group input:focus {
outline: none;
border-color: var(--primary);
}
.form-row {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
.section-title {
font-size: 0.85rem;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--text-muted);
margin: 1.5rem 0 0.8rem;
padding-bottom: 0.3rem;
border-bottom: 1px solid var(--border);
}
.checkbox-group {
display: flex;
align-items: center;
gap: 0.5rem;
}
.checkbox-group input {
width: auto;
}
.btn {
display: inline-block;
padding: 0.7rem 1.5rem;
border: none;
border-radius: 4px;
font-size: 1rem;
cursor: pointer;
transition: background 0.2s;
}
.btn-primary {
background: var(--primary);
color: white;
}
.btn-primary:hover {
background: #c73e54;
}
.btn-secondary {
background: var(--border);
color: var(--text);
}
.btn-secondary:hover {
background: #1a4a7a;
}
.btn-group {
display: flex;
gap: 1rem;
margin-top: 1.5rem;
}
.preview {
font-family: "Consolas", "Monaco", monospace;
font-size: 0.85rem;
background: var(--bg);
border: 1px solid var(--border);
border-radius: 4px;
padding: 1rem;
max-height: 500px;
overflow-y: auto;
white-space: pre;
}
.preview .folder {
color: #82aaff;
}
.preview .file {
color: var(--text-muted);
}
.preview .comment {
color: #546e7a;
}
.status {
margin-top: 1rem;
padding: 0.8rem;
border-radius: 4px;
display: none;
}
.status.success {
display: block;
background: rgba(78, 204, 163, 0.2);
border: 1px solid var(--success);
color: var(--success);
}
.status.error {
display: block;
background: rgba(233, 69, 96, 0.2);
border: 1px solid var(--primary);
color: var(--primary);
}
.help-text {
font-size: 0.8rem;
color: var(--text-muted);
margin-top: 0.3rem;
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>Soleprint Configuration Generator</h1>
<p>
Generate a new room configuration for wrapping a managed
application
</p>
</header>
<div class="grid">
<div class="card">
<h2>Configuration</h2>
<form id="configForm">
<div class="section-title">Room Settings</div>
<div class="form-group">
<label for="roomName">Room Name</label>
<input
type="text"
id="roomName"
placeholder="e.g., myproject"
required
/>
<div class="help-text">
Unique identifier for this configuration
</div>
</div>
<div class="section-title">Framework Branding</div>
<div class="form-row">
<div class="form-group">
<label for="frameworkName"
>Framework Name</label
>
<input
type="text"
id="frameworkName"
value="soleprint"
placeholder="soleprint"
/>
</div>
<div class="form-group">
<label for="frameworkIcon">Icon</label>
<input
type="text"
id="frameworkIcon"
value=""
placeholder="optional"
/>
</div>
</div>
<div class="section-title">System Names</div>
<div class="form-row">
<div class="form-group">
<label for="arteryName">Data Flow System</label>
<input
type="text"
id="arteryName"
value="artery"
placeholder="artery"
/>
</div>
<div class="form-group">
<label for="atlasName"
>Documentation System</label
>
<input
type="text"
id="atlasName"
value="atlas"
placeholder="atlas"
/>
</div>
</div>
<div class="form-group">
<label for="stationName">Execution System</label>
<input
type="text"
id="stationName"
value="station"
placeholder="station"
/>
</div>
<div class="section-title">
Managed Application (Optional)
</div>
<div class="checkbox-group form-group">
<input type="checkbox" id="hasManaged" />
<label for="hasManaged"
>Include managed application</label
>
</div>
<div id="managedFields" style="display: none">
<div class="form-group">
<label for="managedName"
>Managed App Name</label
>
<input
type="text"
id="managedName"
placeholder="e.g., myapp"
/>
</div>
<div class="form-group">
<label for="backendPath"
>Backend Repo Path</label
>
<input
type="text"
id="backendPath"
placeholder="/path/to/backend"
/>
</div>
<div class="form-group">
<label for="frontendPath"
>Frontend Repo Path</label
>
<input
type="text"
id="frontendPath"
placeholder="/path/to/frontend"
/>
</div>
</div>
<div class="btn-group">
<button
type="button"
class="btn btn-primary"
onclick="generateConfig()"
>
Generate Config
</button>
<button
type="button"
class="btn btn-secondary"
onclick="updatePreview()"
>
Preview Structure
</button>
</div>
</form>
<div id="status" class="status"></div>
</div>
<div class="card">
<h2>Preview</h2>
<div id="preview" class="preview">
<span class="comment"
># Enter configuration details and click "Preview
Structure"</span
>
<span class="folder">gen/&lt;room&gt;/</span>
<span class="folder">&lt;managed&gt;/</span>
<span class="comment"># if managed app configured</span>
<span class="folder">link/</span>
<span class="folder">&lt;soleprint&gt;/</span>
</div>
</div>
</div>
</div>
<script>
const form = document.getElementById("configForm");
const hasManaged = document.getElementById("hasManaged");
const managedFields = document.getElementById("managedFields");
const preview = document.getElementById("preview");
const status = document.getElementById("status");
// Toggle managed fields
hasManaged.addEventListener("change", () => {
managedFields.style.display = hasManaged.checked
? "block"
: "none";
updatePreview();
});
// Live preview on input changes
form.querySelectorAll("input").forEach((input) => {
input.addEventListener("input", debounce(updatePreview, 300));
});
function debounce(func, wait) {
let timeout;
return function (...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
function getFormData() {
return {
room_name:
document.getElementById("roomName").value || "myroom",
framework: {
name:
document.getElementById("frameworkName").value ||
"soleprint",
icon:
document.getElementById("frameworkIcon").value ||
null,
},
systems: {
artery:
document.getElementById("arteryName").value ||
"artery",
atlas:
document.getElementById("atlasName").value ||
"atlas",
station:
document.getElementById("stationName").value ||
"station",
},
managed: hasManaged.checked
? {
name:
document.getElementById("managedName")
.value || "",
repos: {
backend:
document.getElementById("backendPath")
.value || "",
frontend:
document.getElementById("frontendPath")
.value || "",
},
}
: null,
};
}
async function updatePreview() {
const data = getFormData();
try {
const response = await fetch("/api/generate/preview", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
if (response.ok) {
const result = await response.json();
preview.innerHTML = result.tree;
} else {
const err = await response.json();
preview.innerHTML = `<span class="comment"># Error: ${err.detail || "Unknown error"}</span>`;
}
} catch (e) {
// Fallback to client-side preview
preview.innerHTML = generateLocalPreview(data);
}
}
function generateLocalPreview(data) {
const room = data.room_name || "room";
const fw = data.framework.name || "soleprint";
const managed = data.managed;
let tree = `<span class="folder">gen/${room}/</span>\n`;
if (managed && managed.name) {
tree += ` <span class="folder">${managed.name}/</span>\n`;
tree += ` <span class="folder">link/</span>\n`;
}
tree += ` <span class="folder">${fw}/</span>\n`;
return tree;
}
async function generateConfig() {
const data = getFormData();
if (!data.room_name) {
showStatus("error", "Room name is required");
return;
}
try {
const response = await fetch("/api/generate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
});
if (response.ok) {
const result = await response.json();
// Download config.json
const blob = new Blob(
[JSON.stringify(result.config, null, 2)],
{ type: "application/json" },
);
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = `config.json`;
a.click();
URL.revokeObjectURL(url);
showStatus(
"success",
`Configuration generated for "${data.room_name}". Save to cfg/${data.room_name}/config.json`,
);
} else {
const err = await response.json();
showStatus(
"error",
err.detail || "Failed to generate config",
);
}
} catch (e) {
showStatus("error", `Error: ${e.message}`);
}
}
function showStatus(type, message) {
status.className = `status ${type}`;
status.textContent = message;
}
// Initial preview
updatePreview();
</script>
</body>
</html>