Skip to content

Commit c834170

Browse files
Merge pull request #20 from KitwareMedical/plug-action-buttons
Plug action buttons
2 parents 0a6f179 + 32d2ab8 commit c834170

23 files changed

Lines changed: 379 additions & 157 deletions

CONTRIBUTING.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Contributing to GirderEGGAnnotator
1+
# Contributing to GirderEEGAnnotator
22

33
1. Clone the repository using ``git clone``
44
2. Install the dev dependencies in your
@@ -17,7 +17,7 @@ pip install -e ."[dev]"
1717

1818
## Commit messages
1919

20-
GirderEGGAnnotator follows trame\'s commit message convention to be compatible with
20+
GirderEEGAnnotator follows trame\'s commit message convention to be compatible with
2121
its CI features including the auto semantic release.
2222

2323
## Tips

girdereegannotator/app/app_logic.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from girdereegannotator.utils.base_logic import BaseLogic
55

66
from ..authentication import AuthenticationLogic
7-
from ..eeg_annotator import EGGAnnotatorLogic
7+
from ..eeg_annotator import EEGAnnotatorLogic
88
from ..portal import PortalLogic
99
from .app_ui import AnnotatorAppState, AnnotatorAppUI
1010
from .components.navigation_card import NavigationWindow
@@ -15,7 +15,7 @@ def __init__(self, server: Server):
1515
super().__init__(server, AnnotatorAppState)
1616

1717
self._portal_logic = PortalLogic(self.server)
18-
self._eeg_annotator_logic = EGGAnnotatorLogic(self.server)
18+
self._eeg_annotator_logic = EEGAnnotatorLogic(self.server)
1919
self._auth_logic = AuthenticationLogic(server)
2020

2121
self._eeg_annotator_logic.next_clicked.connect(self._portal_logic.select_next_eeg)

girdereegannotator/app/app_ui.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
from girdereegannotator.utils.base_ui import BaseUI
99

1010
from ..authentication import AuthenticationUI
11-
from ..eeg_annotator import EGGAnnotatorUI
11+
from ..eeg_annotator import EEGAnnotatorUI
1212
from ..portal import PortalUI
1313
from .components.navigation_card import NavigationCard, NavigationState
1414

1515

1616
@dataclass
1717
class AnnotatorAppState:
18-
app_name: str = "GirderEGGAnnotator"
18+
app_name: str = "GirderEEGAnnotator"
1919
nav_state: NavigationState = field(default_factory=NavigationState)
2020

2121

@@ -50,12 +50,13 @@ def __init__(self, server: Server):
5050

5151
client.Style(
5252
"html { overflow-y: hidden; } "
53-
".annotation-actions { width: 130px; height: 100%; display: flex; align-items: center; justify-content: space-around }"
54-
".annotation-input { width: 450px; height: 100%; display: flex; align-items: center; }"
53+
".annotation-actions { height: 100%; display: flex; align-items: center; justify-content: space-around }"
54+
".annotation-input { height: 100%; display: flex; align-items: center; flex-grow: 1 }"
5555
".annotation-input__menu .v-field { background-color: inherit; }"
5656
".annotation-input__menu .v-field__input:has(.v-select__selection) { padding: 0; }"
5757
".annotation-input__menu { height: 100%; display: flex; flex-grow: 1; }"
5858
".annotation-list .annotation-list-item:hover { background-color: color-mix(in srgb, rgb(var(--v-theme-surface)) 95%, rgb(var(--v-theme-primary))); }"
59+
".annotation-tool { height: 100%; display: flex; align-items: center; width: 600px; }"
5960
".annotator { height: 100%; }"
6061
".annotator-tool { height: 100%; display: flex; flex-direction: column; }"
6162
".annotator-tool__content { height: 40px; padding-left: 8px; padding-right: 8px; display: flex; align-items: center; border-radius: 24px; background-color: rgb(var(--v-theme-surface-variant)); }"
@@ -91,6 +92,7 @@ def __init__(self, server: Server):
9192
".nav-bar { height: 65px; }"
9293
".nav-content { height: calc(100% - 65px); padding: 0px; }"
9394
".nav-window { height: 100%; }"
95+
".nav-window-group { height: 100%; overflow: unset; }"
9496
".portal { padding-left: 20px; padding-right: 20px; padding-bottom: 10px; height: 100%;}"
9597
".portal-toolbar { display: flex; flex-grow: 1; align-items: center; justify-content: end; height: 100%; }"
9698
".remote-controlled-area:focus-visible { outline: none !important; }"
@@ -109,6 +111,7 @@ def __init__(self, server: Server):
109111
".viewer__content { height: calc(100% - 5px); }"
110112
".viewer__error { height: calc(100% - 5px); }"
111113
".viewer__load { height: 5px; }"
114+
".viewer-status { padding: 6px; width: 36px; height: 36px; }"
112115
)
113116
with self.bar:
114117
self.auth_ui = AuthenticationUI()
@@ -123,7 +126,7 @@ def __init__(self, server: Server):
123126
self.portal_ui.build_toolbar()
124127

125128
with self.navigation.annotator:
126-
self.eeg_annotator_ui = EGGAnnotatorUI()
129+
self.eeg_annotator_ui = EEGAnnotatorUI()
127130

128131
with self.navigation.annotator_toolbar:
129132
self.eeg_annotator_ui.build_toolbar()

girdereegannotator/app/components/navigation_card.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def __init__(self, nav_state: TypedState[NavigationState], **kwargs):
4141

4242
with (
4343
v3.VCardText(classes="nav-content"),
44-
v3.VWindow(v_model=(nav_state.name.window,), classes="fill-height", style="overflow: unset;"),
44+
v3.VWindow(v_model=(nav_state.name.window,), classes="nav-window-group"),
4545
):
4646
self.portal = v3.VWindowItem(classes="nav-window", value=(NavigationWindow.PORTAL.value,))
4747
self.annotator = v3.VWindowItem(

girdereegannotator/database/girder/girder_bids_handler.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
from ..models import (
1212
AnnotationsFile,
13+
AnnotationStatus,
1314
Asset,
1415
Dataset,
1516
EEGFile,
@@ -162,6 +163,7 @@ def _find_annotations_files(
162163
_id=annotations_file["_id"],
163164
name=annotations_file["name"],
164165
author=self._get_user_from_id(annotations_file["creatorId"]),
166+
status=AnnotationStatus(annotations_file["bids_metadata"].get("status", AnnotationStatus.IN_PROGRESS)),
165167
)
166168
for annotations_file in eeg_annotations_files
167169
]
@@ -178,6 +180,12 @@ def upload_annotations_file(
178180
)
179181
return AnnotationsFile(_id=file._id, name=file.name, author=author)
180182

183+
def update_annotation_status(self, annotations_file: AnnotationsFile) -> AnnotationsFile:
184+
self.girder_client.put(
185+
path=f"{self.resource.file}/{annotations_file._id}/metadata",
186+
parameters={"metadata": json.dumps({"status": annotations_file.status.value})},
187+
)
188+
181189
def download_file(self, file: EEGFile, path: Path, refresh: bool = False) -> Asset:
182190
asset = self._load_asset_from_file(file)
183191
if not path.exists() or refresh:

girdereegannotator/database/girder/girder_database.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ def download_eeg_files(
158158
if annotations_file is None:
159159
annotations_asset_name = self.bids_handler.get_next_annotations_file_name(eeg_fileset)
160160
annotations_asset_path = Path(download_dir) / annotations_asset_name
161+
if annotations_asset_path.exists():
162+
annotations_asset_path.unlink()
161163
annotations_asset_path.touch()
162164
annotations_asset = Asset(annotations_asset_name, str(annotations_asset_path))
163165

@@ -175,3 +177,19 @@ def upload_annotations_file(self, eeg_fileset: EEGFileset, annotations_asset: As
175177
raise DatabaseError(
176178
f"Could not upload annotations file {annotations_asset.name} to {eeg_fileset.name}: {handle_database_error(e)}"
177179
) from e
180+
181+
def update_annotations_file_status(self, annotations_file: AnnotationsFile) -> None:
182+
try:
183+
self.bids_handler.update_annotation_status(annotations_file)
184+
except GirderHTTPError as e:
185+
raise DatabaseError(
186+
f"Could not update annotations file ({annotations_file.name}) status to {annotations_file.status.value}: {handle_database_error(e)}"
187+
) from e
188+
189+
def delete_annotations_file(self, annotations_file: AnnotationsFile) -> None:
190+
try:
191+
self.girder_client.delete(f"item/{annotations_file._id}")
192+
except GirderHTTPError as e:
193+
raise DatabaseError(
194+
f"Could not delete annotations file ({annotations_file.name}): {handle_database_error(e)}"
195+
) from e

girdereegannotator/database/interface_database.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ def download_eeg_files(
4545
def upload_annotations_file(self, eeg_fileset: EEGFileset, eeg_annotations_asset: Asset) -> AnnotationsFile:
4646
pass
4747

48+
@abstractmethod
49+
def update_annotations_file_status(self, annotations_file: AnnotationsFile) -> None:
50+
pass
51+
52+
@abstractmethod
53+
def delete_annotations_file(self, annotations_file: AnnotationsFile) -> None:
54+
pass
55+
4856

4957
def register_interface(interface: DatabaseInterface, controller: Controller) -> None:
5058
"""Register all interface methods in the controller"""

girdereegannotator/database/models.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class EEGFile(Model): ...
5757

5858

5959
class AnnotationStatus(Enum):
60+
UNDEFINED = auto()
6061
IN_PROGRESS = auto()
6162
IN_REVIEW = auto()
6263
DONE = auto()
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from .eeg_annotator_logic import EGGAnnotatorLogic
2-
from .eeg_annotator_ui import EGGAnnotatorUI
1+
from .eeg_annotator_logic import EEGAnnotatorLogic
2+
from .eeg_annotator_ui import EEGAnnotatorUI
33

4-
__all__ = ["EGGAnnotatorLogic", "EGGAnnotatorUI"]
4+
__all__ = ["EEGAnnotatorLogic", "EEGAnnotatorUI"]
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
from .annotation_actions import AnnotateActions, NoAction, ReadonlyAction, ReviewActions
1+
from .annotation_actions import AnnotateActions, ReviewActions
22
from .annotation_input import AnnotationInput
33
from .fileset_input import FilesetInput
44
from .rca_view import RCAView, RCAViewError, RCAViewMode
55
from .shortcuts_panel import ShortcutsPanel
6+
from .viewer_status import ViewerStatus
67

78
__all__ = [
89
"AnnotateActions",
910
"AnnotationInput",
1011
"FilesetInput",
11-
"NoAction",
1212
"RCAView",
1313
"RCAViewError",
1414
"RCAViewMode",
15-
"ReadonlyAction",
1615
"ReviewActions",
1716
"ShortcutsPanel",
17+
"ViewerStatus",
1818
]

0 commit comments

Comments
 (0)