Refactor solution

This commit is contained in:
Peter Stockings
2023-12-16 15:35:48 +11:00
parent 3545491b88
commit 6dda461404
5 changed files with 306 additions and 97 deletions

View File

@@ -1,95 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Function</title>
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,900&display=swap" rel="stylesheet" />
<script src="/static/js/tailwindcss@3.2.4.js"></script>
<script src="/static/js/htmx.min.js"></script>
<script src="/static/js/hyperscript.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.1/ace.min.js"
integrity="sha512-7QPOFYWq4euLbAVbG/o5YVgkotUdMiwFuFrVQc6lbqZuAcWnLp0sQ6JX2AIWqbm3wWrPuEfu9FqckItCgQzBWw=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.1/mode-javascript.min.js"
integrity="sha512-1OTGICMOnGWxRYfDZRUdv7qut0O8+9s7JPi6JNxlz1pdpHgDwPo1L0dzYKwftuIb0ossdBzWtkAlnyyYpIEp2A=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.1/theme-monokai.min.js"
integrity="sha512-g9yptARGYXbHR9r3kTKIAzF+vvmgEieTxuuUUcHC5tKYFpLR3DR+lsisH2KZJG2Nwaou8jjYVRdbbbBQI3Bo5w=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body class="bg-gray-100 font-roboto">
<div class="container mx-auto p-4">
<h1 class="text-4xl font-bold text-gray-800 mb-2">Function</h1>
<h5 class="text-xl text-gray-500 mb-4">Create your own javascript HTTP handler</h5>
<div id="editor" class="relative rounded-lg shadow-lg bg-white p-4 mb-4" style="height: 300px;">async (req) => {
console.log('hello world...')
return HtmlResponse(`<h1>${req.method}</h1>`)
}</div>
<button id="executeBtn" class="mb-4 bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Execute
</button>
<div id="output" class="relative rounded-lg shadow-lg bg-black text-white p-4"
style="height: 200px; overflow-y: scroll;">
<!-- Execution results will appear here -->
</div>
<script>
var editor = ace.edit("editor");
editor.setTheme("ace/theme/monokai");
editor.session.setMode("ace/mode/javascript");
editor.session.$worker.send("changeOptions", [{ asi: true }]);
document.getElementById('executeBtn').addEventListener('click', function () {
try {
// Get the code from the editor
var code = editor.getValue();
// Define the request object (modify as needed)
var requestObject = {
// Your request object properties here
};
// Send the code and request object to the server
fetch('/execute?playground=true', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ code: code, request: requestObject }),
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.text();
})
.then(data => {
try {
const data = JSON.parse(data); // Try to parse the response as JSON
// The response was a JSON object
document.getElementById('output').textContent = JSON.stringify(data, null, 2);
} catch (err) {
document.getElementById('output').innerHTML = data;
}
})
.catch(error => {
document.getElementById('output').textContent = 'Error: ' + error.message;
});
} catch (e) {
document.getElementById('output').innerHTML = 'Error: ' + e.message;
}
});
</script>
</body>

32
templates/base.html Normal file
View File

@@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Function</title>
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,900&display=swap" rel="stylesheet" />
<script src="/static/js/tailwindcss@3.2.4.js"></script>
<script src="/static/js/htmx.min.js"></script>
<script src="/static/js/hyperscript.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.1/ace.min.js"
integrity="sha512-7QPOFYWq4euLbAVbG/o5YVgkotUdMiwFuFrVQc6lbqZuAcWnLp0sQ6JX2AIWqbm3wWrPuEfu9FqckItCgQzBWw=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.1/mode-javascript.min.js"
integrity="sha512-1OTGICMOnGWxRYfDZRUdv7qut0O8+9s7JPi6JNxlz1pdpHgDwPo1L0dzYKwftuIb0ossdBzWtkAlnyyYpIEp2A=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.1/theme-monokai.min.js"
integrity="sha512-g9yptARGYXbHR9r3kTKIAzF+vvmgEieTxuuUUcHC5tKYFpLR3DR+lsisH2KZJG2Nwaou8jjYVRdbbbBQI3Bo5w=="
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body class="bg-gray-100 font-roboto">
<div class="container mx-auto p-4">
{% block content %}
{% endblock %}
</body>

156
templates/client.html Normal file
View File

@@ -0,0 +1,156 @@
{% extends 'base.html' %}
{% block content %}
<div class="mx-auto w-full">
<form class="flex"><select
class="px-4 py-2 border rounded-md border-gray-300 hover:border-orange-500 focus:outline-none bg-gray-100">
<option value="GET">GET</option>
<option value="POST">POST</option>
<option value="PUT">PUT</option>
<option value="PATCH">PATCH</option>
<option value="DELETE">DELETE</option>
</select><input
class="ml-3 w-full px-4 py-2 border rounded-md border-gray-300 hover:border-orange-500 focus:outline-orange-500"
value="https://function.peterstockings.com/f/helloworld"><button
class="ml-3 px-6 py-2 rounded-md font-semibold text-white bg-orange-500 hover:bg-orange-600"
type="button">Send</button></form>
<div class="react-tabs" data-rttabs="true">
<ul class="flex mt-5 border border-gray-300 rounded-t-lg" role="tablist">
<li class="mr-3 py-2 px-4 border-orange-400 focus:outline-none
hover:text-orange-500 cursor-pointer border-b-2 text-orange-600" role="tab" id="tab:r0:0" aria-selected="true"
aria-disabled="false" aria-controls="panel:r0:0" tabindex="0" data-rttab="true">Query Params</li>
<li class="mr-3 py-2 px-4 border-orange-400 focus:outline-none
hover:text-orange-500 cursor-pointer" role="tab" id="tab:r0:1" aria-selected="false" aria-disabled="false"
aria-controls="panel:r0:1" data-rttab="true">Headers</li>
<li class="mr-3 py-2 px-4 border-orange-400 focus:outline-none
hover:text-orange-500 cursor-pointer" role="tab" id="tab:r0:2" aria-selected="false" aria-disabled="false"
aria-controls="panel:r0:2" data-rttab="true">Body</li>
</ul>
<div class="react-tabs__tab-panel px-4 py-4 rounded-b-lg border border-t-0 border-gray-300 react-tabs__tab-panel--selected"
role="tabpanel" id="panel:r0:0" aria-labelledby="tab:r0:0">
<div class="">
<div class="flex mb-3"><input
class="px-4 py-1.5 w-full border border-gray-300 rounded-md hover:border-orange-500 focus:outline-orange-500"
placeholder="Key" name="keyItem"><input
class="ml-3 px-4 py-1.5 w-full border border-gray-300 rounded-md hover:border-orange-500 focus:outline-orange-500"
placeholder="Value" name="valueItem"><button
class="ml-4 px-4 rounded-md text-red-500 border border-red-300 hover:bg-red-100">Remove</button>
</div><button
class="px-6 py-1 rounded-md text-orange-600 border border-orange-400 hover:bg-orange-100">Add</button>
</div>
</div>
<div class="react-tabs__tab-panel px-4 py-4 rounded-b-lg border border-t-0 border-gray-300" role="tabpanel"
id="panel:r0:1" aria-labelledby="tab:r0:1">
<div class="">
<div class="flex mb-3"><input
class="px-4 py-1.5 w-full border border-gray-300 rounded-md hover:border-orange-500 focus:outline-orange-500"
placeholder="Key" name="keyItem"><input
class="ml-3 px-4 py-1.5 w-full border border-gray-300 rounded-md hover:border-orange-500 focus:outline-orange-500"
placeholder="Value" name="valueItem"><button
class="ml-4 px-4 rounded-md text-red-500 border border-red-300 hover:bg-red-100">Remove</button>
</div><button
class="px-6 py-1 rounded-md text-orange-600 border border-orange-400 hover:bg-orange-100">Add</button>
</div>
</div>
<div class="react-tabs__tab-panel px-4 py-4 rounded-b-lg border border-t-0 border-gray-300" role="tabpanel"
id="panel:r0:2" aria-labelledby="tab:r0:2">
<div>
<div class="cm-editor cm-wrap ͼ1 ͼ2 ͼ4">
<div aria-live="polite" style="position: absolute; top: -10000px;"></div>
<div tabindex="-1" class="cm-scroller">
<div class="cm-gutters" aria-hidden="true" style="position: sticky; min-height: 42px;">
<div class="cm-gutter cm-lineNumbers">
<div class="cm-gutterElement"
style="height: 0px; visibility: hidden; pointer-events: none;">9</div>
<div class="cm-gutterElement cm-activeLineGutter" style="height: 14px;">1</div>
<div class="cm-gutterElement" style="height: 14px;">2</div>
<div class="cm-gutterElement" style="height: 14px;">3</div>
</div>
<div class="cm-gutter cm-foldGutter">
<div class="cm-gutterElement"
style="height: 0px; visibility: hidden; pointer-events: none;"><span
title="Unfold line"></span></div>
<div class="cm-gutterElement cm-activeLineGutter" style="height: 14px;"></div>
</div>
</div>
<div spellcheck="false" autocorrect="off" autocapitalize="off" contenteditable="true"
class="cm-content" style="tab-size: 2" role="textbox" aria-multiline="true"
aria-autocomplete="list">
<div class="cm-activeLine cm-line">{</div>
<div class="cm-line"> </div>
<div class="cm-line">}</div>
</div>
<div class="cm-selectionLayer" aria-hidden="true"></div>
<div class="cm-cursorLayer" aria-hidden="true" style="animation-duration: 1200ms;">
<div class="cm-cursor cm-cursor-primary" style="left: 0px; top: 0px; height: 0px;"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="my-4"><span class="text-2xl font-medium">Response</span>
<div class="react-tabs" data-rttabs="true">
<ul class="flex mt-5 border border-gray-300 rounded-t-lg" role="tablist">
<li class="mr-3 py-2 px-4 border-orange-400 focus:outline-none hover:text-orange-500 cursor-pointer border-b-2 text-orange-600"
role="tab" id="tab:r1:0" aria-selected="true" aria-disabled="false" aria-controls="panel:r1:0"
tabindex="0" data-rttab="true">Response Body</li>
<li class="mr-3 py-2 px-4 border-orange-400 focus:outline-none hover:text-orange-500 cursor-pointer"
role="tab" id="tab:r1:1" aria-selected="false" aria-disabled="false" aria-controls="panel:r1:1"
data-rttab="true">Response Header</li>
</ul>
<div class="px-4 py-4 rounded-b-lg border border-t-0 border-gray-300">
<div class="react-tabs__tab-panel react-tabs__tab-panel--selected" role="tabpanel" id="panel:r1:0"
aria-labelledby="tab:r1:0">
<div>
<div class="cm-editor cm-wrap ͼ1 ͼ2 ͼ4">
<div aria-live="polite" style="position: absolute; top: -10000px;"></div>
<div tabindex="-1" class="cm-scroller">
<div class="cm-gutters" aria-hidden="true"
style="position: sticky; min-height: 26.1979px;">
<div class="cm-gutter cm-lineNumbers">
<div class="cm-gutterElement"
style="height: 0px; visibility: hidden; pointer-events: none;">9</div>
<div class="cm-gutterElement cm-activeLineGutter"
style="height: 18.1979px; margin-top: 4px;">1</div>
</div>
<div class="cm-gutter cm-foldGutter">
<div class="cm-gutterElement"
style="height: 0px; visibility: hidden; pointer-events: none;"><span
title="Unfold line"></span></div>
<div class="cm-gutterElement cm-activeLineGutter"
style="height: 18.1979px; margin-top: 4px;"></div>
</div>
</div>
<div spellcheck="false" autocorrect="off" autocapitalize="off" contenteditable="false"
class="cm-content" style="tab-size: 2" role="textbox" aria-multiline="true"
aria-autocomplete="list">
<div class="cm-activeLine cm-line">{}</div>
</div>
<div class="cm-selectionLayer" aria-hidden="true"></div>
<div class="cm-cursorLayer" aria-hidden="true" style="animation-duration: 1200ms;">
<div class="cm-cursor cm-cursor-primary"
style="left: 33.8229px; top: 5.33334px; height: 15.3333px;"></div>
</div>
</div>
</div>
</div>
</div>
<div class="react-tabs__tab-panel" role="tabpanel" id="panel:r1:1" aria-labelledby="tab:r1:1">
<table class="text-left">
<thead>
<tr>
<th class="w-36 pb-1.5">Key</th>
<th class="w-60">Value</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

87
templates/home.html Normal file
View File

@@ -0,0 +1,87 @@
{% extends 'base.html' %}
{% block content %}
<h1 class="text-4xl font-bold text-gray-800 mb-2">Function</h1>
<h5 class="text-xl text-gray-500 mb-4">Create your own javascript HTTP handler</h5>
<div id="editor" class="relative rounded-lg shadow-lg bg-white p-4 mb-4" style="height: 300px;">{{ script }}
</div>
<button id="executeBtn" class="mb-4 bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Execute
</button>
<div id="output" class="relative rounded-lg shadow-lg bg-black text-white p-4">
<!-- Execution results will appear here -->
</div>
<aside class="bg-black text-white p-6 rounded-lg w-full max-w-lg font-mono mt-4" data-id="1">
<div class="flex justify-between items-center" data-id="2">
<div class="flex space-x-2 text-red-500" data-id="3">
<div class="w-3 h-3 rounded-full bg-red-500" data-id="4"></div>
<div class="w-3 h-3 rounded-full bg-yellow-500" data-id="5"></div>
<div class="w-3 h-3 rounded-full bg-green-500" data-id="6"></div>
</div>
<p class="text-sm" data-id="7">logs</p>
</div>
<div class="mt-4" data-id="8" id="response-logs">
</div>
</aside>
<script>
var editor = ace.edit("editor");
editor.setTheme("ace/theme/monokai");
editor.session.setMode("ace/mode/javascript");
editor.session.$worker.send("changeOptions", [{ asi: true }]);
document.getElementById('executeBtn').addEventListener('click', function () {
try {
// Get the code from the editor
var code = editor.getValue();
// Define the request object (modify as needed)
var requestObject = {
// Your request object properties here
};
// Send the code and request object to the server
fetch('/execute?playground=true', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ code: code, request: requestObject }),
})
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return response.text();
})
.then(text => {
try {
const data = JSON.parse(text); // Try to parse the response as JSON
const logs_el = document.querySelector('#response-logs');
logs_el.innerHTML = data.logs.map(log => `<p class="text-white" data-id="11">${log}</p>`).join('\n');
document.getElementById('output').innerHTML = data.result.body;
} catch (err) {
document.getElementById('output').innerHTML = data;
}
})
.catch(error => {
document.getElementById('output').textContent = 'Error: ' + error.message;
});
} catch (e) {
document.getElementById('output').innerHTML = 'Error: ' + e.message;
}
});
</script>
{% endblock %}