Add way for gallery providers to specify bulk actions.
This commit is contained in:
parent
3e38722d45
commit
2dcd386661
4 changed files with 57 additions and 0 deletions
|
|
@ -332,6 +332,13 @@ class BaseCamera(OFMThing, ABC):
|
||||||
self.logger.info(f"Deleting: {capture}")
|
self.logger.info(f"Deleting: {capture}")
|
||||||
os.remove(capture)
|
os.remove(capture)
|
||||||
|
|
||||||
|
def get_gallery_bulk_actions(self) -> list[ActionButton]:
|
||||||
|
"""Return the bulk gallery actions for cameras.
|
||||||
|
|
||||||
|
By default there are no bulk actions.
|
||||||
|
"""
|
||||||
|
return []
|
||||||
|
|
||||||
@lt.endpoint(
|
@lt.endpoint(
|
||||||
"delete",
|
"delete",
|
||||||
"capture/{name}",
|
"capture/{name}",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ from pydantic import BaseModel
|
||||||
import labthings_fastapi as lt
|
import labthings_fastapi as lt
|
||||||
|
|
||||||
from openflexure_microscope_server.things import OFMThing
|
from openflexure_microscope_server.things import OFMThing
|
||||||
|
from openflexure_microscope_server.ui import ActionButton
|
||||||
|
|
||||||
|
|
||||||
@runtime_checkable
|
@runtime_checkable
|
||||||
|
|
@ -38,6 +39,8 @@ class GalleryCompatibleThing(Protocol):
|
||||||
|
|
||||||
def delete_all_gallery_items(self) -> None: ... # noqa: D102
|
def delete_all_gallery_items(self) -> None: ... # noqa: D102
|
||||||
|
|
||||||
|
def get_gallery_bulk_actions(self) -> list[ActionButton]: ... # noqa: D102
|
||||||
|
|
||||||
|
|
||||||
class GalleryThing(lt.Thing):
|
class GalleryThing(lt.Thing):
|
||||||
"""A Thing for communicating with the front end gallery."""
|
"""A Thing for communicating with the front end gallery."""
|
||||||
|
|
@ -125,6 +128,19 @@ class GalleryThing(lt.Thing):
|
||||||
raise RuntimeError("Cannot access card_types before server has started.")
|
raise RuntimeError("Cannot access card_types before server has started.")
|
||||||
return self._card_types
|
return self._card_types
|
||||||
|
|
||||||
|
# Cache result after first call.
|
||||||
|
_bulk_actions: Optional[list[ActionButton]] = None
|
||||||
|
|
||||||
|
@lt.property
|
||||||
|
def bulk_actions(self) -> list[ActionButton]:
|
||||||
|
"""All bulk actions."""
|
||||||
|
if self._bulk_actions is None:
|
||||||
|
actions: list[ActionButton] = []
|
||||||
|
for thing in self.gallery_providing_things.values():
|
||||||
|
actions += thing.get_gallery_bulk_actions()
|
||||||
|
self._bulk_actions = actions
|
||||||
|
return self._bulk_actions
|
||||||
|
|
||||||
@lt.property
|
@lt.property
|
||||||
def list_data(self) -> list[dict[str, Any]]:
|
def list_data(self) -> list[dict[str, Any]]:
|
||||||
"""List the data from all registered things.
|
"""List the data from all registered things.
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ import labthings_fastapi as lt
|
||||||
|
|
||||||
from openflexure_microscope_server import scan_directories, stitching
|
from openflexure_microscope_server import scan_directories, stitching
|
||||||
from openflexure_microscope_server.things import OFMThing
|
from openflexure_microscope_server.things import OFMThing
|
||||||
|
from openflexure_microscope_server.ui import ActionButton, action_button_for
|
||||||
from openflexure_microscope_server.utilities import coerce_thing_selector
|
from openflexure_microscope_server.utilities import coerce_thing_selector
|
||||||
|
|
||||||
# Things
|
# Things
|
||||||
|
|
@ -199,6 +200,26 @@ class SmartScanThing(OFMThing):
|
||||||
self.logger.info(f"Deleting: {scan_name}")
|
self.logger.info(f"Deleting: {scan_name}")
|
||||||
self._delete_scan(scan_name)
|
self._delete_scan(scan_name)
|
||||||
|
|
||||||
|
def get_gallery_bulk_actions(self) -> list[ActionButton]:
|
||||||
|
"""Return the bulk gallery actions for smart scan."""
|
||||||
|
# Stitch all scans
|
||||||
|
return [
|
||||||
|
action_button_for(
|
||||||
|
self,
|
||||||
|
"stitch_all_scans",
|
||||||
|
submit_label="Stitch All Unstitched Scans",
|
||||||
|
can_terminate=True,
|
||||||
|
button_primary=False,
|
||||||
|
modal_progress=True,
|
||||||
|
requires_confirmation=True,
|
||||||
|
confirmation_message=(
|
||||||
|
"<h3>Stitch all unstitched scans?</h3>"
|
||||||
|
"<br>Depending on the number and size of scans, this may be slow, "
|
||||||
|
"and your microscope should not be used during the stitching.'"
|
||||||
|
),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
# Note that the default detector name is set at init. This is over written if
|
# Note that the default detector name is set at init. This is over written if
|
||||||
# setting is loaded from disk.
|
# setting is loaded from disk.
|
||||||
@lt.setting
|
@lt.setting
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ from openflexure_microscope_server.things.gallery import (
|
||||||
GalleryCompatibleThing,
|
GalleryCompatibleThing,
|
||||||
GalleryThing,
|
GalleryThing,
|
||||||
)
|
)
|
||||||
|
from openflexure_microscope_server.ui import ActionButton
|
||||||
|
|
||||||
from ..shared_utils.lt_test_utils import LabThingsTestEnv
|
from ..shared_utils.lt_test_utils import LabThingsTestEnv
|
||||||
|
|
||||||
|
|
@ -63,6 +64,10 @@ class MinimalGalleryClass:
|
||||||
def delete_all_gallery_items(self) -> None:
|
def delete_all_gallery_items(self) -> None:
|
||||||
"""Mock deleting all the data."""
|
"""Mock deleting all the data."""
|
||||||
|
|
||||||
|
def get_gallery_bulk_actions(self) -> list[ActionButton]:
|
||||||
|
"""No bulk actions."""
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
class MinimalGallerySource(OFMThing, MinimalGalleryClass):
|
class MinimalGallerySource(OFMThing, MinimalGalleryClass):
|
||||||
"""Minimal example of a Thing that can show data in the gallery.
|
"""Minimal example of a Thing that can show data in the gallery.
|
||||||
|
|
@ -94,6 +99,10 @@ class BadGallerySource(OFMThing):
|
||||||
def delete_all_gallery_items(self) -> None:
|
def delete_all_gallery_items(self) -> None:
|
||||||
"""Mock deleting all the data."""
|
"""Mock deleting all the data."""
|
||||||
|
|
||||||
|
def get_gallery_bulk_actions(self) -> list[ActionButton]:
|
||||||
|
"""No bulk actions."""
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
class BadMockGalleryData(BaseModel):
|
class BadMockGalleryData(BaseModel):
|
||||||
"""Mock gallery data without a card type."""
|
"""Mock gallery data without a card type."""
|
||||||
|
|
@ -119,6 +128,10 @@ class BadGallerySource2(OFMThing):
|
||||||
def delete_all_gallery_items(self) -> None:
|
def delete_all_gallery_items(self) -> None:
|
||||||
"""Mock deleting all the data."""
|
"""Mock deleting all the data."""
|
||||||
|
|
||||||
|
def get_gallery_bulk_actions(self) -> list[ActionButton]:
|
||||||
|
"""No bulk actions."""
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
def test_gallery_compatible_protocol():
|
def test_gallery_compatible_protocol():
|
||||||
"""Check the gallery compatible protocol detects compatible classes only."""
|
"""Check the gallery compatible protocol detects compatible classes only."""
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue