You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
258 lines
5.8 KiB
258 lines
5.8 KiB
2 years ago
|
<script>
|
||
|
import template from "lodash/template";
|
||
|
import { fade } from "svelte/transition";
|
||
|
import Icon from "$/client/components/Icon.svelte";
|
||
|
import { log } from "$/client/logging.js";
|
||
|
import Layout from "../Layout.svelte";
|
||
|
import api from '$/client/api.js';
|
||
|
import { onMount } from "svelte";
|
||
|
|
||
|
export let selected_template;
|
||
|
|
||
|
let showing_rendered = false;
|
||
|
let results = "";
|
||
|
let source = "";
|
||
|
let variable_json = "{ }";
|
||
|
let generators = [];
|
||
|
|
||
|
let variables = {};
|
||
|
let renderer = () => source;
|
||
|
let notice = "";
|
||
|
let last_good = "";
|
||
|
|
||
|
const list_generators = async () => {
|
||
|
let [status, data] = await api.get('/api/devtools/djenterator');
|
||
|
|
||
|
if(status == 200) {
|
||
|
generators = data;
|
||
|
selected_template = generators[0];
|
||
|
} else {
|
||
|
log.debug("failed to load generators", status);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const render_template = () => {
|
||
|
try {
|
||
|
// avoid rendering when the current template doesn't match the renderer
|
||
|
if(selected_template == renderer._template) {
|
||
|
variables = variable_json ? JSON.parse(variable_json): {};
|
||
|
results = renderer(variables);
|
||
|
notice = "";
|
||
|
last_good = results;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
} catch(err) {
|
||
|
notice = err.message;
|
||
|
results = last_good;
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const load_variables = async (template_name) => {
|
||
|
let res = await fetch(`/djenterator/${template_name}.vars`);
|
||
|
|
||
|
if(res.status == 200) {
|
||
|
variable_json = await res.text();
|
||
|
} else {
|
||
|
variable_json = '{}';
|
||
|
notice = `No ${template_name}.vars file found. ${res.status}`;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const load_template = async (template_name) => {
|
||
|
let res = await fetch(`/djenterator/${template_name}`);
|
||
|
|
||
|
if(res.status == 200) {
|
||
|
source = await res.text();
|
||
|
last_good = source;
|
||
|
try {
|
||
|
renderer = template(source);
|
||
|
// tag this template renderer so that we don't try to render it against the wrong one
|
||
|
renderer._template = template_name;
|
||
|
render_template();
|
||
|
} catch(error) {
|
||
|
log.error(error);
|
||
|
notice = `${error.message}`;
|
||
|
results = source;
|
||
|
}
|
||
|
} else {
|
||
|
notice = `Error loading ${template_name}: ${res.status}`;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const toggle_template = () => {
|
||
|
if(showing_rendered) {
|
||
|
render_template();
|
||
|
} else {
|
||
|
results = renderer.toString();
|
||
|
}
|
||
|
|
||
|
showing_rendered = !showing_rendered;
|
||
|
}
|
||
|
|
||
|
const copy_code = () => {
|
||
|
navigator.clipboard.writeText(results).then(() => {
|
||
|
notice = "Code copied to clipboard.";
|
||
|
}, () => {
|
||
|
notice = "Failed copying to clipboard.";
|
||
|
});
|
||
|
}
|
||
|
|
||
|
const canary = '3a025dba-1a62-4169-ae9f-f7cd4104c4f4';
|
||
|
log.debug("Canary is compiled into build as", canary);
|
||
|
|
||
|
$: if(variable_json) render_template();
|
||
|
|
||
|
// this reload the templates when you click on a new one
|
||
|
const re_render = async (what) => {
|
||
|
await load_variables(what);
|
||
|
await load_template(what);
|
||
|
}
|
||
|
|
||
|
$: if(selected_template) re_render(selected_template);
|
||
|
|
||
|
onMount(async () => await list_generators());
|
||
|
</script>
|
||
|
|
||
|
<style>
|
||
|
content {
|
||
|
display: flex;
|
||
|
flex-direction: row;
|
||
|
width: 100%;
|
||
|
}
|
||
|
|
||
|
template-editor {
|
||
|
display: flex;
|
||
|
flex-direction: column;
|
||
|
width: 100%;
|
||
|
align-items: center;
|
||
|
}
|
||
|
|
||
|
pre {
|
||
|
position: relative;
|
||
|
height: 90vh;
|
||
|
max-height: 90vh;
|
||
|
overflow-y: auto;
|
||
|
}
|
||
|
|
||
|
right pre {
|
||
|
display: flex;
|
||
|
font-size: 1em;
|
||
|
flex-basis: 100%;
|
||
|
margin: 0;
|
||
|
padding: 0;
|
||
|
}
|
||
|
|
||
|
right pre code {
|
||
|
padding-top: 2rem;
|
||
|
display: flex;
|
||
|
flex-basis: 100%;
|
||
|
border-radius: 0px 4px 4px 0px;
|
||
|
line-height: unset;
|
||
|
margin: 0;
|
||
|
}
|
||
|
|
||
|
left {
|
||
|
display: flex;
|
||
|
flex-grow: 1;
|
||
|
flex-basis: 70ch;
|
||
|
}
|
||
|
|
||
|
left textarea {
|
||
|
border-radius: 4px 0px 0px 4px;
|
||
|
margin: 0;
|
||
|
background-color: var(--color-secondary);
|
||
|
color: var(--color-bg);
|
||
|
height: 90vh;
|
||
|
max-height: 90vh;
|
||
|
}
|
||
|
|
||
|
right {
|
||
|
position: relative;
|
||
|
display: flex;
|
||
|
flex-direction: column;
|
||
|
flex-grow: 3;
|
||
|
flex-basis: 100ch;
|
||
|
align-items: stretch;
|
||
|
}
|
||
|
|
||
|
status {
|
||
|
position: absolute;
|
||
|
z-index: 100;
|
||
|
top: 0;
|
||
|
padding-right: 1rem;
|
||
|
padding-left: 1rem;
|
||
|
padding-top: 0.1rem;
|
||
|
width: 90%;
|
||
|
color: var(--color-bg);
|
||
|
display: flex;
|
||
|
box-sizing: border-box;
|
||
|
background-color: var(--color-secondary);
|
||
|
border-radius: 0px 4px 0px 0px;
|
||
|
justify-content: space-evenly;
|
||
|
}
|
||
|
|
||
|
status file {
|
||
|
flex-basis: 90%;
|
||
|
text-align: right;
|
||
|
}
|
||
|
|
||
|
status buttons {
|
||
|
display: flex;
|
||
|
justify-content: space-around;
|
||
|
flex-basis: 10%;
|
||
|
padding-top: 0.5rem;
|
||
|
}
|
||
|
|
||
|
pre notice {
|
||
|
position: absolute;
|
||
|
bottom: 0;
|
||
|
left: 0.3rem;
|
||
|
right: 0.3rem;
|
||
|
text-align: right;
|
||
|
padding: 0.5rem;
|
||
|
font-size: 1rem;
|
||
|
background-color: var(--color-bg-tertiary);
|
||
|
border-radius: 4px 4px 0px 0px;
|
||
|
}
|
||
|
</style>
|
||
|
|
||
|
<Layout fullscreen={ true } header={ false } testid="page-bando-djenterator">
|
||
|
<template-editor>
|
||
|
<select bind:value={ selected_template }>
|
||
|
{#each generators as template}
|
||
|
<option value={ template }>{ template }</option>
|
||
|
{/each}
|
||
|
</select>
|
||
|
|
||
|
<content>
|
||
|
<left>
|
||
|
<textarea class="editor" bind:value={ variable_json } rows="15"></textarea>
|
||
|
</left>
|
||
|
|
||
|
<right>
|
||
|
<status>
|
||
|
<buttons>
|
||
|
<span on:click={ copy_code }><Icon name="copy" size="24" color="var(--color-bg)" /></span>
|
||
|
<span on:click={ toggle_template }><Icon name="code" size="24" color="var(--color-bg)" /></span>
|
||
|
</buttons>
|
||
|
|
||
|
<file>static/djenterator/{ selected_template }</file>
|
||
|
</status>
|
||
|
<pre>
|
||
|
<code>
|
||
|
{results}
|
||
|
</code>
|
||
|
|
||
|
{#if notice}
|
||
|
<notice in:fade on:click={ () => notice = "" }>
|
||
|
<b>{ notice }</b>
|
||
|
</notice>
|
||
|
{/if}
|
||
|
</pre>
|
||
|
</right>
|
||
|
</content>
|
||
|
<template-editor>
|
||
|
</Layout>
|