Extract download files
This commit is contained in:
parent
200e5d0a13
commit
17c647b60d
@ -1 +1,2 @@
|
|||||||
|
from pyzebra.app.download_files import DownloadFiles
|
||||||
from pyzebra.app.fit_controls import FitControls
|
from pyzebra.app.fit_controls import FitControls
|
||||||
|
44
pyzebra/app/download_files.py
Normal file
44
pyzebra/app/download_files.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
from bokeh.models import Button, ColumnDataSource, CustomJS
|
||||||
|
|
||||||
|
js_code = """
|
||||||
|
let j = 0;
|
||||||
|
for (let i = 0; i < source.data['name'].length; i++) {
|
||||||
|
if (source.data['content'][i] === "") continue;
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
const blob = new Blob([source.data['content'][i]], {type: 'text/plain'})
|
||||||
|
const link = document.createElement('a');
|
||||||
|
document.body.appendChild(link);
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
link.href = url;
|
||||||
|
link.download = source.data['name'][i] + source.data['ext'][i];
|
||||||
|
link.click();
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
document.body.removeChild(link);
|
||||||
|
}, 100 * j)
|
||||||
|
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class DownloadFiles:
|
||||||
|
def __init__(self, n_files):
|
||||||
|
source = ColumnDataSource(
|
||||||
|
data=dict(content=[""] * n_files, name=[""] * n_files, ext=[""] * n_files)
|
||||||
|
)
|
||||||
|
self._source = source
|
||||||
|
|
||||||
|
label = "Download File" if n_files == 1 else "Download Files"
|
||||||
|
button = Button(label=label, button_type="success", width=200)
|
||||||
|
button.js_on_click(CustomJS(args={"source": source}, code=js_code))
|
||||||
|
self.button = button
|
||||||
|
|
||||||
|
def set_contents(self, contents):
|
||||||
|
self._source.data.update(content=contents)
|
||||||
|
|
||||||
|
def set_names(self, names):
|
||||||
|
self._source.data.update(name=names)
|
||||||
|
|
||||||
|
def set_extensions(self, extensions):
|
||||||
|
self._source.data.update(ext=extensions)
|
@ -11,7 +11,6 @@ from bokeh.models import (
|
|||||||
CellEditor,
|
CellEditor,
|
||||||
CheckboxEditor,
|
CheckboxEditor,
|
||||||
ColumnDataSource,
|
ColumnDataSource,
|
||||||
CustomJS,
|
|
||||||
DataTable,
|
DataTable,
|
||||||
Div,
|
Div,
|
||||||
FileInput,
|
FileInput,
|
||||||
@ -31,33 +30,12 @@ from bokeh.plotting import figure
|
|||||||
import pyzebra
|
import pyzebra
|
||||||
from pyzebra import EXPORT_TARGETS, app
|
from pyzebra import EXPORT_TARGETS, app
|
||||||
|
|
||||||
javaScript = """
|
|
||||||
let j = 0;
|
|
||||||
for (let i = 0; i < js_data.data['fname'].length; i++) {
|
|
||||||
if (js_data.data['content'][i] === "") continue;
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
const blob = new Blob([js_data.data['content'][i]], {type: 'text/plain'})
|
|
||||||
const link = document.createElement('a');
|
|
||||||
document.body.appendChild(link);
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
link.href = url;
|
|
||||||
link.download = js_data.data['fname'][i] + js_data.data['ext'][i];
|
|
||||||
link.click();
|
|
||||||
window.URL.revokeObjectURL(url);
|
|
||||||
document.body.removeChild(link);
|
|
||||||
}, 100 * j)
|
|
||||||
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def create():
|
def create():
|
||||||
doc = curdoc()
|
doc = curdoc()
|
||||||
dataset1 = []
|
dataset1 = []
|
||||||
dataset2 = []
|
dataset2 = []
|
||||||
js_data = ColumnDataSource(data=dict(content=["", ""], fname=["", ""], ext=["", ""]))
|
app_dlfiles = app.DownloadFiles(n_files=2)
|
||||||
|
|
||||||
def file_select_update_for_proposal():
|
def file_select_update_for_proposal():
|
||||||
proposal_path = proposal_textinput.name
|
proposal_path = proposal_textinput.name
|
||||||
@ -135,7 +113,7 @@ def create():
|
|||||||
pyzebra.merge_duplicates(file_data)
|
pyzebra.merge_duplicates(file_data)
|
||||||
|
|
||||||
if ind == 0:
|
if ind == 0:
|
||||||
js_data.data.update(fname=[base, base])
|
app_dlfiles.set_names([base, base])
|
||||||
new_data1 = file_data
|
new_data1 = file_data
|
||||||
else: # ind = 1
|
else: # ind = 1
|
||||||
new_data2 = file_data
|
new_data2 = file_data
|
||||||
@ -173,7 +151,7 @@ def create():
|
|||||||
pyzebra.merge_duplicates(file_data)
|
pyzebra.merge_duplicates(file_data)
|
||||||
|
|
||||||
if ind == 0:
|
if ind == 0:
|
||||||
js_data.data.update(fname=[base, base])
|
app_dlfiles.set_names([base, base])
|
||||||
new_data1 = file_data
|
new_data1 = file_data
|
||||||
else: # ind = 1
|
else: # ind = 1
|
||||||
new_data2 = file_data
|
new_data2 = file_data
|
||||||
@ -493,18 +471,18 @@ def create():
|
|||||||
content = ""
|
content = ""
|
||||||
file_content.append(content)
|
file_content.append(content)
|
||||||
|
|
||||||
js_data.data.update(content=file_content)
|
app_dlfiles.set_contents(file_content)
|
||||||
export_preview_textinput.value = exported_content
|
export_preview_textinput.value = exported_content
|
||||||
|
|
||||||
def export_target_select_callback(_attr, _old, new):
|
def export_target_select_callback(_attr, _old, new):
|
||||||
js_data.data.update(ext=EXPORT_TARGETS[new])
|
app_dlfiles.set_extensions(EXPORT_TARGETS[new])
|
||||||
_update_preview()
|
_update_preview()
|
||||||
|
|
||||||
export_target_select = Select(
|
export_target_select = Select(
|
||||||
title="Export target:", options=list(EXPORT_TARGETS.keys()), value="fullprof", width=80
|
title="Export target:", options=list(EXPORT_TARGETS.keys()), value="fullprof", width=80
|
||||||
)
|
)
|
||||||
export_target_select.on_change("value", export_target_select_callback)
|
export_target_select.on_change("value", export_target_select_callback)
|
||||||
js_data.data.update(ext=EXPORT_TARGETS[export_target_select.value])
|
app_dlfiles.set_extensions(EXPORT_TARGETS[export_target_select.value])
|
||||||
|
|
||||||
def hkl_precision_select_callback(_attr, _old, _new):
|
def hkl_precision_select_callback(_attr, _old, _new):
|
||||||
_update_preview()
|
_update_preview()
|
||||||
@ -514,9 +492,6 @@ def create():
|
|||||||
)
|
)
|
||||||
hkl_precision_select.on_change("value", hkl_precision_select_callback)
|
hkl_precision_select.on_change("value", hkl_precision_select_callback)
|
||||||
|
|
||||||
save_button = Button(label="Download File(s)", button_type="success", width=200)
|
|
||||||
save_button.js_on_click(CustomJS(args={"js_data": js_data}, code=javaScript))
|
|
||||||
|
|
||||||
area_method_div = Div(text="Intensity:", margin=(5, 5, 0, 5))
|
area_method_div = Div(text="Intensity:", margin=(5, 5, 0, 5))
|
||||||
fitpeak_controls = row(
|
fitpeak_controls = row(
|
||||||
column(
|
column(
|
||||||
@ -548,7 +523,9 @@ def create():
|
|||||||
export_layout = column(
|
export_layout = column(
|
||||||
export_preview_textinput,
|
export_preview_textinput,
|
||||||
row(
|
row(
|
||||||
export_target_select, hkl_precision_select, column(Spacer(height=19), row(save_button))
|
export_target_select,
|
||||||
|
hkl_precision_select,
|
||||||
|
column(Spacer(height=19), row(app_dlfiles.button)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ from bokeh.models import (
|
|||||||
CellEditor,
|
CellEditor,
|
||||||
CheckboxEditor,
|
CheckboxEditor,
|
||||||
ColumnDataSource,
|
ColumnDataSource,
|
||||||
CustomJS,
|
|
||||||
DataTable,
|
DataTable,
|
||||||
Div,
|
Div,
|
||||||
FileInput,
|
FileInput,
|
||||||
@ -30,32 +29,11 @@ from bokeh.plotting import figure
|
|||||||
import pyzebra
|
import pyzebra
|
||||||
from pyzebra import EXPORT_TARGETS, app
|
from pyzebra import EXPORT_TARGETS, app
|
||||||
|
|
||||||
javaScript = """
|
|
||||||
let j = 0;
|
|
||||||
for (let i = 0; i < js_data.data['fname'].length; i++) {
|
|
||||||
if (js_data.data['content'][i] === "") continue;
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
const blob = new Blob([js_data.data['content'][i]], {type: 'text/plain'})
|
|
||||||
const link = document.createElement('a');
|
|
||||||
document.body.appendChild(link);
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
link.href = url;
|
|
||||||
link.download = js_data.data['fname'][i] + js_data.data['ext'][i];
|
|
||||||
link.click();
|
|
||||||
window.URL.revokeObjectURL(url);
|
|
||||||
document.body.removeChild(link);
|
|
||||||
}, 100 * j)
|
|
||||||
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def create():
|
def create():
|
||||||
doc = curdoc()
|
doc = curdoc()
|
||||||
dataset = []
|
dataset = []
|
||||||
js_data = ColumnDataSource(data=dict(content=["", ""], fname=["", ""], ext=["", ""]))
|
app_dlfiles = app.DownloadFiles(n_files=2)
|
||||||
|
|
||||||
def file_select_update_for_proposal():
|
def file_select_update_for_proposal():
|
||||||
proposal_path = proposal_textinput.name
|
proposal_path = proposal_textinput.name
|
||||||
@ -131,7 +109,7 @@ def create():
|
|||||||
if not new_data: # first file
|
if not new_data: # first file
|
||||||
new_data = file_data
|
new_data = file_data
|
||||||
pyzebra.merge_duplicates(new_data)
|
pyzebra.merge_duplicates(new_data)
|
||||||
js_data.data.update(fname=[base, base])
|
app_dlfiles.set_names([base, base])
|
||||||
else:
|
else:
|
||||||
pyzebra.merge_datasets(new_data, file_data)
|
pyzebra.merge_datasets(new_data, file_data)
|
||||||
|
|
||||||
@ -181,7 +159,7 @@ def create():
|
|||||||
if not new_data: # first file
|
if not new_data: # first file
|
||||||
new_data = file_data
|
new_data = file_data
|
||||||
pyzebra.merge_duplicates(new_data)
|
pyzebra.merge_duplicates(new_data)
|
||||||
js_data.data.update(fname=[base, base])
|
app_dlfiles.set_names([base, base])
|
||||||
else:
|
else:
|
||||||
pyzebra.merge_datasets(new_data, file_data)
|
pyzebra.merge_datasets(new_data, file_data)
|
||||||
|
|
||||||
@ -455,18 +433,18 @@ def create():
|
|||||||
content = ""
|
content = ""
|
||||||
file_content.append(content)
|
file_content.append(content)
|
||||||
|
|
||||||
js_data.data.update(content=file_content)
|
app_dlfiles.set_contents(file_content)
|
||||||
export_preview_textinput.value = exported_content
|
export_preview_textinput.value = exported_content
|
||||||
|
|
||||||
def export_target_select_callback(_attr, _old, new):
|
def export_target_select_callback(_attr, _old, new):
|
||||||
js_data.data.update(ext=EXPORT_TARGETS[new])
|
app_dlfiles.set_extensions(EXPORT_TARGETS[new])
|
||||||
_update_preview()
|
_update_preview()
|
||||||
|
|
||||||
export_target_select = Select(
|
export_target_select = Select(
|
||||||
title="Export target:", options=list(EXPORT_TARGETS.keys()), value="fullprof", width=80
|
title="Export target:", options=list(EXPORT_TARGETS.keys()), value="fullprof", width=80
|
||||||
)
|
)
|
||||||
export_target_select.on_change("value", export_target_select_callback)
|
export_target_select.on_change("value", export_target_select_callback)
|
||||||
js_data.data.update(ext=EXPORT_TARGETS[export_target_select.value])
|
app_dlfiles.set_extensions(EXPORT_TARGETS[export_target_select.value])
|
||||||
|
|
||||||
def hkl_precision_select_callback(_attr, _old, _new):
|
def hkl_precision_select_callback(_attr, _old, _new):
|
||||||
_update_preview()
|
_update_preview()
|
||||||
@ -476,9 +454,6 @@ def create():
|
|||||||
)
|
)
|
||||||
hkl_precision_select.on_change("value", hkl_precision_select_callback)
|
hkl_precision_select.on_change("value", hkl_precision_select_callback)
|
||||||
|
|
||||||
save_button = Button(label="Download File(s)", button_type="success", width=200)
|
|
||||||
save_button.js_on_click(CustomJS(args={"js_data": js_data}, code=javaScript))
|
|
||||||
|
|
||||||
area_method_div = Div(text="Intensity:", margin=(5, 5, 0, 5))
|
area_method_div = Div(text="Intensity:", margin=(5, 5, 0, 5))
|
||||||
fitpeak_controls = row(
|
fitpeak_controls = row(
|
||||||
column(
|
column(
|
||||||
@ -515,7 +490,9 @@ def create():
|
|||||||
export_layout = column(
|
export_layout = column(
|
||||||
export_preview_textinput,
|
export_preview_textinput,
|
||||||
row(
|
row(
|
||||||
export_target_select, hkl_precision_select, column(Spacer(height=19), row(save_button))
|
export_target_select,
|
||||||
|
hkl_precision_select,
|
||||||
|
column(Spacer(height=19), row(app_dlfiles.button)),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ from bokeh.models import (
|
|||||||
Button,
|
Button,
|
||||||
CheckboxGroup,
|
CheckboxGroup,
|
||||||
ColumnDataSource,
|
ColumnDataSource,
|
||||||
CustomJS,
|
|
||||||
Div,
|
Div,
|
||||||
FileInput,
|
FileInput,
|
||||||
Legend,
|
Legend,
|
||||||
@ -32,27 +31,7 @@ from bokeh.palettes import Dark2
|
|||||||
from bokeh.plotting import figure
|
from bokeh.plotting import figure
|
||||||
|
|
||||||
import pyzebra
|
import pyzebra
|
||||||
|
from pyzebra import app
|
||||||
javaScript = """
|
|
||||||
let j = 0;
|
|
||||||
for (let i = 0; i < js_data.data['fname'].length; i++) {
|
|
||||||
if (js_data.data['content'][i] === "") continue;
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
const blob = new Blob([js_data.data['content'][i]], {type: 'text/plain'})
|
|
||||||
const link = document.createElement('a');
|
|
||||||
document.body.appendChild(link);
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
link.href = url;
|
|
||||||
link.download = js_data.data['fname'][i];
|
|
||||||
link.click();
|
|
||||||
window.URL.revokeObjectURL(url);
|
|
||||||
document.body.removeChild(link);
|
|
||||||
}, 100 * j)
|
|
||||||
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
ANG_CHUNK_DEFAULTS = {"2theta": 30, "gamma": 30, "omega": 30, "chi": 35, "phi": 35, "nu": 10}
|
ANG_CHUNK_DEFAULTS = {"2theta": 30, "gamma": 30, "omega": 30, "chi": 35, "phi": 35, "nu": 10}
|
||||||
SORT_OPT_BI = ["2theta", "chi", "phi", "omega"]
|
SORT_OPT_BI = ["2theta", "chi", "phi", "omega"]
|
||||||
@ -64,7 +43,7 @@ def create():
|
|||||||
cif_data = {}
|
cif_data = {}
|
||||||
params = {}
|
params = {}
|
||||||
res_files = {}
|
res_files = {}
|
||||||
js_data = ColumnDataSource(data=dict(content=[""], fname=[""]))
|
app_dlfiles = app.DownloadFiles(n_files=1)
|
||||||
|
|
||||||
anglim_div = Div(text="Angular min/max limits:", margin=(5, 5, 0, 5))
|
anglim_div = Div(text="Angular min/max limits:", margin=(5, 5, 0, 5))
|
||||||
sttgamma_ti = TextInput(title="stt/gamma", width=100)
|
sttgamma_ti = TextInput(title="stt/gamma", width=100)
|
||||||
@ -315,14 +294,13 @@ def create():
|
|||||||
sel_file = new[0]
|
sel_file = new[0]
|
||||||
file_text = res_files[sel_file]
|
file_text = res_files[sel_file]
|
||||||
preview_lists.value = file_text
|
preview_lists.value = file_text
|
||||||
js_data.data.update(content=[file_text], fname=[sel_file])
|
app_dlfiles.set_contents([file_text])
|
||||||
|
app_dlfiles.set_names([sel_file])
|
||||||
|
|
||||||
created_lists = MultiSelect(title="Created lists:", width=200, height=150)
|
created_lists = MultiSelect(title="Created lists:", width=200, height=150)
|
||||||
created_lists.on_change("value", created_lists_callback)
|
created_lists.on_change("value", created_lists_callback)
|
||||||
preview_lists = TextAreaInput(title="Preview selected list:", width=600, height=150)
|
preview_lists = TextAreaInput(title="Preview selected list:", width=600, height=150)
|
||||||
|
|
||||||
download_file = Button(label="Download file", button_type="success", width=200)
|
|
||||||
download_file.js_on_click(CustomJS(args={"js_data": js_data}, code=javaScript))
|
|
||||||
plot_list = Button(label="Plot selected list", button_type="primary", width=200, disabled=True)
|
plot_list = Button(label="Plot selected list", button_type="primary", width=200, disabled=True)
|
||||||
|
|
||||||
measured_data_div = Div(text="Measured data:")
|
measured_data_div = Div(text="Measured data:")
|
||||||
@ -709,7 +687,7 @@ def create():
|
|||||||
row(ranges_layout, Spacer(width=50), magstruct_layout),
|
row(ranges_layout, Spacer(width=50), magstruct_layout),
|
||||||
row(sorting_layout, Spacer(width=30), column(Spacer(height=18), go_button)),
|
row(sorting_layout, Spacer(width=30), column(Spacer(height=18), go_button)),
|
||||||
row(created_lists, preview_lists),
|
row(created_lists, preview_lists),
|
||||||
row(download_file, plot_list),
|
row(app_dlfiles.button, plot_list),
|
||||||
)
|
)
|
||||||
|
|
||||||
hkl_layout = column(
|
hkl_layout = column(
|
||||||
|
@ -12,7 +12,6 @@ from bokeh.models import (
|
|||||||
CellEditor,
|
CellEditor,
|
||||||
CheckboxEditor,
|
CheckboxEditor,
|
||||||
ColumnDataSource,
|
ColumnDataSource,
|
||||||
CustomJS,
|
|
||||||
DataTable,
|
DataTable,
|
||||||
Div,
|
Div,
|
||||||
FileInput,
|
FileInput,
|
||||||
@ -38,27 +37,6 @@ from scipy import interpolate
|
|||||||
import pyzebra
|
import pyzebra
|
||||||
from pyzebra import app
|
from pyzebra import app
|
||||||
|
|
||||||
javaScript = """
|
|
||||||
let j = 0;
|
|
||||||
for (let i = 0; i < js_data.data['fname'].length; i++) {
|
|
||||||
if (js_data.data['content'][i] === "") continue;
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
const blob = new Blob([js_data.data['content'][i]], {type: 'text/plain'})
|
|
||||||
const link = document.createElement('a');
|
|
||||||
document.body.appendChild(link);
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
link.href = url;
|
|
||||||
link.download = js_data.data['fname'][i] + js_data.data['ext'][i];
|
|
||||||
link.click();
|
|
||||||
window.URL.revokeObjectURL(url);
|
|
||||||
document.body.removeChild(link);
|
|
||||||
}, 100 * j)
|
|
||||||
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def color_palette(n_colors):
|
def color_palette(n_colors):
|
||||||
palette = itertools.cycle(Category10[10])
|
palette = itertools.cycle(Category10[10])
|
||||||
@ -68,7 +46,7 @@ def color_palette(n_colors):
|
|||||||
def create():
|
def create():
|
||||||
doc = curdoc()
|
doc = curdoc()
|
||||||
dataset = []
|
dataset = []
|
||||||
js_data = ColumnDataSource(data=dict(content=[""], fname=[""], ext=[""]))
|
app_dlfiles = app.DownloadFiles(n_files=1)
|
||||||
|
|
||||||
def file_select_update_for_proposal():
|
def file_select_update_for_proposal():
|
||||||
proposal_path = proposal_textinput.name
|
proposal_path = proposal_textinput.name
|
||||||
@ -138,7 +116,7 @@ def create():
|
|||||||
if not new_data: # first file
|
if not new_data: # first file
|
||||||
new_data = file_data
|
new_data = file_data
|
||||||
pyzebra.merge_duplicates(new_data)
|
pyzebra.merge_duplicates(new_data)
|
||||||
js_data.data.update(fname=[base])
|
app_dlfiles.set_names([base])
|
||||||
else:
|
else:
|
||||||
pyzebra.merge_datasets(new_data, file_data)
|
pyzebra.merge_datasets(new_data, file_data)
|
||||||
|
|
||||||
@ -188,7 +166,7 @@ def create():
|
|||||||
if not new_data: # first file
|
if not new_data: # first file
|
||||||
new_data = file_data
|
new_data = file_data
|
||||||
pyzebra.merge_duplicates(new_data)
|
pyzebra.merge_duplicates(new_data)
|
||||||
js_data.data.update(fname=[base])
|
app_dlfiles.set_names([base])
|
||||||
else:
|
else:
|
||||||
pyzebra.merge_datasets(new_data, file_data)
|
pyzebra.merge_datasets(new_data, file_data)
|
||||||
|
|
||||||
@ -628,12 +606,9 @@ def create():
|
|||||||
content = ""
|
content = ""
|
||||||
file_content.append(content)
|
file_content.append(content)
|
||||||
|
|
||||||
js_data.data.update(content=file_content)
|
app_dlfiles.set_contents(file_content)
|
||||||
export_preview_textinput.value = exported_content
|
export_preview_textinput.value = exported_content
|
||||||
|
|
||||||
save_button = Button(label="Download File", button_type="success", width=220)
|
|
||||||
save_button.js_on_click(CustomJS(args={"js_data": js_data}, code=javaScript))
|
|
||||||
|
|
||||||
area_method_div = Div(text="Intensity:", margin=(5, 5, 0, 5))
|
area_method_div = Div(text="Intensity:", margin=(5, 5, 0, 5))
|
||||||
fitpeak_controls = row(
|
fitpeak_controls = row(
|
||||||
column(
|
column(
|
||||||
@ -667,7 +642,7 @@ def create():
|
|||||||
append_upload_button,
|
append_upload_button,
|
||||||
)
|
)
|
||||||
|
|
||||||
export_layout = column(export_preview_textinput, row(save_button))
|
export_layout = column(export_preview_textinput, row(app_dlfiles.button))
|
||||||
|
|
||||||
tab_layout = column(
|
tab_layout = column(
|
||||||
row(import_layout, scan_layout, plots, Spacer(width=30), export_layout),
|
row(import_layout, scan_layout, plots, Spacer(width=30), export_layout),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user