Run playground examples from entrypoint
This commit is contained in:
@@ -3,6 +3,7 @@ export const playgroundExamples = [
|
||||
id: 'product-api-production',
|
||||
title: 'Production API deployment',
|
||||
activePath: 'main.dcdl',
|
||||
entryPath: 'main.dcdl',
|
||||
files: {
|
||||
'main.dcdl': `let
|
||||
schema = import "./schemas/service.dcdl";
|
||||
@@ -105,6 +106,7 @@ image = "registry.example.com/checkout-api:2026.06.15";
|
||||
id: 'tenant-enterprise-plan',
|
||||
title: 'Enterprise tenant contract',
|
||||
activePath: 'main.dcdl',
|
||||
entryPath: 'main.dcdl',
|
||||
files: {
|
||||
'main.dcdl': `let
|
||||
schema = import "./schemas/tenant.dcdl";
|
||||
@@ -192,6 +194,7 @@ Acme = {
|
||||
id: 'event-pipeline-prod',
|
||||
title: 'Event ingestion pipeline',
|
||||
activePath: 'main.dcdl',
|
||||
entryPath: 'main.dcdl',
|
||||
files: {
|
||||
'main.dcdl': `let
|
||||
schema = import "./schemas/pipeline.dcdl";
|
||||
@@ -276,6 +279,7 @@ privacy = ["redact_ip", "hash_user_id"];
|
||||
id: 'edge-cdn-policy',
|
||||
title: 'Edge CDN routing policy',
|
||||
activePath: 'main.dcdl',
|
||||
entryPath: 'main.dcdl',
|
||||
files: {
|
||||
'main.dcdl': `let
|
||||
schema = import "./schemas/edge.dcdl";
|
||||
@@ -340,6 +344,7 @@ StrictHeaders = {
|
||||
id: 'incident-escalation',
|
||||
title: 'Incident escalation policy',
|
||||
activePath: 'main.dcdl',
|
||||
entryPath: 'main.dcdl',
|
||||
files: {
|
||||
'main.dcdl': `let
|
||||
schema = import "./schemas/oncall.dcdl";
|
||||
|
||||
@@ -7,7 +7,7 @@ import { keymap } from '@codemirror/view';
|
||||
import { decodal } from 'decodal-codemirror';
|
||||
import { playgroundExamples } from './playground-examples.js';
|
||||
|
||||
const STORAGE_KEY = 'decodal-playground-project-v1';
|
||||
const STORAGE_KEY = 'decodal-playground-project-v2';
|
||||
const starterProject = playgroundExamples[0];
|
||||
|
||||
const editorHost = document.getElementById('editor');
|
||||
@@ -90,6 +90,7 @@ for (const example of playgroundExamples) {
|
||||
exampleSelect.value = starterProject.id;
|
||||
|
||||
setActiveFile(project.activePath);
|
||||
updateRunLabel();
|
||||
renderFileTree();
|
||||
|
||||
function loadProject() {
|
||||
@@ -98,12 +99,22 @@ function loadProject() {
|
||||
if (stored && stored.files && typeof stored.activePath === 'string') {
|
||||
const files = normalizeFiles(stored.files);
|
||||
const activePath = files[stored.activePath] === undefined ? Object.keys(files)[0] : stored.activePath;
|
||||
if (activePath) return { files, activePath };
|
||||
if (activePath) {
|
||||
const storedEntryPath = typeof stored.entryPath === 'string' ? normalizePath(stored.entryPath) : '';
|
||||
const entryPath = files[storedEntryPath] === undefined
|
||||
? files['main.dcdl'] === undefined ? activePath : 'main.dcdl'
|
||||
: storedEntryPath;
|
||||
return { files, activePath, entryPath };
|
||||
}
|
||||
}
|
||||
} catch (_error) {
|
||||
// Fall back to the starter project.
|
||||
}
|
||||
return { files: cloneFiles(starterProject.files), activePath: starterProject.activePath };
|
||||
return {
|
||||
files: cloneFiles(starterProject.files),
|
||||
activePath: starterProject.activePath,
|
||||
entryPath: starterProject.entryPath ?? starterProject.activePath,
|
||||
};
|
||||
}
|
||||
|
||||
function cloneFiles(files) {
|
||||
@@ -127,6 +138,7 @@ function loadExampleProject(exampleId) {
|
||||
const example = playgroundExamples.find((item) => item.id === exampleId) ?? starterProject;
|
||||
project.files = cloneFiles(example.files);
|
||||
project.activePath = example.activePath;
|
||||
project.entryPath = example.entryPath ?? example.activePath;
|
||||
exampleSelect.value = example.id;
|
||||
setActiveFile(project.activePath);
|
||||
output.textContent = '';
|
||||
@@ -166,16 +178,27 @@ function setActiveFile(path) {
|
||||
}
|
||||
project.activePath = normalized;
|
||||
setEditorText(project.files[normalized]);
|
||||
activeFile.textContent = normalized;
|
||||
activeFile.textContent = normalized === project.entryPath ? `${normalized} (entry)` : normalized;
|
||||
deleteFile.disabled = Object.keys(project.files).length <= 1;
|
||||
renderFileTree();
|
||||
updateRunLabel();
|
||||
saveProject();
|
||||
}
|
||||
|
||||
function updateRunLabel() {
|
||||
const entryPath = project.files[project.entryPath] === undefined ? project.activePath : project.entryPath;
|
||||
project.entryPath = entryPath;
|
||||
run.textContent = `Run ${entryPath}`;
|
||||
run.title = `Materialize ${entryPath}`;
|
||||
}
|
||||
|
||||
function execute() {
|
||||
project.files[project.activePath] = getEditorText();
|
||||
const entryPath = project.files[project.entryPath] === undefined ? project.activePath : project.entryPath;
|
||||
project.entryPath = entryPath;
|
||||
updateRunLabel();
|
||||
saveProject();
|
||||
const result = JSON.parse(evaluateProject(project.activePath, JSON.stringify(project.files)));
|
||||
const result = JSON.parse(evaluateProject(entryPath, JSON.stringify(project.files)));
|
||||
output.textContent = result.ok ? result.output : result.error;
|
||||
output.classList.toggle('error', !result.ok);
|
||||
}
|
||||
@@ -224,8 +247,8 @@ function renderTreeList(children) {
|
||||
const button = document.createElement('button');
|
||||
button.type = 'button';
|
||||
button.className = child.path === project.activePath ? 'file active' : 'file';
|
||||
button.textContent = child.name;
|
||||
button.title = child.path;
|
||||
button.textContent = child.path === project.entryPath ? `${child.name} *` : child.name;
|
||||
button.title = child.path === project.entryPath ? `${child.path} (entry point)` : child.path;
|
||||
button.addEventListener('click', () => setActiveFile(child.path));
|
||||
item.append(button);
|
||||
} else {
|
||||
@@ -276,5 +299,8 @@ deleteFile.addEventListener('click', () => {
|
||||
if (Object.keys(project.files).length <= 1) return;
|
||||
if (!confirm(`Delete ${project.activePath}?`)) return;
|
||||
delete project.files[project.activePath];
|
||||
if (project.files[project.entryPath] === undefined) {
|
||||
project.entryPath = Object.keys(project.files).sort()[0];
|
||||
}
|
||||
setActiveFile(Object.keys(project.files).sort()[0]);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user