mirror of
https://github.com/leporello-js/leporello-js
synced 2026-01-13 21:14:28 -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
|
||||
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
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
.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 {
|
||||
margin-left: 1em;
|
||||
}
|
||||
@@ -248,10 +226,20 @@
|
||||
margin-left: 0em !important;
|
||||
}
|
||||
|
||||
.files .file_title {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.files .file_title.active {
|
||||
background-color: rgb(225, 244, 253);
|
||||
}
|
||||
|
||||
.files .file_title .select_entrypoint {
|
||||
margin-left: auto;
|
||||
width: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.files .file_title .icon {
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
@@ -259,13 +247,27 @@
|
||||
}
|
||||
|
||||
.file_actions {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-evenly;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
padding: 5px;
|
||||
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 */
|
||||
|
||||
.embed_value_explorer_container {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import {el} from './domutils.js'
|
||||
import {map_find} from '../utils.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 {
|
||||
constructor(ui) {
|
||||
@@ -10,6 +13,18 @@ export class Files {
|
||||
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) {
|
||||
if(state.project_dir == null) {
|
||||
this.el.innerHTML = ''
|
||||
@@ -25,32 +40,40 @@ export class Files {
|
||||
)
|
||||
)
|
||||
} else {
|
||||
this.render_files(state.project_dir, state.current_module)
|
||||
this.render_files(state)
|
||||
}
|
||||
}
|
||||
|
||||
render_files(dir, current_module) {
|
||||
const files = this.el.querySelector('.files')
|
||||
|
||||
render_files(state) {
|
||||
const children = [
|
||||
this.render_file({name: '*scratch*', path: ''}, current_module),
|
||||
this.render_file(dir, current_module),
|
||||
this.render_file({name: '*scratch*', path: ''}, state),
|
||||
this.render_file(state.project_dir, state),
|
||||
]
|
||||
|
||||
const files = this.el.querySelector('.files')
|
||||
|
||||
if(files == null) {
|
||||
this.el.innerHTML = ''
|
||||
this.el.appendChild(
|
||||
el('div', 'file_actions',
|
||||
el('a', {
|
||||
'class': 'file_action',
|
||||
href: 'javascript: void(0)',
|
||||
click: this.create_file.bind(this, false),
|
||||
},
|
||||
'Create file'
|
||||
),
|
||||
el('a', {
|
||||
'class': 'file_action',
|
||||
href: 'javascript: void(0)',
|
||||
click: this.create_file.bind(this, true),
|
||||
}, '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(
|
||||
@@ -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',
|
||||
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)
|
||||
},
|
||||
el('span', 'icon',
|
||||
@@ -76,13 +129,14 @@ export class Files {
|
||||
: '\xa0',
|
||||
),
|
||||
file.name,
|
||||
this.render_select_entrypoint(file, state),
|
||||
),
|
||||
file.children == 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_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 {Files} from './files.js'
|
||||
import {CallTree} from './calltree.js'
|
||||
@@ -8,8 +8,6 @@ import {el} from './domutils.js'
|
||||
|
||||
export class UI {
|
||||
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.files = new Files(this)
|
||||
@@ -42,7 +40,6 @@ export class UI {
|
||||
href: 'javascript: void(0)',
|
||||
}, 'IO trace (F4)')
|
||||
),
|
||||
this.entrypoint_select = el('div', 'entrypoint_select')
|
||||
),
|
||||
this.debugger.calltree = el('div', {
|
||||
'class': 'tab_content',
|
||||
@@ -58,12 +55,10 @@ export class UI {
|
||||
}),
|
||||
),
|
||||
this.debugger_loading = el('div', 'debugger_wrapper',
|
||||
el('div', 'entrypoint_select'),
|
||||
this.debugger_loading_message = el('div'),
|
||||
),
|
||||
),
|
||||
this.problems_container = el('div', {"class": 'problems_container', tabindex: 0},
|
||||
el('div', 'entrypoint_select'),
|
||||
this.problems = el('div'),
|
||||
)
|
||||
),
|
||||
@@ -194,7 +189,6 @@ export class UI {
|
||||
// instead
|
||||
this.debugger.calltree.addEventListener('click', jump_to_fn_location)
|
||||
|
||||
this.render_entrypoint_select(state)
|
||||
this.render_current_module(state.current_module)
|
||||
|
||||
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(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) {
|
||||
this.debugger_container.style = ''
|
||||
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)
|
||||
}
|
||||
|
||||
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) {
|
||||
localStorage.current_module = next.current_module
|
||||
ui.render_current_module(next.current_module)
|
||||
|
||||
Reference in New Issue
Block a user