mirror of
https://github.com/leporello-js/leporello-js
synced 2026-01-13 13:04:30 -08:00
change ui for entrypoint
This commit is contained in:
@@ -197,6 +197,9 @@ in production, you can do it like this:
|
|||||||
Leporello.js appends `?leporello` query parameter to your HTML file, so you can
|
Leporello.js appends `?leporello` query parameter to your HTML file, so you can
|
||||||
test if HTML file is run in Leporello.js or in production.
|
test if HTML file is run in Leporello.js or in production.
|
||||||
|
|
||||||
|
You can add javascript libraries by including `script` tag to HTML file. If the library is exposing globals, they will be available in your javascript code after you select that HTML file as an entrypoint.
|
||||||
|
|
||||||
|
|
||||||
## Run and debug UI code in separate window
|
## Run and debug UI code in separate window
|
||||||
|
|
||||||
By default your code is run in invisible iframe. If you want to run and debug
|
By default your code is run in invisible iframe. If you want to run and debug
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 166 KiB After Width: | Height: | Size: 437 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 475 KiB After Width: | Height: | Size: 925 KiB |
48
index.html
48
index.html
@@ -161,28 +161,6 @@
|
|||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.entrypoint_select {
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
width: fit-content;
|
|
||||||
align-items: center;
|
|
||||||
margin-left: auto;
|
|
||||||
min-height: 55px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.entrypoint_select select {
|
|
||||||
min-width: 20px;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.entrypoint_title {
|
|
||||||
margin-right: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.entrypoint_title:not(:first-child) {
|
|
||||||
margin-left: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.callnode {
|
.callnode {
|
||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
}
|
}
|
||||||
@@ -248,10 +226,20 @@
|
|||||||
margin-left: 0em !important;
|
margin-left: 0em !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.files .file_title {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
.files .file_title.active {
|
.files .file_title.active {
|
||||||
background-color: rgb(225, 244, 253);
|
background-color: rgb(225, 244, 253);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.files .file_title .select_entrypoint {
|
||||||
|
margin-left: auto;
|
||||||
|
width: 40px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
.files .file_title .icon {
|
.files .file_title .icon {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
@@ -259,13 +247,27 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.file_actions {
|
.file_actions {
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-evenly;
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
background-color: rgb(225 244 253 / 80%);
|
background-color: rgb(225 244 253 / 80%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.file_actions .file_action {
|
||||||
|
margin-right: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file_actions .select_entrypoint_title {
|
||||||
|
width: 40px;
|
||||||
|
position: absolute;
|
||||||
|
right: 7px;
|
||||||
|
font-size: 0.8em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
/* value_explorer */
|
/* value_explorer */
|
||||||
|
|
||||||
.embed_value_explorer_container {
|
.embed_value_explorer_container {
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import {el} from './domutils.js'
|
import {el} from './domutils.js'
|
||||||
import {map_find} from '../utils.js'
|
import {map_find} from '../utils.js'
|
||||||
import {load_dir, create_file} from '../filesystem.js'
|
import {load_dir, create_file} from '../filesystem.js'
|
||||||
import {exec, get_state, open_directory} from '../index.js'
|
import {exec, get_state, open_directory, reload_run_window} from '../index.js'
|
||||||
|
|
||||||
|
const is_html = path => path.endsWith('.htm') || path.endsWith('.html')
|
||||||
|
const is_js = path => path == '' || path.endsWith('.js') || path.endsWith('.mjs')
|
||||||
|
|
||||||
export class Files {
|
export class Files {
|
||||||
constructor(ui) {
|
constructor(ui) {
|
||||||
@@ -10,6 +13,18 @@ export class Files {
|
|||||||
this.render(get_state())
|
this.render(get_state())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
change_entrypoint(e) {
|
||||||
|
const file = e.target.value
|
||||||
|
exec('change_entrypoint', file)
|
||||||
|
this.ui.editor.focus()
|
||||||
|
}
|
||||||
|
|
||||||
|
change_html_file(e) {
|
||||||
|
const html_file = e.target.value
|
||||||
|
exec('change_html_file', html_file)
|
||||||
|
reload_run_window(get_state())
|
||||||
|
}
|
||||||
|
|
||||||
render(state) {
|
render(state) {
|
||||||
if(state.project_dir == null) {
|
if(state.project_dir == null) {
|
||||||
this.el.innerHTML = ''
|
this.el.innerHTML = ''
|
||||||
@@ -25,32 +40,40 @@ export class Files {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
this.render_files(state.project_dir, state.current_module)
|
this.render_files(state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render_files(dir, current_module) {
|
render_files(state) {
|
||||||
const files = this.el.querySelector('.files')
|
|
||||||
|
|
||||||
const children = [
|
const children = [
|
||||||
this.render_file({name: '*scratch*', path: ''}, current_module),
|
this.render_file({name: '*scratch*', path: ''}, state),
|
||||||
this.render_file(dir, current_module),
|
this.render_file(state.project_dir, state),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const files = this.el.querySelector('.files')
|
||||||
|
|
||||||
if(files == null) {
|
if(files == null) {
|
||||||
this.el.innerHTML = ''
|
this.el.innerHTML = ''
|
||||||
this.el.appendChild(
|
this.el.appendChild(
|
||||||
el('div', 'file_actions',
|
el('div', 'file_actions',
|
||||||
el('a', {
|
el('a', {
|
||||||
|
'class': 'file_action',
|
||||||
href: 'javascript: void(0)',
|
href: 'javascript: void(0)',
|
||||||
click: this.create_file.bind(this, false),
|
click: this.create_file.bind(this, false),
|
||||||
},
|
},
|
||||||
'Create file'
|
'Create file'
|
||||||
),
|
),
|
||||||
el('a', {
|
el('a', {
|
||||||
|
'class': 'file_action',
|
||||||
href: 'javascript: void(0)',
|
href: 'javascript: void(0)',
|
||||||
click: this.create_file.bind(this, true),
|
click: this.create_file.bind(this, true),
|
||||||
}, 'Create dir'),
|
}, 'Create dir'),
|
||||||
|
el('a', {
|
||||||
|
href: 'https://github.com/leporello-js/leporello-js#selecting-entrypoint-module',
|
||||||
|
target: '__blank',
|
||||||
|
"class": 'select_entrypoint_title',
|
||||||
|
title: 'Select entrypoint',
|
||||||
|
}, 'Entry point'),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
this.el.appendChild(
|
this.el.appendChild(
|
||||||
@@ -64,10 +87,40 @@ export class Files {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render_file(file, current_module) {
|
render_select_entrypoint(file, state) {
|
||||||
|
if(file.kind == 'directory') {
|
||||||
|
return null
|
||||||
|
} else if(is_js(file.path)) {
|
||||||
|
return el('span', 'select_entrypoint',
|
||||||
|
el('input', {
|
||||||
|
type: 'radio',
|
||||||
|
name: 'js_entrypoint',
|
||||||
|
value: file.path,
|
||||||
|
checked: state.entrypoint == file.path,
|
||||||
|
change: e => this.change_entrypoint(e),
|
||||||
|
click: e => e.stopPropagation(),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
} else if(is_html(file.path)) {
|
||||||
|
return el('span', 'select_entrypoint',
|
||||||
|
el('input', {
|
||||||
|
type: 'radio',
|
||||||
|
name: 'html_file',
|
||||||
|
value: file.path,
|
||||||
|
checked: state.html_file == file.path,
|
||||||
|
change: e => this.change_html_file(e),
|
||||||
|
click: e => e.stopPropagation(),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render_file(file, state) {
|
||||||
const result = el('div', 'file',
|
const result = el('div', 'file',
|
||||||
el('div', {
|
el('div', {
|
||||||
'class': 'file_title' + (file.path == current_module ? ' active' : ''),
|
'class': 'file_title' + (file.path == state.current_module ? ' active' : ''),
|
||||||
click: e => this.on_click(e, file)
|
click: e => this.on_click(e, file)
|
||||||
},
|
},
|
||||||
el('span', 'icon',
|
el('span', 'icon',
|
||||||
@@ -76,13 +129,14 @@ export class Files {
|
|||||||
: '\xa0',
|
: '\xa0',
|
||||||
),
|
),
|
||||||
file.name,
|
file.name,
|
||||||
|
this.render_select_entrypoint(file, state),
|
||||||
),
|
),
|
||||||
file.children == null
|
file.children == null
|
||||||
? null
|
? null
|
||||||
: file.children.map(c => this.render_file(c, current_module))
|
: file.children.map(c => this.render_file(c, state))
|
||||||
)
|
)
|
||||||
|
|
||||||
if(file.path == current_module) {
|
if(file.path == state.current_module) {
|
||||||
this.active_el = result
|
this.active_el = result
|
||||||
this.active_file = file
|
this.active_file = file
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {exec, get_state, open_run_window, reload_run_window} from '../index.js'
|
import {exec, get_state, open_run_window} from '../index.js'
|
||||||
import {Editor} from './editor.js'
|
import {Editor} from './editor.js'
|
||||||
import {Files} from './files.js'
|
import {Files} from './files.js'
|
||||||
import {CallTree} from './calltree.js'
|
import {CallTree} from './calltree.js'
|
||||||
@@ -8,8 +8,6 @@ import {el} from './domutils.js'
|
|||||||
|
|
||||||
export class UI {
|
export class UI {
|
||||||
constructor(container, state){
|
constructor(container, state){
|
||||||
this.change_entrypoint = this.change_entrypoint.bind(this)
|
|
||||||
this.change_html_file = this.change_html_file.bind(this)
|
|
||||||
this.open_run_window = this.open_run_window.bind(this)
|
this.open_run_window = this.open_run_window.bind(this)
|
||||||
|
|
||||||
this.files = new Files(this)
|
this.files = new Files(this)
|
||||||
@@ -42,7 +40,6 @@ export class UI {
|
|||||||
href: 'javascript: void(0)',
|
href: 'javascript: void(0)',
|
||||||
}, 'IO trace (F4)')
|
}, 'IO trace (F4)')
|
||||||
),
|
),
|
||||||
this.entrypoint_select = el('div', 'entrypoint_select')
|
|
||||||
),
|
),
|
||||||
this.debugger.calltree = el('div', {
|
this.debugger.calltree = el('div', {
|
||||||
'class': 'tab_content',
|
'class': 'tab_content',
|
||||||
@@ -58,12 +55,10 @@ export class UI {
|
|||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
this.debugger_loading = el('div', 'debugger_wrapper',
|
this.debugger_loading = el('div', 'debugger_wrapper',
|
||||||
el('div', 'entrypoint_select'),
|
|
||||||
this.debugger_loading_message = el('div'),
|
this.debugger_loading_message = el('div'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
this.problems_container = el('div', {"class": 'problems_container', tabindex: 0},
|
this.problems_container = el('div', {"class": 'problems_container', tabindex: 0},
|
||||||
el('div', 'entrypoint_select'),
|
|
||||||
this.problems = el('div'),
|
this.problems = el('div'),
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
@@ -194,7 +189,6 @@ export class UI {
|
|||||||
// instead
|
// instead
|
||||||
this.debugger.calltree.addEventListener('click', jump_to_fn_location)
|
this.debugger.calltree.addEventListener('click', jump_to_fn_location)
|
||||||
|
|
||||||
this.render_entrypoint_select(state)
|
|
||||||
this.render_current_module(state.current_module)
|
this.render_current_module(state.current_module)
|
||||||
|
|
||||||
this.set_active_tab('calltree', true)
|
this.set_active_tab('calltree', true)
|
||||||
@@ -216,72 +210,10 @@ export class UI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render_entrypoint_select(state) {
|
|
||||||
for(let select of this.root.getElementsByClassName('entrypoint_select')) {
|
|
||||||
this.do_render_entrypoint_select(state, select)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
do_render_entrypoint_select(state, select) {
|
|
||||||
select.replaceChildren(
|
|
||||||
el('span', 'entrypoint_title', 'js entrypoint'),
|
|
||||||
el('select', {
|
|
||||||
click: e => e.stopPropagation(),
|
|
||||||
change: this.change_entrypoint,
|
|
||||||
},
|
|
||||||
Object
|
|
||||||
.keys(state.files)
|
|
||||||
.sort()
|
|
||||||
.filter(f => f == '' || f.endsWith('.js') || f.endsWith('.mjs'))
|
|
||||||
.map(f =>
|
|
||||||
el('option',
|
|
||||||
state.entrypoint == f
|
|
||||||
? { value: f, selected: true }
|
|
||||||
: { value: f},
|
|
||||||
f == '' ? "*scratch*" : f
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
el('span', 'entrypoint_title', 'html page'),
|
|
||||||
el('select', {
|
|
||||||
click: e => e.stopPropagation(),
|
|
||||||
change: this.change_html_file,
|
|
||||||
},
|
|
||||||
['']
|
|
||||||
.concat(
|
|
||||||
Object
|
|
||||||
.keys(state.files)
|
|
||||||
.sort()
|
|
||||||
.filter(f => f.endsWith('.htm') || f.endsWith('.html'))
|
|
||||||
)
|
|
||||||
.map(f =>
|
|
||||||
el('option',
|
|
||||||
state.html_file == f
|
|
||||||
? { value: f, selected: true }
|
|
||||||
: { value: f},
|
|
||||||
f == '' ? 'about:blank' : f
|
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
open_run_window() {
|
open_run_window() {
|
||||||
open_run_window(get_state())
|
open_run_window(get_state())
|
||||||
}
|
}
|
||||||
|
|
||||||
change_entrypoint(e) {
|
|
||||||
const file = e.target.value
|
|
||||||
exec('change_entrypoint', file)
|
|
||||||
this.editor.focus()
|
|
||||||
}
|
|
||||||
|
|
||||||
change_html_file(e) {
|
|
||||||
const html_file = e.target.value
|
|
||||||
exec('change_html_file', html_file)
|
|
||||||
reload_run_window(get_state())
|
|
||||||
}
|
|
||||||
|
|
||||||
render_debugger_loading(state) {
|
render_debugger_loading(state) {
|
||||||
this.debugger_container.style = ''
|
this.debugger_container.style = ''
|
||||||
this.problems_container.style = 'display: none'
|
this.problems_container.style = 'display: none'
|
||||||
|
|||||||
10
src/effects.js
vendored
10
src/effects.js
vendored
@@ -140,16 +140,6 @@ export const apply_side_effects = (prev, next, command, ui) => {
|
|||||||
ui.files.render(next)
|
ui.files.render(next)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(
|
|
||||||
prev.project_dir != next.project_dir
|
|
||||||
||
|
|
||||||
prev.entrypoint != next.entrypoint
|
|
||||||
||
|
|
||||||
prev.html_file != next.html_file
|
|
||||||
) {
|
|
||||||
ui.render_entrypoint_select(next)
|
|
||||||
}
|
|
||||||
|
|
||||||
if(prev.current_module != next.current_module) {
|
if(prev.current_module != next.current_module) {
|
||||||
localStorage.current_module = next.current_module
|
localStorage.current_module = next.current_module
|
||||||
ui.render_current_module(next.current_module)
|
ui.render_current_module(next.current_module)
|
||||||
|
|||||||
Reference in New Issue
Block a user