mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
ref: split app widget in 2
This commit is contained in:
+29
-20
@@ -29,20 +29,44 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.menubar {
|
.menubar {
|
||||||
padding-left: 8px;
|
|
||||||
background-color: #1c2128;
|
background-color: #1c2128;
|
||||||
color: white;
|
color: white;
|
||||||
line-height: 50px;
|
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menubar select {
|
||||||
|
margin-right: 15px;
|
||||||
|
font-size: 16px;
|
||||||
|
height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.run-code {
|
||||||
|
margin-right: 12px;
|
||||||
|
height: 25px;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
}
|
||||||
|
.run-code:hover {
|
||||||
|
border-bottom: 2px solid gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TABBED EDITOR ****************************************/
|
||||||
|
|
||||||
|
.tabBar {
|
||||||
|
color: white;
|
||||||
|
height: 22px;
|
||||||
|
margin-top: -22px;
|
||||||
|
padding-left: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab {
|
.tab {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
vertical-align: -9px;
|
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
line-height: 26px;
|
line-height: 20px;
|
||||||
width: 34px;
|
width: 34px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
@@ -55,24 +79,9 @@ body {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.right-thing {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.right-thing select {
|
|
||||||
margin-right: 15px;
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
.run-code {
|
|
||||||
margin-right: 12px;
|
|
||||||
padding: 4px;
|
|
||||||
}
|
|
||||||
.run-code:hover {
|
|
||||||
border-bottom: 2px solid gray;
|
|
||||||
}
|
|
||||||
|
|
||||||
.code-editor {
|
.code-editor {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
|
height: calc(100% - 10px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SEPARATOR ****************************************/
|
/* SEPARATOR ****************************************/
|
||||||
|
|||||||
+83
-42
@@ -11,23 +11,87 @@ const MODES = {
|
|||||||
const DEFAULT_XML = `<templates>
|
const DEFAULT_XML = `<templates>
|
||||||
</templates>`;
|
</templates>`;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Tabbed editor
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
const EDITOR_TEMPLATE = `
|
||||||
|
<div class="tabbed-editor">
|
||||||
|
<div class="tabBar">
|
||||||
|
<a class="tab" t-att-class="{active: state.currentTab==='js'}" t-on-click="setTab('js')">JS</a>
|
||||||
|
<a class="tab" t-att-class="{active: state.currentTab==='xml'}" t-on-click="setTab('xml')">XML</a>
|
||||||
|
<a class="tab" t-att-class="{active: state.currentTab==='css'}" t-on-click="setTab('css')">CSS</a>
|
||||||
|
</div>
|
||||||
|
<div class="code-editor" t-ref="editor"></div>
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
class TabbedEditor extends Component {
|
||||||
|
constructor() {
|
||||||
|
super(...arguments);
|
||||||
|
this.inlineTemplate = EDITOR_TEMPLATE;
|
||||||
|
this.state = {
|
||||||
|
currentTab: "js"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.editor = ace.edit(this.refs.editor);
|
||||||
|
|
||||||
|
// remove this for xml/css (?)
|
||||||
|
this.editor.session.setOption("useWorker", false);
|
||||||
|
this.editor.setValue(this.props.js, -1);
|
||||||
|
this.editor.setFontSize("14px");
|
||||||
|
this.editor.setTheme("ace/theme/monokai");
|
||||||
|
this.editor.session.setMode("ace/mode/javascript");
|
||||||
|
this.editor.on("blur", () => {
|
||||||
|
const editorValue = this.editor.getValue();
|
||||||
|
const propsValue = this.props[this.state.currentTab];
|
||||||
|
if (editorValue !== propsValue) {
|
||||||
|
this.trigger("updateCode", {
|
||||||
|
type: this.state.currentTab,
|
||||||
|
value: editorValue
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateProps() {
|
||||||
|
const result = super.updateProps(...arguments);
|
||||||
|
if (this.editor) {
|
||||||
|
this.editor.setValue(this.props[this.state.currentTab], -1);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
willUnmount() {
|
||||||
|
this.editor.destroy();
|
||||||
|
delete this.editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTab(tab) {
|
||||||
|
this.editor.setValue(this.props[tab], -1);
|
||||||
|
|
||||||
|
const mode = MODES[tab];
|
||||||
|
this.editor.session.setMode(mode);
|
||||||
|
this.updateState({ currentTab: tab });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// MAIN APP
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
const TEMPLATE = `
|
const TEMPLATE = `
|
||||||
<div class="playground">
|
<div class="playground">
|
||||||
<div class="left-bar" t-att-style="leftPaneStyle">
|
<div class="left-bar" t-att-style="leftPaneStyle">
|
||||||
<div class="menubar">
|
<div class="menubar">
|
||||||
<a class="tab" t-att-class="{active: state.currentTab==='js'}" t-on-click="setTab('js')">JS</a>
|
<a class="btn run-code" t-on-click="runCode">▶ Run</a>
|
||||||
<a class="tab" t-att-class="{active: state.currentTab==='xml'}" t-on-click="setTab('xml')">XML</a>
|
<select t-on-change="setSample">
|
||||||
<a class="tab" t-att-class="{active: state.currentTab==='css'}" t-on-click="setTab('css')">CSS</a>
|
<option t-foreach="SAMPLES" t-as="sample">
|
||||||
<div class="right-thing">
|
<t t-esc="sample.description"/>
|
||||||
<select t-on-change="setSample">
|
</option>
|
||||||
<option t-foreach="SAMPLES" t-as="sample">
|
</select>
|
||||||
<t t-esc="sample.description"/>
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
<a class="btn run-code" t-on-click="runCode">▶ Run</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="code-editor" t-ref="editor"></div>
|
<t t-widget="TabbedEditor" t-props="{js:state.js, css:state.css, xml: state.xml}" t-on-updateCode="updateCode"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="separator horizontal" t-on-mousedown="onMouseDown"/>
|
<div class="separator horizontal" t-on-mousedown="onMouseDown"/>
|
||||||
<div class="right-pane" t-att-style="rightPaneStyle">
|
<div class="right-pane" t-att-style="rightPaneStyle">
|
||||||
@@ -50,6 +114,8 @@ class App extends Component {
|
|||||||
this.version = owl._version;
|
this.version = owl._version;
|
||||||
this.SAMPLES = SAMPLES;
|
this.SAMPLES = SAMPLES;
|
||||||
this.inlineTemplate = TEMPLATE;
|
this.inlineTemplate = TEMPLATE;
|
||||||
|
this.widgets = { TabbedEditor };
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
currentTab: "js",
|
currentTab: "js",
|
||||||
js: SAMPLES[0].code,
|
js: SAMPLES[0].code,
|
||||||
@@ -57,22 +123,11 @@ class App extends Component {
|
|||||||
xml: SAMPLES[0].xml || DEFAULT_XML,
|
xml: SAMPLES[0].xml || DEFAULT_XML,
|
||||||
error: false,
|
error: false,
|
||||||
displayWelcome: true,
|
displayWelcome: true,
|
||||||
leftPaneWidth: window.innerWidth / 2
|
leftPaneWidth: Math.ceil(window.innerWidth / 2)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
mounted() {
|
|
||||||
this.editor = ace.edit(this.refs.editor);
|
|
||||||
this.editor.session.setOption("useWorker", false);
|
|
||||||
this.editor.setValue(this.state.js, -1);
|
|
||||||
this.editor.setFontSize("14px");
|
|
||||||
this.editor.setTheme("ace/theme/monokai");
|
|
||||||
this.editor.session.setMode("ace/mode/javascript");
|
|
||||||
}
|
|
||||||
|
|
||||||
async runCode() {
|
async runCode() {
|
||||||
this.updateStateFromEditor();
|
|
||||||
|
|
||||||
// check templates
|
// check templates
|
||||||
var qweb = new owl.core.QWeb();
|
var qweb = new owl.core.QWeb();
|
||||||
var error = false;
|
var error = false;
|
||||||
@@ -124,23 +179,6 @@ class App extends Component {
|
|||||||
css: sample.css || "",
|
css: sample.css || "",
|
||||||
xml: sample.xml || DEFAULT_XML
|
xml: sample.xml || DEFAULT_XML
|
||||||
});
|
});
|
||||||
this.editor.setValue(this.state[this.state.currentTab], -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
updateStateFromEditor() {
|
|
||||||
const value = this.editor.getValue();
|
|
||||||
this.updateState({
|
|
||||||
[this.state.currentTab]: value
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setTab(tab) {
|
|
||||||
this.updateStateFromEditor();
|
|
||||||
this.editor.setValue(this.state[tab], -1);
|
|
||||||
|
|
||||||
const mode = MODES[tab];
|
|
||||||
this.editor.session.setMode(mode);
|
|
||||||
this.updateState({ currentTab: tab });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get leftPaneStyle() {
|
get leftPaneStyle() {
|
||||||
@@ -148,7 +186,7 @@ class App extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get rightPaneStyle() {
|
get rightPaneStyle() {
|
||||||
return `width:${window.innerWidth - 5 - this.state.leftPaneWidth}px`;
|
return `width:${window.innerWidth - 6 - this.state.leftPaneWidth}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseDown(ev) {
|
onMouseDown(ev) {
|
||||||
@@ -168,6 +206,9 @@ class App extends Component {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
updateCode(ev) {
|
||||||
|
this.state[ev.type] = ev.value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user