feat: wip previews for non-get routes
This commit is contained in:
parent
ee0b9e597a
commit
a23aee5d21
5 changed files with 366 additions and 24 deletions
238
db.js
238
db.js
|
|
@ -126,22 +126,61 @@ function createStructure(db, name, userId) {
|
||||||
|
|
||||||
function createRoute(db, verb, path, structureId, handler) {
|
function createRoute(db, verb, path, structureId, handler) {
|
||||||
path = encodeURI(path);
|
path = encodeURI(path);
|
||||||
// add default handler here
|
|
||||||
const stmt = db.prepare(
|
const stmt = db.prepare(
|
||||||
"INSERT INTO routes (verb, path, structure_id, handler) VALUES (?, ?, ?, ?)",
|
"INSERT INTO routes (verb, path, structure_id, handler) VALUES (?, ?, ?, ?)"
|
||||||
);
|
);
|
||||||
const info = stmt.run(verb, path, structureId, handler);
|
const info = stmt.run(verb, path, structureId, handler);
|
||||||
return info.lastInsertRowid; // Returns the route_id of the newly created route
|
const routeId = info.lastInsertRowid; // Get the newly created route ID
|
||||||
|
|
||||||
|
if (verb !== 'GET') {
|
||||||
|
createScaffoldPage(db, routeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return routeId; // Returns the route_id of the newly created route
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRoutes(db, structureId) {
|
function getRoutes(db, structureId) {
|
||||||
return db
|
const query = `
|
||||||
.prepare("SELECT * from routes where structure_id = ?")
|
SELECT
|
||||||
.all(structureId);
|
r.*,
|
||||||
|
sp.id AS scaffold_page_id,
|
||||||
|
sp.content AS scaffold_page_content,
|
||||||
|
sp2.id AS scaffold_params_id,
|
||||||
|
sp2.query_params,
|
||||||
|
sp2.url_params
|
||||||
|
FROM routes r
|
||||||
|
LEFT JOIN scaffold_pages sp ON r.id = sp.route_id
|
||||||
|
LEFT JOIN scaffold_params sp2 ON r.id = sp2.route_id
|
||||||
|
WHERE r.structure_id = ?
|
||||||
|
ORDER BY sp.created_at DESC, sp2.created_at DESC
|
||||||
|
`;
|
||||||
|
|
||||||
|
return db.prepare(query).all(structureId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRoute(db, routeId) {
|
function getRoute(db, routeId) {
|
||||||
return db.prepare("SELECT * from routes where id = ?").get(routeId);
|
const query = `
|
||||||
|
SELECT
|
||||||
|
r.*,
|
||||||
|
sp.id AS scaffold_page_id,
|
||||||
|
sp.content AS scaffold_page_content,
|
||||||
|
sp2.id AS scaffold_params_id,
|
||||||
|
sp2.query_params,
|
||||||
|
sp2.url_params
|
||||||
|
FROM routes r
|
||||||
|
LEFT JOIN scaffold_pages sp ON r.id = sp.route_id
|
||||||
|
LEFT JOIN scaffold_params sp2 ON r.id = sp2.route_id
|
||||||
|
WHERE r.id = ?
|
||||||
|
ORDER BY sp.created_at DESC, sp2.created_at DESC
|
||||||
|
LIMIT 1
|
||||||
|
`;
|
||||||
|
|
||||||
|
return db.prepare(query).get(routeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function defaultEndpointForRoute(db, routeId) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateRoute(db, route) {
|
function updateRoute(db, route) {
|
||||||
|
|
@ -334,7 +373,7 @@ function cloneStructure(
|
||||||
).lastInsertRowid;
|
).lastInsertRowid;
|
||||||
|
|
||||||
const dbIds = db
|
const dbIds = db
|
||||||
.prepare(`select db_id from structure_dbs where structure_id = ?;`)
|
.prepare(`SELECT db_id FROM structure_dbs WHERE structure_id = ?;`)
|
||||||
.all(structId);
|
.all(structId);
|
||||||
|
|
||||||
const toClone = new Set(cloneDbs);
|
const toClone = new Set(cloneDbs);
|
||||||
|
|
@ -363,7 +402,7 @@ function cloneStructure(
|
||||||
`,
|
`,
|
||||||
).run(newDb, newStructId, db_id, structId);
|
).run(newDb, newStructId, db_id, structId);
|
||||||
|
|
||||||
db.prepare(`select id from dbs where structure_id = ?`)
|
db.prepare(`SELECT id FROM dbs WHERE structure_id = ?`)
|
||||||
.all(newStructId)
|
.all(newStructId)
|
||||||
.map((new_db) => {
|
.map((new_db) => {
|
||||||
const srcPath = path.join(__dirname, "dbs", `${db_id}.sqlite`);
|
const srcPath = path.join(__dirname, "dbs", `${db_id}.sqlite`);
|
||||||
|
|
@ -373,6 +412,7 @@ function cloneStructure(
|
||||||
fs.copyFileSync(srcPath + "-wal", destPath + "-wal");
|
fs.copyFileSync(srcPath + "-wal", destPath + "-wal");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let db_id of toAlias) {
|
for (let db_id of toAlias) {
|
||||||
db.prepare(
|
db.prepare(
|
||||||
`
|
`
|
||||||
|
|
@ -382,18 +422,42 @@ function cloneStructure(
|
||||||
).run(newStructId, structId, db_id);
|
).run(newStructId, structId, db_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clone templates
|
||||||
const cloneTemplates = db.prepare(`
|
const cloneTemplates = db.prepare(`
|
||||||
INSERT INTO templates (name, content, structure_id, test_object, engine)
|
INSERT INTO templates (name, content, structure_id, test_object, engine)
|
||||||
SELECT name, content, ?, test_object, engine FROM templates WHERE structure_id = ?;
|
SELECT name, content, ?, test_object, engine FROM templates WHERE structure_id = ?;
|
||||||
`);
|
`);
|
||||||
cloneTemplates.run(newStructId, structId);
|
cloneTemplates.run(newStructId, structId);
|
||||||
|
|
||||||
|
// Clone routes
|
||||||
const cloneRoutes = db.prepare(`
|
const cloneRoutes = db.prepare(`
|
||||||
INSERT INTO routes (verb, path, structure_id, handler)
|
INSERT INTO routes (verb, path, structure_id, handler)
|
||||||
SELECT verb, path, ?, handler FROM routes WHERE structure_id = ?;
|
SELECT verb, path, ?, handler FROM routes WHERE structure_id = ?;
|
||||||
`);
|
`);
|
||||||
cloneRoutes.run(newStructId, structId);
|
cloneRoutes.run(newStructId, structId);
|
||||||
|
|
||||||
|
// Clone scaffold pages
|
||||||
|
const cloneScaffoldPages = db.prepare(`
|
||||||
|
INSERT INTO scaffold_pages (route_id, content, created_at)
|
||||||
|
SELECT newRoutes.id, sp.content, sp.created_at
|
||||||
|
FROM scaffold_pages sp
|
||||||
|
JOIN routes oldRoutes ON sp.route_id = oldRoutes.id
|
||||||
|
JOIN routes newRoutes ON oldRoutes.path = newRoutes.path AND oldRoutes.verb = newRoutes.verb
|
||||||
|
WHERE oldRoutes.structure_id = ? AND newRoutes.structure_id = ?;
|
||||||
|
`);
|
||||||
|
cloneScaffoldPages.run(structId, newStructId);
|
||||||
|
|
||||||
|
// Clone scaffold params
|
||||||
|
const cloneScaffoldParams = db.prepare(`
|
||||||
|
INSERT INTO scaffold_params (route_id, query_params, url_params, created_at)
|
||||||
|
SELECT newRoutes.id, sp.query_params, sp.url_params, sp.created_at
|
||||||
|
FROM scaffold_params sp
|
||||||
|
JOIN routes oldRoutes ON sp.route_id = oldRoutes.id
|
||||||
|
JOIN routes newRoutes ON oldRoutes.path = newRoutes.path AND oldRoutes.verb = newRoutes.verb
|
||||||
|
WHERE oldRoutes.structure_id = ? AND newRoutes.structure_id = ?;
|
||||||
|
`);
|
||||||
|
cloneScaffoldParams.run(structId, newStructId);
|
||||||
|
|
||||||
return newStructId;
|
return newStructId;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -432,6 +496,158 @@ function getMostRecentLogIdByRoute(db, routeId) {
|
||||||
return result ? result.id : 0;
|
return result ? result.id : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildScaffoldUrl(endpoint, urlParams, queryString) {
|
||||||
|
let populatedUrl = endpoint.replace(/:([^/]+)/g, () => urlParams.shift() || '');
|
||||||
|
return queryString ? `${populatedUrl}?${queryString}` : populatedUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createScaffoldPage(db, routeId, content=null) {
|
||||||
|
if (!content) {
|
||||||
|
const route = getRoute(db, routeId)
|
||||||
|
const endpoint = buildScaffoldUrl(route.path, route.url_params, route.query_params);
|
||||||
|
content = getDefaultScaffoldContentByVerb(endpoint, route.verb);
|
||||||
|
console.log("gabga", content, route, endpoint)
|
||||||
|
}
|
||||||
|
console.log(content, "content")
|
||||||
|
const stmt = db.prepare(
|
||||||
|
"INSERT INTO scaffold_pages (route_id, content) VALUES (?, ?)"
|
||||||
|
);
|
||||||
|
const info = stmt.run(routeId, content);
|
||||||
|
return info.lastInsertRowid; // Returns the scaffold_page id of the newly created scaffold page
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLatestScaffoldPage(db, routeId) {
|
||||||
|
const stmt = db.prepare(
|
||||||
|
"SELECT * FROM scaffold_pages WHERE route_id = ? ORDER BY created_at DESC LIMIT 1"
|
||||||
|
);
|
||||||
|
return stmt.get(routeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateScaffoldPage(db, scaffoldPage) {
|
||||||
|
const fields = ["content"];
|
||||||
|
const values = fields.map((field) => scaffoldPage[field]);
|
||||||
|
const placeholders = fields.map((field) => `${field} = ?`).join(", ");
|
||||||
|
console.log(scaffoldPage, "gabababab")
|
||||||
|
|
||||||
|
const sql = `UPDATE scaffold_pages SET ${placeholders} WHERE id = ?`;
|
||||||
|
values.push(scaffoldPage.id); // Add scaffoldPageId to the end for the WHERE clause
|
||||||
|
|
||||||
|
const info = db.prepare(sql).run(...values);
|
||||||
|
console.log(info.changes)
|
||||||
|
return info.changes > 0; // Returns true if a row was updated, false otherwise
|
||||||
|
}
|
||||||
|
|
||||||
|
function generatePostForm(endpoint) {
|
||||||
|
return `
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Test POST Request</title>
|
||||||
|
<script src="https://unpkg.com/htmx.org@1.9.2"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Test POST Request</h1>
|
||||||
|
|
||||||
|
<form action="<%= it.route("${endpoint}") %>" method="POST">
|
||||||
|
<!-- Add your form fields here to test post requests. -->
|
||||||
|
<label for="testField">Test Field:</label>
|
||||||
|
<input type="text" id="testField" name="testField" required>
|
||||||
|
|
||||||
|
<button type="submit">Submit</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<!-- Add any divs for hx-swaps anywhere on the page. -->
|
||||||
|
<div id="result" hx-swap="innerHTML"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateModifyForm(endpoint, verb) {
|
||||||
|
return `
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Test ${verb} Request</title>
|
||||||
|
<script src="https://unpkg.com/htmx.org@1.9.2"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Test ${verb} Request</h1>
|
||||||
|
|
||||||
|
<form action="<%= it.route(${endpoint}) %>" method="${verb}">
|
||||||
|
<!-- Add your form fields here to test ${verb.toLowerCase()} requests. -->
|
||||||
|
<label for="testField">Test Field:</label>
|
||||||
|
<input type="text" id="testField" name="testField" required>
|
||||||
|
|
||||||
|
<button type="submit">${verb}</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<!-- Add any divs for hx-swaps anywhere on the page. -->
|
||||||
|
<div id="result" hx-swap="innerHTML"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateWSPage(endpoint) {
|
||||||
|
return `
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Test WebSocket</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Test WebSocket Connection</h1>
|
||||||
|
|
||||||
|
<input type="text" id="wsMessage" placeholder="Type a message">
|
||||||
|
<button onclick="sendMessage()">Send</button>
|
||||||
|
|
||||||
|
<div id="wsOutput"></div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const ws = new WebSocket('<%= it.route("${endpoint}") %>');
|
||||||
|
|
||||||
|
ws.onopen = () => {
|
||||||
|
document.getElementById('wsOutput').innerHTML += '<p>Connected to WebSocket</p>';
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.onmessage = (event) => {
|
||||||
|
document.getElementById('wsOutput').innerHTML += '<p>Received: ' + event.data + '</p>';
|
||||||
|
};
|
||||||
|
|
||||||
|
ws.onclose = () => {
|
||||||
|
document.getElementById('wsOutput').innerHTML += '<p>WebSocket connection closed</p>';
|
||||||
|
};
|
||||||
|
|
||||||
|
function sendMessage() {
|
||||||
|
const message = document.getElementById('wsMessage').value;
|
||||||
|
ws.send(message);
|
||||||
|
document.getElementById('wsOutput').innerHTML += '<p>Sent: ' + message + '</p>';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDefaultScaffoldContentByVerb(url, verb) {
|
||||||
|
if (verb == "POST") {
|
||||||
|
return generatePostForm(url);
|
||||||
|
}
|
||||||
|
else if (verb == "PUT" || verb == "DELETE") {
|
||||||
|
return generateModifyForm(url, verb);
|
||||||
|
}
|
||||||
|
else if (verb == "WS") {
|
||||||
|
return generateWSPage(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
db,
|
db,
|
||||||
applyMigrations,
|
applyMigrations,
|
||||||
|
|
@ -445,6 +661,7 @@ module.exports = {
|
||||||
createRoute,
|
createRoute,
|
||||||
getRoutes,
|
getRoutes,
|
||||||
getRoute,
|
getRoute,
|
||||||
|
buildScaffoldUrl,
|
||||||
updateRoute,
|
updateRoute,
|
||||||
updateDb,
|
updateDb,
|
||||||
updateStruct,
|
updateStruct,
|
||||||
|
|
@ -467,4 +684,7 @@ module.exports = {
|
||||||
getLogsByRoute,
|
getLogsByRoute,
|
||||||
getNewLogsByRoute,
|
getNewLogsByRoute,
|
||||||
getMostRecentLogIdByRoute,
|
getMostRecentLogIdByRoute,
|
||||||
|
createScaffoldPage,
|
||||||
|
getLatestScaffoldPage,
|
||||||
|
updateScaffoldPage
|
||||||
};
|
};
|
||||||
|
|
|
||||||
51
index.js
51
index.js
|
|
@ -464,6 +464,11 @@ app.post("/workshop/:structure_id/route", (req, res) => {
|
||||||
app.put("/workshop/:structure_id/route/:route_id", (req, res) => {
|
app.put("/workshop/:structure_id/route/:route_id", (req, res) => {
|
||||||
const route = model.getRoute(db, req.params.route_id);
|
const route = model.getRoute(db, req.params.route_id);
|
||||||
model.updateRoute(db, { ...route, ...req.body });
|
model.updateRoute(db, { ...route, ...req.body });
|
||||||
|
if (req.body.scaffold_page) {
|
||||||
|
// TODO: make this send over scaffold page id too someday
|
||||||
|
const latestPage = model.getLatestScaffoldPage(db, req.params.route_id)
|
||||||
|
model.updateScaffoldPage(db, { ...latestPage, content: req.body.scaffold_page })
|
||||||
|
}
|
||||||
if (route.verb == "WS") {
|
if (route.verb == "WS") {
|
||||||
bootstrapWebsocketHandler({ ...route, ...req.body })
|
bootstrapWebsocketHandler({ ...route, ...req.body })
|
||||||
}
|
}
|
||||||
|
|
@ -575,11 +580,6 @@ app.put("/workshop/:structure_id/template/:template_id", (req, res) => {
|
||||||
app.get("/workshop/:structure_id/template/:template_id", (req, res) => {
|
app.get("/workshop/:structure_id/template/:template_id", (req, res) => {
|
||||||
const template = model.getTemplate(db, req.params.template_id);
|
const template = model.getTemplate(db, req.params.template_id);
|
||||||
|
|
||||||
console.log("wassup", {
|
|
||||||
template: template,
|
|
||||||
...sidebarStuff(db, req.params.structure_id),
|
|
||||||
});
|
|
||||||
|
|
||||||
return res.send(
|
return res.send(
|
||||||
bootstrapTemplateWithHTMXetc(
|
bootstrapTemplateWithHTMXetc(
|
||||||
eta.render("workshop/template", {
|
eta.render("workshop/template", {
|
||||||
|
|
@ -594,7 +594,6 @@ app.get("/workshop/:structure_id/template/:template_id/preview", (req, res) => {
|
||||||
const template = model.getTemplate(db, req.params.template_id);
|
const template = model.getTemplate(db, req.params.template_id);
|
||||||
const struct = model.getStructure(db, req.params.structure_id);
|
const struct = model.getStructure(db, req.params.structure_id);
|
||||||
const eta = model.getTemplater(req.params.structure_id);
|
const eta = model.getTemplater(req.params.structure_id);
|
||||||
console.log(template);
|
|
||||||
|
|
||||||
const context = vm.createContext({ it: null });
|
const context = vm.createContext({ it: null });
|
||||||
vm.runInContext(template.test_object, context);
|
vm.runInContext(template.test_object, context);
|
||||||
|
|
@ -621,22 +620,54 @@ app.get("/workshop/:structure_id/route/:id", (req, res) => {
|
||||||
db,
|
db,
|
||||||
req.params.structure_id,
|
req.params.structure_id,
|
||||||
).route_prefix;
|
).route_prefix;
|
||||||
let previewUrl = routePrefix
|
let previewUrl = null;
|
||||||
|
|
||||||
|
if (route["verb"] == "GET" ) {
|
||||||
|
previewUrl = routePrefix
|
||||||
? path.join(routePrefix || "", route.path)
|
? path.join(routePrefix || "", route.path)
|
||||||
: route.path;
|
: route.path;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
previewUrl = `/workshop/${req.params.structure_id}/route/${req.params.id}/preview`;
|
||||||
|
}
|
||||||
|
|
||||||
|
template = route["verb"] == "GET" ? "workshop/route" : "workshop/cud_route";
|
||||||
|
|
||||||
return res.send(
|
return res.send(
|
||||||
bootstrapTemplateWithHTMXetc(
|
bootstrapTemplateWithHTMXetc(
|
||||||
eta.render("workshop/route", {
|
eta.render(template, {
|
||||||
route: route,
|
route: route,
|
||||||
previewUrl:
|
previewUrl: previewUrl,
|
||||||
route["verb"] == "GET" ? previewUrl : "/workshop/do-something-here",
|
|
||||||
...sidebarStuff(db, req.params.structure_id),
|
...sidebarStuff(db, req.params.structure_id),
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.get("/workshop/:structure_id/route/:route_id/preview", (req, res) => {
|
||||||
|
const route = model.getRoute(db, req.params.route_id);
|
||||||
|
const struct = model.getStructure(db, req.params.structure_id);
|
||||||
|
|
||||||
|
const it = {
|
||||||
|
route: function (url) {
|
||||||
|
return struct.route_prefix ? path.join(struct.route_prefix, url) : url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(route)
|
||||||
|
|
||||||
|
return res.send(
|
||||||
|
bootstrapTemplateWithHTMXetc(
|
||||||
|
eta.renderString(route.scaffold_page_content, it),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
struct.head_injection,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
app.get("/workshop/:structure_id/route/:route_id/logs", (req, res) => {
|
app.get("/workshop/:structure_id/route/:route_id/logs", (req, res) => {
|
||||||
const since = req.query.since;
|
const since = req.query.since;
|
||||||
let logs = [];
|
let logs = [];
|
||||||
|
|
|
||||||
16
migrations/002_add_scaffold_stuff.sql
Normal file
16
migrations/002_add_scaffold_stuff.sql
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
CREATE TABLE scaffold_pages (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
route_id INTEGER NOT NULL,
|
||||||
|
content TEXT,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY(route_id) REFERENCES routes(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE scaffold_params (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
route_id INTEGER NOT NULL,
|
||||||
|
query_params JSON,
|
||||||
|
url_params JSON,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
FOREIGN KEY(route_id) REFERENCES routes(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
75
views/workshop/cud_route.eta
Normal file
75
views/workshop/cud_route.eta
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="/css/xp.css">
|
||||||
|
<script src="/js/ace/ace.js" type="text/javascript" charset="utf-8"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div class="flex flex-col w-full h-full window">
|
||||||
|
<div class="title-bar">
|
||||||
|
<div class="title-bar-text">Workshop - <%~ include('/workshop/structure_name', {structure: it.structure}) %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-row flex-grow window-body">
|
||||||
|
<div class="w-1/5 h-full">
|
||||||
|
<%~ include('/workshop/sidebar', it) %>
|
||||||
|
</div>
|
||||||
|
<div id="main-editor" class="flex flex-grow">
|
||||||
|
<div id="left-pane" class="w-1/2 flex-grow h-full flex flex-col">
|
||||||
|
Route
|
||||||
|
<div id="route-editor" class="w-full flex-grow"><%= it.route.handler %></div>
|
||||||
|
<input id="urlparams" name="urlparams">
|
||||||
|
<input id="queryparams" name="queryparams">
|
||||||
|
Test Page
|
||||||
|
<div id="scaffold-editor" class="w-full flex-grow"><%= it.route.scaffold_page_content %></div>
|
||||||
|
<button id="save-btn" type="submit">Save</button>
|
||||||
|
<button id="logs-btn" type="submit" _="on click toggle .hidden on #logs">Logs</button>
|
||||||
|
</div>
|
||||||
|
<pre id="logs" class="max-h-[50vh] overflow-scroll flex hidden" hx-get="/workshop/<%= it.structure.id %>/route/<%= it.route.id %>/logs" hx-trigger="load">
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div id="preview-area" class="w-1/2 h-full flex flex-col">
|
||||||
|
<form _="on submit halt the event then set #preview's contentWindow.location.href to #url's value">
|
||||||
|
<input id="url" class="w-full">
|
||||||
|
</form>
|
||||||
|
<iframe id="preview"
|
||||||
|
src="/workshop/<%= it.route.structure_id %>/route/<%= it.route.id %>/preview"
|
||||||
|
class="w-full flex-grow"
|
||||||
|
_="on load set #url's value to my contentWindow.location.href">
|
||||||
|
</iframe>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
const routeEditor = ace.edit("route-editor");
|
||||||
|
routeEditor.setTheme("ace/theme/monokai");
|
||||||
|
routeEditor.session.setMode("ace/mode/javascript");
|
||||||
|
|
||||||
|
const scaffoldEditor = ace.edit("scaffold-editor");
|
||||||
|
scaffoldEditor.setTheme("ace/theme/monokai");
|
||||||
|
scaffoldEditor.session.setMode("ace/mode/ejs");
|
||||||
|
|
||||||
|
document.getElementById('save-btn').onclick = function() {
|
||||||
|
fetch('/workshop/<%= it.structure.id %>/route/<%= it.route.id %>', {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded'
|
||||||
|
},
|
||||||
|
body: new URLSearchParams({
|
||||||
|
handler: routeEditor.getValue(),
|
||||||
|
scaffold_page: scaffoldEditor.getValue(),
|
||||||
|
}).toString()
|
||||||
|
}).then(response => {
|
||||||
|
if (response.ok) {
|
||||||
|
document.getElementById('preview').contentWindow.location.reload()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
<div id="editor" class="w-full flex-grow"><%= it.route.handler %></div>
|
<div id="editor" class="w-full flex-grow"><%= it.route.handler %></div>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<button id="save-btn" type="submit">Save</button>
|
<button id="save-btn" type="submit">Save</button>
|
||||||
<button id="save-btn" type="submit" _="on click toggle .hidden on #logs">Logs</button>
|
<button id="logs-btn" type="submit" _="on click toggle .hidden on #logs">Logs</button>
|
||||||
</div>
|
</div>
|
||||||
<pre id="logs" class="max-h-[50vh] overflow-scroll flex hidden" hx-get="/workshop/<%= it.structure.id %>/route/<%= it.route.id %>/logs" hx-trigger="load">
|
<pre id="logs" class="max-h-[50vh] overflow-scroll flex hidden" hx-get="/workshop/<%= it.structure.id %>/route/<%= it.route.id %>/logs" hx-trigger="load">
|
||||||
</pre>
|
</pre>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue