[IMP] playground: add download app feature

closes #60
This commit is contained in:
Géry Debongnie
2019-04-26 14:01:47 +02:00
parent 21cee6c0de
commit 02a0edb754
3 changed files with 66 additions and 12 deletions
+10 -7
View File
@@ -13,6 +13,8 @@ body {
.btn {
cursor: pointer;
padding: 5px;
margin: 5px;
}
/* APPLICATION ROOT ****************************************/
@@ -54,18 +56,20 @@ body {
.run-code {
margin-right: 12px;
height: 25px;
padding: 5px 10px;
border: 2px solid transparent;
opacity: 0.9;
background-position: center;
transition: background 0.5s;
}
.run-code:hover {
opacity: 1;
}
.run-code:active {
.flash {
background-position: center;
transition: background 0.5s;
}
.flash:active {
background-color: #41454a;
background-size: 100%;
transition: background 0s;
@@ -73,12 +77,10 @@ body {
.layout-selector {
font-size: 33px;
padding: 0px 3px;
margin-right: 17px;
cursor: pointer;
margin: 8px;
color: #cccccc;
transform: rotate(90deg);
padding: 0 5px;
}
.layout-selector.active {
@@ -99,6 +101,7 @@ body {
.tabBar {
color: white;
height: 22px;
width: 170px;
margin-top: -22px;
padding-left: 5px;
user-select: none;
+50
View File
@@ -1,5 +1,16 @@
import { SAMPLES } from "./samples.js";
let owlJS;
async function owlSourceCode() {
if (owlJS) {
return owlJS;
}
const result = await fetch("/playground/libs/owl.js");
owlJS = await result.text();
return owlJS;
}
const MODES = {
js: "ace/mode/javascript",
css: "ace/mode/css",
@@ -9,6 +20,22 @@ const MODES = {
const DEFAULT_XML = `<templates>
</templates>`;
const DEFAULT_HTML = `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>OWL App</title>
<link rel="icon" href="data:,">
<script src="owl.js"></script>
<link rel="stylesheet" href="app.css">
<script type="module" src="app.js"></script>
</head>
<body>
</body>
</html>
`;
//------------------------------------------------------------------------------
// Tabbed editor
//------------------------------------------------------------------------------
@@ -227,6 +254,29 @@ class App extends owl.Component {
}
this.state.topPanelHeight = height + ev.delta;
}
async downloadCode() {
await owl.utils.loadJS("/playground/libs/FileSaver.min.js");
await owl.utils.loadJS("/playground/libs/jszip.min.js");
const zip = new JSZip();
const JS = `async function startApp() {
const TEMPLATES = await owl.utils.loadTemplates('app.xml');
${this.state.js};
}
owl.utils.whenReady(startApp);`;
zip.file("app.js", JS);
zip.file("app.css", this.state.css);
zip.file("app.xml", this.state.xml);
zip.file("index.html", DEFAULT_HTML);
zip.file("owl.js", owlSourceCode());
zip.generateAsync({ type: "blob" }).then(function(content) {
saveAs(content, "app.zip");
});
}
}
//------------------------------------------------------------------------------
+6 -5
View File
@@ -1,9 +1,9 @@
<templates>
<div t-name="tabbed-editor" class="tabbed-editor" t-att-style="props.style">
<div class="tabBar" t-att-class="{resizeable: props.resizeable}" t-on-mousedown="onMouseDown">
<a t-if="tabs.js" class="tab" t-att-class="{active: state.currentTab==='js'}" t-on-click="setTab('js')">JS</a>
<a t-if="tabs.xml" class="tab" t-att-class="{active: state.currentTab==='xml'}" t-on-click="setTab('xml')">XML</a>
<a t-if="tabs.css" class="tab" t-att-class="{active: state.currentTab==='css'}" t-on-click="setTab('css')">CSS</a>
<a t-if="tabs.js" class="tab flash" t-att-class="{active: state.currentTab==='js'}" t-on-click="setTab('js')">JS</a>
<a t-if="tabs.xml" class="tab flash" t-att-class="{active: state.currentTab==='xml'}" t-on-click="setTab('xml')">XML</a>
<a t-if="tabs.css" class="tab flash" t-att-class="{active: state.currentTab==='css'}" t-on-click="setTab('css')">CSS</a>
</div>
<div class="code-editor" t-ref="'editor'"></div>
</div>
@@ -11,13 +11,14 @@
<div t-name="playground" class="playground">
<div class="left-bar" t-att-style="leftPaneStyle" t-att-class="{split: state.splitLayout}">
<div class="menubar">
<a class="btn run-code" t-on-click="runCode" title="Execute this Code">▶ Run</a>
<a class="btn run-code flash" t-on-click="runCode" title="Execute this Code">▶ Run</a>
<select t-on-change="setSample">
<option t-foreach="SAMPLES" t-as="sample" t-key="sample_index">
<t t-esc="sample.description"/>
</option>
</select>
<div class="layout-selector" t-att-class="{active:state.splitLayout}" t-on-click="toggleLayout" title="Toggle Layout"></div>
<a class="btn flash" t-on-click="downloadCode" title="Download a Zip with this Code"></a>
<a class="layout-selector flash" t-att-class="{active:state.splitLayout}" t-on-click="toggleLayout" title="Toggle Layout"></a>
</div>
<t t-if="!state.splitLayout">
<t t-widget="TabbedEditor" t-props="{js:state.js, css:state.css, xml: state.xml, display: 'js|xml|css'}" t-on-updateCode="updateCode"/>