def __init__(self, aoi_model, model, **kwargs): # gather the model self.aoi_model = aoi_model self.model = model self.scale = v.TextField(label=cm.export.scale, v_model=30) # create buttons self.asset_btn = sw.Btn( cm.export.asset_btn, "mdi-download", disabled=True, class_="ma-5" ) self.sepal_btn = sw.Btn( cm.export.sepal_btn, "mdi-download", disabled=True, class_="ma-5" ) # bindings self.model.bind(self.scale, "scale") # note that btn and alert are not a madatory attributes super().__init__( id_="export_widget", title=cm.export.title, inputs=[self.scale], alert=sw.Alert(), btn=v.Layout(row=True, children=[self.asset_btn, self.sepal_btn]), ) # link the btn self.asset_btn.on_event("click", self._on_asset_click) self.sepal_btn.on_event("click", self._on_sepal_click)
def __init__(self, aoi_tile, questionnaire_tile): # gather the io self.layer_model = questionnaire_tile.layer_model self.aoi_model = aoi_tile.view.model self.question_model = questionnaire_tile.question_model # gather the tiles that need to be filled self.aoi_tile = aoi_tile self.questionnaire_tile = questionnaire_tile # add the naming textField self.w_name = v.TextField(label=cm.custom.recipe.name, v_model=None) # link the widget to the model self.question_model.bind(self.w_name, "recipe_name") # create the layer list widget self.layers_recipe = cw.layerRecipe().hide() mkd = sw.Markdown(" \n".join(cm.valid.txt)) # add the recipe loader self.reset_to_recipe = sw.Btn(text=cm.custom.recipe.apply, icon="mdi-download", class_="ml-2") self.file_select = sw.FileInput([".json"], cp.result_dir, cm.custom.recipe.file) ep = v.ExpansionPanels( class_="mt-5", children=[ v.ExpansionPanel(children=[ v.ExpansionPanelHeader(disable_icon_rotate=True, children=[cm.custom.recipe.title]), v.ExpansionPanelContent( children=[self.file_select, self.reset_to_recipe]), ]) ], ) # create the tile super().__init__( id_="compute_widget", inputs=[ep, mkd, self.w_name, self.layers_recipe], title=cm.valid.title, btn=sw.Btn(cm.valid.display, class_="ma-1"), alert=sw.Alert(), ) # decorate the custom recipe btn self.load_recipe = su.loading_button(self.alert, self.reset_to_recipe, debug=True)(self.load_recipe) # js behaviours aoi_tile.view.observe(self._recipe_placeholder, "updated") self.btn.on_event("click", self._validate_data) self.reset_to_recipe.on_event("click", self.load_recipe) self.w_name.on_event("blur", self._normalize_name)
def __init__(self, aoi_vew, model): # save the model self.model = model # listen to the aoi_vew to update the map self.view = aoi_vew self.init_layer = "" self.id = "" self.index = None # add all the standard placeholder, they will be replaced when a layer will be selected self.title = v.CardTitle(children=["Layer name"]) self.text = v.CardText(children=[""]) self.layer = v.TextField(class_="ma-5", v_model=None, color="warning", outlined=True, label="Layer") self.unit = v.TextField(class_="ma-5", v_model=None, color="warning", outlined=True, label="Unit") # add a map to display the layers self.m = sm.SepalMap() self.m.layout.height = "40vh" self.m.layout.margin = "2em" # two button will be placed at the bottom of the panel self.cancel = sw.Btn(cm.dial.cancel, color="primary", outlined=True) self.save = sw.Btn(cm.dial.save, color="primary") # create the init card self.card = v.Card(children=[ self.title, self.text, self.layer, self.unit, self.m, v.CardActions(class_="ma-5", children=[self.cancel, self.save]), ]) # init the dialog super().__init__(persistent=True, value=False, max_width="50vw", children=[self.card]) # js behaviours self.layer.on_event("blur", self._on_layer_change) self.cancel.on_event("click", self._cancel_click) self.save.on_event("click", self._save_click) self.view.observe(self._update_aoi, "updated")
def __init__(self, io, nb_class): # gather the io self.io = io # create the download layout self.down_test = sw.Btn(cm.bin.default.btn, icon="mdi-cloud-download-outline", small=True, outlined=True, class_="ma-5") tooltip = sw.Tooltip(widget=self.down_test, tooltip=cm.bin.default.tooltip) # create the widgets self.file = sw.FileInput(['.tif', '.tiff']) self.classes = [ v.Select(label=cp.convert[nb_class]['label'][i], items=None, v_model=None, chips=True, small_chips=True, multiple=True, dense=True, deletable_chips=True) for i in range(len(cp.convert[nb_class]['label'])) ] requirements = sw.Markdown(cm.requirement[nb_class]) # bind it to the io self.output = sw.Alert().bind(self.file, self.io, 'file') for i in range(len(cp.convert[nb_class]['label'])): self.output.bind(self.classes[i], self.io, cp.convert[nb_class]['io'][i]) # create the btn btn = sw.Btn(cm.bin.btn) super().__init__( self.io.tile_id, cm.bin.title, inputs=[tooltip, v.Divider(), requirements, self.file] + self.classes, output=self.output, btn=btn) # bind js event btn.on_event('click', self._on_click) self.file.observe(self._on_change, 'v_model') self.down_test.on_event('click', self._on_download)
def test_init(self): #minimal btn btn = sw.Btn() self.assertEqual(btn.color, 'primary') self.assertEqual(btn.v_icon, None) self.assertEqual(btn.children[0], 'Click') #extensive btn btn = sw.Btn('toto', 'mdi-folder') self.assertEqual(btn.children[1], 'toto') self.assertIsInstance(btn.v_icon, v.Icon) self.assertEqual(btn.v_icon.children[0], 'mdi-folder') return
def __init__(self, io, nb_class): # gather the io self.io = io # create the widgets self.file = sw.FileInput(['.tif', '.tiff']) self.classes = [ v.Select(label=cp.convert[nb_class]['label'][i], items=None, v_model=None, chips=True, multiple=True) for i in range(nb_class) ] requirements = sw.Markdown(cm.requirement[nb_class]) # bind it to the io self.output = sw.Alert().bind(self.file, self.io, 'file') for i in range(nb_class): self.output.bind(self.classes[i], self.io, cp.convert[nb_class]['io'][i]) # create the btn btn = sw.Btn("Convert the imag classes") super().__init__(self.io.tile_id, "Select map classes", inputs=[requirements, self.file] + self.classes, output=self.output, btn=btn) # bind js event btn.on_event('click', self._on_click) self.file.observe(self._on_change, 'v_model')
def __init__(self, aoi_tile, model, result_tile): # gather the model objects self.aoi_model = aoi_tile.view.model self.model = model # add the result_tile map to attributes self.m = result_tile.m self.tile = result_tile # create the widgets mkd = sw.Markdown(cm.process_txt) # create the tile super().__init__( "compute_widget", cm.tile.launch, inputs=[mkd], btn=sw.Btn(cm.launch_btn, class_="mt-5"), alert=sw.Alert(), ) # link the js behaviours self.btn.on_event("click", self._launch_fcdm) aoi_tile.view.observe(self._update_geometry, "updated")
def __init__(self, tb_model, m): # gather model self.model = tb_model # get the map self.m = m # create widgets file_select = sw.LoadTableField() # bind it to the model self.alert = sw.Alert() self.model.bind(file_select, 'json_table') # create the tile super().__init__( id_ = 'file_widget', title = cm.table.title, btn = sw.Btn(cm.table.btn), alert = self.alert, inputs = [file_select] ) # js behaviour self.btn.on_event('click', self._load_file)
def __init__(self, model, aoi_model): # gather the io as class attribute self.aoi_model = aoi_model self.model = model # create widgets self.date_picker_start = sw.DatePicker(label="Start of event") self.date_picker_end = sw.DatePicker(label="End of event") self.username = v.TextField(label="Copernicus Scihub Username", v_model=None) self.password = sw.PasswordField(label="Copernicus Scihub Password") # bind them with the output self.model.bind(self.date_picker_start, "event_start").bind( self.date_picker_end, "event_end").bind(self.username, "username").bind(self.password, "password") # construct the tile super().__init__( id_="process_widget", title="Set input parameters", inputs=[ self.date_picker_start, self.date_picker_end, self.username, self.password ], alert=sw.Alert(), btn=sw.Btn("Process"), ) # link the click to an event self.btn.on_event("click", self._on_click)
def __init__(self, aoi_tile, model, questionnaire_model, **kwargs): # link the ios to the tile self.model = model self.questionnaire_model = questionnaire_model self.aoi_tile = aoi_tile self.table = cw.LayerTable(aoi_tile) # create the txt self.txt = sw.Markdown(cm.custom.desc) self.reset_to_recipe = sw.Btn( text=cm.custom.recipe.apply, icon="mdi-download", class_="ml-2", color="success", ) # build the tile super().__init__("manual_widget", cm.custom.title, inputs=[self.txt, self.table], **kwargs) # js behaviours self.table.observe(self._on_item_change, "change_model")
def __init__(self, io, **kwargs): self.io = io self.btn = sw.Btn(ms.SELECT_ALERTS, 'mdi-map-marker-check') self.output = sw.Alert() # create the inputs self.set_inputs() inputs = [ self.select_type, self.picker_line, self.local_txt, self.select_date_file, self.select_alerts_file, self.gee_txt, self.asset_date_line, self.asset_alerts_line ] # hide all inputs but select_type self.show_inputs() # misc id_ = "driver_widget" title = "Select your alerts" super().__init__(id_, title, btn=self.btn, output=self.output, inputs=inputs, **kwargs)
def download_tile(obj, w_selection): def bind_change(change, obj, attr): setattr(obj, attr, change['new']) w_overwrite = v.Switch(v_model=obj.overwrite, inset=True, label="Overwrite SEPAL images") w_overwrite.observe(partial(bind_change, obj=obj, attr='overwrite'), 'v_model') w_remove = v.Switch(v_model=obj.rmdrive, inset=True, label="Remove Google Drive Images") w_remove.observe(partial(bind_change, obj=obj, attr='rmdrive'), 'v_model') out = widgets.Output() btn = s.Btn(text="Download", icon='download') # Create an alert element for the process process_alert = s.Alert() on_download(obj, w_selection, btn, out, process_alert) html_header = """ <style> .widget-html span { color:black!important; } div.output_stderr{ color:none; } </style> <p>With this module you can track and download the images processed into your Google Earth Engine account by providing the 'tasks' text file, the results will be stored directly into your SEPAL account.</br> <b>Note that if you check the overwrite and remove options, the result can't be undone.</b> </p> """ download_content = v.Layout( class_="pa-5", row=True, align_center=True, children=[ v.Flex(xs12=True, children=[ v.Sheet(class_="pa-5", children=[ widgets.HTML(html_header), w_selection, w_overwrite, w_remove, btn, process_alert, out, ]) ]) ]) return download_content
def __init__(self, alert_model): # inti the model self.alert_model = alert_model # select the parameters for the planet API self.w_key = sw.PasswordField(label=cm.view.planet.key.label) self.w_advance = cw.PlanetParam(self.alert_model) # set the view btn # cancel will cancel the use of planet data and switch to GEE based map # instead # btn is called c_btn instead of cancel to avoid duplication self.btn = sw.Btn("apply", "fas fa-check", color="secondary") self.c_btn = sw.Btn("cancel", "fas fa-times", color="error", outlined=True, class_="mr-1") # set up an alert to show information to the user self.alert = sw.Alert() # bind the parameters to the model self.alert_model.bind(self.w_key, "api_key") # manually decorate the functions self.cancel = su.loading_button(self.alert, self.c_btn, True)(self.cancel) self.apply = su.loading_button(self.alert, self.btn, True)(self.apply) # create the object super().__init__( children=[ self.w_key, self.w_advance, sw.Row(class_="mt-2 ml-1", children=[self.c_btn, self.btn]), self.alert, ], class_="mt_5", elevation=False, ) # js bindings self.c_btn.on_event("click", self.cancel) self.btn.on_event("click", self.apply)
def __init__(self, aoi_model, model, viz_tile, export_tile, **kwargs): # gather the model self.aoi_model = aoi_model self.model = model self.viz_tile = viz_tile self.export_tile = export_tile # widgets w_time_title = v.Html(tag="H3", class_="mt-3", children=[ms.selection.time_range]) self.start_picker = sw.DatePicker(label=ms.selection.start) self.end_picker = sw.DatePicker(label=ms.selection.end) w_time_range = v.Layout(row=True, children=[self.start_picker, self.end_picker]) w_collection_title = v.Html(tag="H3", class_="mt-3", children=[ms.selection.collection]) self.sensors = v.Select( label=ms.selection.sensor, items=pm.sensors, v_model=None, chips=True, multiple=True, ) self.t2 = v.Switch(class_="ml-5", label=ms.selection.t2, v_model=False) self.sr = v.Switch(class_="ml-5", label=ms.selection.sr, v_model=False) self.model.bind(self.start_picker, "start").bind(self.end_picker, "end").bind( self.sensors, "sensors").bind(self.t2, "t2").bind(self.sr, "sr") # construct the Tile with the widget we have initialized super().__init__( id_= "selection_widget", # the id will be used to make the Tile appear and disapear title=ms.selection. title, # the Title will be displayed on the top of the tile inputs=[ w_time_title, w_time_range, w_collection_title, self.sensors, self.t2, self.sr, ], btn=sw.Btn(ms.selection.btn), alert=sw.Alert(), ) # now that the Tile is created we can link it to a specific function self.btn.on_event("click", self._on_run)
def __init__(self, class_path=Path("~").expanduser() / "downloads", *args, **kwargs): """Stand-alone tile composed by a select widget containing .csv reclassify files found in the class_path, and a ClassTable to edit and/or create a new classification table, Args: class_path (str) (optional): Folder path containing classification tables """ super().__init__(*args, **kwargs) self.title = v.CardTitle( children=["Edit or create new classifications"]) self.class_path = class_path self.w_class_file = v.Select( label="Select a classes file", items=self.get_items(), v_model="", dense=True, ) self.ct = ClassTable( out_path=self.class_path, schema={ "id": "number", "code": "number", "description": "string" }, ).hide() use_btn = sw.Btn("Get table") self.children = [ self.title, v.Flex( class_="ml-2 d-flex", children=[ self.w_class_file, use_btn, ], ), self.ct, ] self.get_classes_files() # Events # Listen Class table save dialog to refresh the classes widget self.ct.save_dialog.observe(self._refresh_files, "reload") # Get the corresponding table use_btn.on_event("click", self.get_class_table)
def __init__(self, model, aoi_model, viz_tile, export_tile, **kwargs): # Define the model and the aoi_model as class attribute so that they can be manipulated in its custom methods self.model = model self.aoi_model = aoi_model # LINK to the result tile self.viz_tile = viz_tile self.export_tile = export_tile # WIDGETS self.year_beg = v.Select( label=cm.process.slider_b, v_model=None, items=[i for i in range(pm.max_year, pm.min_year - 1, -1)], ) self.year_end = v.Select( label=cm.process.slider_e, v_model=None, items=[i for i in range(pm.max_year, pm.min_year - 1, -1)], ) self.type_tmf = v.RadioGroup( row=True, v_model=pm.layer_select[0]["value"], children=[ v.Radio(key=e["key"], label=e["label"], value=e["value"]) for e in pm.layer_select ], ) # self.type_tmf.observe(self._on_change, 'v_model') # Create the alert alert self.model.bind(self.year_beg, "year_beg").bind( self.year_end, "year_end").bind(self.type_tmf, "type_tmf") # construct the Tile with the widget we have initialized super().__init__( id_= "process_widget", # the id will be used to make the Tile appear and disapear title=cm.process. title, # the Title will be displayed on the top of the tile inputs=[self.year_beg, self.year_end, self.type_tmf], btn=sw.Btn(cm.process.validate, "mdi-check", disabled=False, class_="ma-5"), alert=sw.Alert(), ) # now that the Tile is created we can link it to a specific function self.btn.on_event("click", self._on_run)
def test_toggle_loading(self): btn = sw.Btn().toggle_loading() self.assertTrue(btn.loading) self.assertTrue(btn.disabled) btn.toggle_loading() self.assertFalse(btn.loading) self.assertFalse(btn.disabled) return
def close_filter_tile(w_selector): def on_click(widget, event, data, out, obj, alert): # Get the current path process_path = obj.get_current_path() # Clear output if there is something printed before out.clear_output() # Once the button is clicked, disable it btn.disable() # Clear old alert messages alert.clear() @out.capture() def run_process(obj): run_filter( process_path, alert, ) run_process(obj) btn.activate() out = Output() btn = s.Btn(text="Start") # Create an alert element for the process alert = s.Alert() content = v.Layout(xs12=True, row=True, class_="ma-5 d-block", children=[ filter_text, w_selector, btn, alert, out, ]) btn.on_event('click', partial( on_click, obj=w_selector, out=out, alert=alert, )) return content
def __init__(self, aoi, results_tile, *args, **kwargs): super().__init__(*args, **kwargs) self.aoi = aoi self.results_tile = results_tile self.alert = sw.Alert() self.btn = sw.Btn(ms.buttons.process.label) self.children = [self.alert, self.btn] self.btn.on_event('click', self.process_start)
def test_hide_component(self): # hide a normal v component widget = v.Btn() su.hide_component(widget) self.assertIn('d-none', widget.class_) # hide a sepalwidget widget = sw.Btn() su.hide_component(widget) self.assertFalse(widget.viz) return
def test_init(self): # minimal tooltip on a btn btn = sw.Btn('click') tooltip = sw.Tooltip(widget=btn, tooltip='Click over the button') # assert that a slot cannot be modified with self.assertRaises(Exception): tooltip.bottom = False return
def __init__(self): # create the widget file_input = sw.FileInput(extentions=['']) txt = sw.Markdown("here I will add a lot of explanations") # create the actual tile super().__init__( 'folder_tile', "Select folder", inputs = [txt, file_input], output = sw.Alert(), btn = sw.Btn("validate this folder") )
def __init__(self, class_path=Path('~').expanduser() / 'downloads', *args, **kwargs): """Stand-alone tile composed by a select widget containing .csv reclassify files found in the class_path, and a ClassTable to edit and/or create a new classification table, Args: class_path (str) (optional): Folder path containing classification tables """ super().__init__(*args, **kwargs) self.title = v.CardTitle( children=['Edit or create new classifications']) self.class_path = class_path self.w_class_file = v.Select(label='Select a classes file', items=self.get_items(), v_model='', dense=True) self.ct = ClassTable( out_path=self.class_path, schema={ 'id': 'number', 'code': 'number', 'description': 'string' }, ).hide() use_btn = sw.Btn('Get table') self.children = [ self.title, v.Flex(class_='ml-2 d-flex', children=[ self.w_class_file, use_btn, ]), self.ct ] self.get_classes_files() # Events # Listen Class table save dialog to refresh the classes widget self.ct.save_dialog.observe(self._refresh_files, 'reload') # Get the corresponding table use_btn.on_event('click', self.get_class_table)
def __init__(self, model, inputs): # gather model self.model = model super().__init__( self.model.tile_id, "Run Process", inputs=inputs, alert=sw.Alert(), btn=sw.Btn(cm.process.btn.format(model.process)), ) # link js behaviours self.btn.on_event("click", self._on_click)
def test_set_content(self): id_ = "id" title = "title" tile = sw.Tile(id_, title, alert=sw.Alert(), btn=sw.Btn()) input_ = v.Slider() res = tile.set_content([input_]) self.assertEqual(res, tile) self.assertEqual(tile.children[0].children[0].children[0], title) self.assertEqual(tile.children[0].children[1].children[0], input_) return
def test_set_icon(self): # new icon icon = 'mdi-folder' btn = sw.Btn().set_icon(icon) self.assertIsInstance(btn.v_icon, v.Icon) self.assertEqual(btn.v_icon.children[0], icon) # change existing icon icon = 'mdi-file' btn.set_icon(icon) self.assertEqual(btn.v_icon.children[0], icon) return
def test_show_component(self): # show a normal v component widget = v.Btn() su.hide_component(widget) su.show_component(widget) self.assertNotIn('d-none', widget.class_) # show a sepalwidget widget = sw.Btn() su.hide_component(widget) su.show_component(widget) self.assertTrue(widget.viz) return
def __init__(self, io, output, inputs): # gather io self.io = io # create the btn btn = sw.Btn(cm.process.btn.format(io.process)) super().__init__(self.io.tile_id, "Run Process", inputs=inputs, output=output, btn=btn) # link js behaviours btn.on_event('click', self._on_click)
def __init__(self, model, aoi_model): # gather models self.model = model self.aoi_model = aoi_model # create a result tile self.result_tile = sw.Tile('gfc_export_tile', "Results", inputs=['']) super().__init__("gfc_export_tile", "Export the data", btn=sw.Btn('Export data'), alert=sw.Alert(), inputs=[sw.Markdown(cm.gfc.txt)]) # add js behaviour self.btn.on_event('click', self._on_click)
def __init__(self): # create the widgets txt = sw.Markdown(cm.table.test.txt) self.alert = sw.Alert() # create the tile super().__init__( id_ = 'file_widget', title = cm.table.test.title, alert = self.alert, btn = sw.Btn(cm.table.test.btn, outlined=True, small=True), inputs = [txt] ) # js behaviour self.btn.on_event('click', self._import_test_file)