diff --git a/docs/source/_static/switcher.json b/docs/source/_static/switcher.json index d472185f..790dd126 100644 --- a/docs/source/_static/switcher.json +++ b/docs/source/_static/switcher.json @@ -1,12 +1,17 @@ [ { - "name": "dev", + "name": "main", "version": "latest", "url": "https://sepal-ui.readthedocs.io/en/latest/" }, { - "name": "2.9.0 (stable)", - "version": "v_2.9.0", - "url": "https://sepal-ui.readthedocs.io/en/v_2.9.0" + "name": "2.10.0 (stable)", + "version": "v_2.10.0", + "url": "https://sepal-ui.readthedocs.io/en/v_2.10.0" + } + { + "name": "2.9.4", + "version": "v_2.9.4", + "url": "https://sepal-ui.readthedocs.io/en/v_2.9.4" } ] \ No newline at end of file diff --git a/sepal_ui/frontend/css/custom.css b/sepal_ui/frontend/css/custom.css index 89a6d900..65c9147f 100644 --- a/sepal_ui/frontend/css/custom.css +++ b/sepal_ui/frontend/css/custom.css @@ -3,4 +3,5 @@ .leaflet-widgetcontrol {box-shadow: none;} main.v-content {padding-top: 0px !important;} .leaflet-control-container .vuetify-styles .v-application {background: rgb(0,0,0,0);} -.v-alert__wrapper .progress {background-color: transparent;} \ No newline at end of file +.v-alert__wrapper .progress {background-color: transparent;} +header.v-app-bar {z-index: 800 !important} \ No newline at end of file diff --git a/sepal_ui/mapping/aoi_control.py b/sepal_ui/mapping/aoi_control.py index 26c1337a..7b5e6ac1 100644 --- a/sepal_ui/mapping/aoi_control.py +++ b/sepal_ui/mapping/aoi_control.py @@ -25,20 +25,18 @@ class AoiControl(MenuControl): def __init__(self, m, **kwargs): - # load the map - self.m = m - # init the aoi data list self.aoi_bounds = {} # set some default parameters kwargs["position"] = kwargs.pop("position", "topright") + kwargs["m"] = m # create a list self.aoi_list = sw.ListItemGroup(children=[], v_model="") # create the widget - super().__init__("fas fa-search-location", self.aoi_list) + super().__init__("fas fa-search-location", self.aoi_list, **kwargs) # change a bit the behavior of the control self.menu.open_on_hover = True diff --git a/sepal_ui/mapping/menu_control.py b/sepal_ui/mapping/menu_control.py index 232101e8..1f2db123 100644 --- a/sepal_ui/mapping/menu_control.py +++ b/sepal_ui/mapping/menu_control.py @@ -6,7 +6,7 @@ class MenuControl(WidgetControl): """ - Widget control displaying a btn on the map. When clicked the menu expand to show the content set by the user. + Widget control displaying a btn on the map. When clicked the menu expand to show the content set by the user and all the others are closed. It's used to display interactive tiles directly in the map. If the card_content is a Tile it will be automatically nested. Args: @@ -18,7 +18,13 @@ class MenuControl(WidgetControl): menu = None "sw.Menu: the menu displayed on the map as a widget" - def __init__(self, icon_content, card_content, card_title=None, **kwargs): + m = None + "sm.SepalMap: the map used to display the control" + + def __init__(self, icon_content, card_content, card_title=None, m=None, **kwargs): + + # save the map in the members + self.m = m # create a clickable btn btn = MapBtn(content=icon_content, v_on="menu.on") @@ -68,6 +74,7 @@ def __init__(self, icon_content, card_content, card_title=None, **kwargs): # add some interaction self.observe(self.update_position, "position") + self.menu.observe(self.close_others, "v_model") def update_position(self, change): """ @@ -103,3 +110,22 @@ def set_size(self, **kwargs): card.max_height = kwargs.pop("max_height", "40vh") return self + + def close_others(self, change): + """Close all the other menus associated to the map to avoid overlapping""" + + # don't do anything if no map was set to avoid deprecation + # remove when jumping to sepal-ui 3.0 + if self.m is None: + return + + # avoid infinite loop by exiting the method when it's closed + if self.menu.v_model is True: + + [ + setattr(c.menu, "v_model", False) + for c in self.m.controls + if isinstance(c, MenuControl) and c != self + ] + + return diff --git a/sepal_ui/mapping/value_inspector.py b/sepal_ui/mapping/value_inspector.py index 3d61dfe7..5cebbd77 100644 --- a/sepal_ui/mapping/value_inspector.py +++ b/sepal_ui/mapping/value_inspector.py @@ -40,11 +40,9 @@ class ValueInspector(MenuControl): def __init__(self, m, **kwargs): - # load the map - self.m = m - # set some default parameters kwargs["position"] = kwargs.pop("position", "topleft") + kwargs["m"] = m # create a loading to place it on top of the card. It will always be visible # even when the card is scrolled diff --git a/sepal_ui/sepalwidgets/alert.py b/sepal_ui/sepalwidgets/alert.py index efa852b7..68e3f115 100644 --- a/sepal_ui/sepalwidgets/alert.py +++ b/sepal_ui/sepalwidgets/alert.py @@ -90,6 +90,9 @@ def update_progress(self, progress, msg="Progress", **tqdm_args): self """ + # show the alert + self.show() + # cast the progress to float progress = float(progress) if not (0 <= progress <= 1): diff --git a/tests/test_Alert.py b/tests/test_Alert.py index d125b74e..fd99907d 100644 --- a/tests/test_Alert.py +++ b/tests/test_Alert.py @@ -178,6 +178,7 @@ def test_update_progress(self): # test a random update alert.update_progress(0.5) assert alert.progress_bar.n == 50 + assert alert.viz is True # show that a value > 1 raise an error with pytest.raises(ValueError): diff --git a/tests/test_MenuControl.py b/tests/test_MenuControl.py index 979c67f2..eec567cc 100644 --- a/tests/test_MenuControl.py +++ b/tests/test_MenuControl.py @@ -51,3 +51,33 @@ def test_update_position(self): assert menu_control.menu.right is True return + + def test_close_others(self): + + # add controls on the map + m = sm.SepalMap() + control_1 = sm.MenuControl("fas fa-folder", sw.Card(), m=m) + control_2 = sm.MenuControl("fas fa-folder", sw.Card(), m=m) + control_3 = sm.MenuControl("fas fa-folder", sw.Card()) + m.add_control(control_1) + m.add_control(control_2) + m.add_control(control_3) + + # open the first one and then the second one + control_1.menu.v_model = True + control_2.menu.v_model = True + control_3.menu.v_model = False + + # check the values + assert control_1.menu.v_model is False + assert control_2.menu.v_model is True + assert control_3.menu.v_model is False + + # use the control that is not wired + control_3.menu.v_model = True + + assert control_1.menu.v_model is False + assert control_2.menu.v_model is True + assert control_3.menu.v_model is True + + return