From 24e5749f50fa20224a1af447d9243e96669fb167 Mon Sep 17 00:00:00 2001 From: Julian Stirling Date: Fri, 19 Sep 2025 15:19:37 +0100 Subject: [PATCH 1/4] Remove commented out CSS in scanListContent --- .../tabContentComponents/scanListContent.vue | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/webapp/src/components/tabContentComponents/scanListContent.vue b/webapp/src/components/tabContentComponents/scanListContent.vue index 65363c43..1abed3a0 100644 --- a/webapp/src/components/tabContentComponents/scanListContent.vue +++ b/webapp/src/components/tabContentComponents/scanListContent.vue @@ -364,39 +364,6 @@ export default { .gallery-folder-heading { margin-bottom: 30px; } -/* -.gallery-grid { - display: grid; - grid-template-columns: repeat(auto-fill, 320px); - justify-content: center; - overflow-y: hidden; -} - -.gallery-grid > div { - display: inline-block; - margin-bottom: 20px; -} - -#openseadragon { - width: 100%; - height: 100%; -} -#info-panel { - position: absolute; - top: 10px; - left: 10px; - background-color: rgba(255, 255, 255, 0.7); - padding: 5px; - border-radius: 1px; - z-index: 1000; -} - -/deep/ .capture-card { - width: 300px; - height: 100%; // Used to have all cards in a row match their heights - margin-left: auto; - margin-right: auto; -}*/ ul { display: inline-block; From 2fd3a8f6966d8789bc034681c52e27a9e07bc80e Mon Sep 17 00:00:00 2001 From: Julian Stirling Date: Fri, 19 Sep 2025 16:49:47 +0100 Subject: [PATCH 2/4] Split scan cards and scan list components --- .../scanListComponents/scanCard.vue | 173 ++++++++++++++++++ .../tabContentComponents/scanListContent.vue | 171 ++--------------- 2 files changed, 190 insertions(+), 154 deletions(-) create mode 100644 webapp/src/components/tabContentComponents/scanListComponents/scanCard.vue diff --git a/webapp/src/components/tabContentComponents/scanListComponents/scanCard.vue b/webapp/src/components/tabContentComponents/scanListComponents/scanCard.vue new file mode 100644 index 00000000..092da2ce --- /dev/null +++ b/webapp/src/components/tabContentComponents/scanListComponents/scanCard.vue @@ -0,0 +1,173 @@ + + + + \ No newline at end of file diff --git a/webapp/src/components/tabContentComponents/scanListContent.vue b/webapp/src/components/tabContentComponents/scanListContent.vue index 1abed3a0..d4434415 100644 --- a/webapp/src/components/tabContentComponents/scanListContent.vue +++ b/webapp/src/components/tabContentComponents/scanListContent.vue @@ -60,12 +60,12 @@ fullscreen -
- +
+
@@ -84,97 +84,30 @@ There are no scans available to show.

-
-
-
-
-
- -
-
-

{{ item.name }}

-
-
- - -
- - - -
-
-
    -
  • {{ item.number_of_images }} images
  • -
  • created: {{ formatDate(item.created) }}
  • -
  • modified: {{ formatDate(item.modified) }}
  • -
-
  • Not enough images to stitch
  • -
  • Interactive preview not available
  • -
  • High quality stitch not available
  • -
    -
    +
    +
    - @@ -365,23 +247,4 @@ export default { margin-bottom: 30px; } -ul { - display: inline-block; - text-align: center; - list-style-type:none; - margin: 5px 0px 10px 0px; -} - -.warning-msg { - color: red; - text-align: center; - font-weight: bold; -} - -.alert-msg{ - color: orange; - text-align: center; - font-weight: bold; -} - \ No newline at end of file From 29a62a278b52a6554d19acf048ce544f0bab46f9 Mon Sep 17 00:00:00 2001 From: Julian Stirling Date: Fri, 19 Sep 2025 17:49:28 +0100 Subject: [PATCH 3/4] Update scan card to use computed properties and request new thumb if modified date changed --- .../scanListComponents/scanCard.vue | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/webapp/src/components/tabContentComponents/scanListComponents/scanCard.vue b/webapp/src/components/tabContentComponents/scanListComponents/scanCard.vue index 092da2ce..cef8e35b 100644 --- a/webapp/src/components/tabContentComponents/scanListComponents/scanCard.vue +++ b/webapp/src/components/tabContentComponents/scanListComponents/scanCard.vue @@ -8,7 +8,7 @@ @@ -32,13 +32,13 @@ class="uk-width-1-2" :buttonPrimary=true :isDisabled=!scanData.stitch_available - :URL="downloadStitchFile( scanData.name )" + :URL="downloadStitchFile" buttonLabel="Download JPEG" /> @@ -95,16 +95,16 @@ export default { } }, + computed: { + downloadStitchFile() { + return `${this.$store.getters.baseUri}/smart_scan/get_stitch/${this.scanData.name}`; + }, + thumbnailPath() { + return `${this.$store.getters.baseUri}/smart_scan/scans/stitched_thumbnail.jpg?scan_name=${this.scanData.name}&modified=${this.scanData.modified}`; + }, + }, + methods: { - downloadStitchFile: function(name) { - return `${this.$store.getters.baseUri}/smart_scan/get_stitch/${name}`; - }, - thumbnailPath(scan_name) { - return ( - `${this.$store.getters.baseUri}/smart_scan/scans/stitched_thumbnail.jpg?scan_name=` + - scan_name - ); - }, formatDate(timestamp) { // Multiply by 1000 as JS uses ms not s let d = new Date(timestamp*1000); @@ -126,12 +126,12 @@ export default { // Notify parent that thumbnail was clicked this.$emit('viewer-requested', this.scanData); }, - async deleteScan(name) { + async deleteScan() { try { - await this.modalConfirm(`Are you sure you want to delete ${name}?`); - await axios.delete(`${this.scansUri}/${name}`); + await this.modalConfirm(`Are you sure you want to delete ${this.scanData.name}?`); + await axios.delete(`${this.scansUri}/${this.scanData.name}`); this.$emit('update-requested'); - this.modalNotify(`Deleted ${name}`); + this.modalNotify(`Deleted ${this.scanData.name}`); } catch (e) { // if the confirmation was cancelled, it's rejected with null error if (e) this.modalError(e); From cd6bcd196f8062332a0fb3f9c401b34531bc886c Mon Sep 17 00:00:00 2001 From: Julian Stirling Date: Fri, 19 Sep 2025 18:29:34 +0100 Subject: [PATCH 4/4] Don't show buttons for ongoing scans. --- .../things/smart_scan.py | 18 ++- .../scanListComponents/scanCard.vue | 129 +++++++++++------- .../tabContentComponents/scanListContent.vue | 9 +- 3 files changed, 100 insertions(+), 56 deletions(-) diff --git a/src/openflexure_microscope_server/things/smart_scan.py b/src/openflexure_microscope_server/things/smart_scan.py index 1b760e13..44fddb61 100644 --- a/src/openflexure_microscope_server/things/smart_scan.py +++ b/src/openflexure_microscope_server/things/smart_scan.py @@ -17,6 +17,7 @@ from subprocess import SubprocessError from fastapi import HTTPException from fastapi.responses import FileResponse import numpy as np +from pydantic import BaseModel import labthings_fastapi as lt @@ -39,6 +40,16 @@ CSMDep = lt.deps.direct_thing_client_dependency( AutofocusDep = lt.deps.direct_thing_client_dependency(AutofocusThing, "/autofocus/") +class ScanListData(BaseModel): + """The data to be sent to the Scan List tab.""" + + scans: list[scan_directories.ScanInfo] + """The list of scans as ScanInfo objects""" + + ongoing: Optional[str] + """The name of the ongoing scan or None""" + + class JPEGBlob(lt.blob.Blob): """A class representing a JPEG image as a LabThings FastAPI Blob.""" @@ -557,7 +568,7 @@ class SmartScanThing(lt.Thing): """Whether to run a final stitch at the end of a successful scan.""" @lt.thing_property - def scans(self) -> list[scan_directories.ScanInfo]: + def scans(self) -> ScanListData: """All the available scans. Each scan has a name (which can be used to access it), along with @@ -566,7 +577,10 @@ class SmartScanThing(lt.Thing): uses a regular expression, and changes to the naming scheme will break it. """ - return self._scan_dir_manager.all_scans_info() + return ScanListData( + scans=self._scan_dir_manager.all_scans_info(), + ongoing=None if self._ongoing_scan is None else self._ongoing_scan.name, + ) @lt.fastapi_endpoint( "get", diff --git a/webapp/src/components/tabContentComponents/scanListComponents/scanCard.vue b/webapp/src/components/tabContentComponents/scanListComponents/scanCard.vue index cef8e35b..a44d5406 100644 --- a/webapp/src/components/tabContentComponents/scanListComponents/scanCard.vue +++ b/webapp/src/components/tabContentComponents/scanListComponents/scanCard.vue @@ -14,61 +14,64 @@ /> -

    {{ scanData.name }}

    -
    -
    - - {{ scanData.name }} +

    Scan in progress

    +
    +
    + -
    - - - + +
    + + +
    -
      -
    • {{ scanData.number_of_images }} images
    • -
    • created: {{ formatDate(scanData.created) }}
    • -
    • modified: {{ formatDate(scanData.modified) }}
    • -
    -
  • Not enough images to stitch
  • -
  • Interactive preview not available
  • -
  • High quality stitch not available
  • +
      +
    • {{ scanData.number_of_images }} images
    • +
    • created: {{ formatDate(scanData.created) }}
    • +
    • modified: {{ formatDate(scanData.modified) }}
    • +
    +
      +
    • Not enough images to stitch
    • +
    • Interactive preview not available
    • +
    • High quality stitch not available
    • +
    @@ -92,6 +95,10 @@ export default { scansUri: { type: String, required: true + }, + ongoing: { + type: Boolean, + required: true } }, @@ -124,7 +131,9 @@ export default { }, requestViewer() { // Notify parent that thumbnail was clicked - this.$emit('viewer-requested', this.scanData); + if (!this.ongoing) { + this.$emit('viewer-requested', this.scanData); + } }, async deleteScan() { try { @@ -165,9 +174,23 @@ ul { font-weight: bold; } -.alert-msg{ +.alert-msg { color: orange; text-align: center; font-weight: bold; } + +.scan-card-buttons { + width: 100%; +} + +.scan-card-title { + text-align: center; +} + +.ongoing-msg { + text-align: center; + padding: 2rem 0; +} + \ No newline at end of file diff --git a/webapp/src/components/tabContentComponents/scanListContent.vue b/webapp/src/components/tabContentComponents/scanListContent.vue index d4434415..7cf1d4dc 100644 --- a/webapp/src/components/tabContentComponents/scanListContent.vue +++ b/webapp/src/components/tabContentComponents/scanListContent.vue @@ -88,6 +88,7 @@ @@ -112,6 +113,7 @@ export default { data: function() { return { scans: [], + ongoing: null, selectedScan: null, osdViewer: null }; @@ -191,7 +193,9 @@ export default { }, async updateScans() { try { - let scans = await this.readThingProperty("smart_scan", "scans"); + let scans_information = await this.readThingProperty("smart_scan", "scans"); + let scans = scans_information.scans + this.ongoing = scans_information.ongoing if (!scans | (scans.length == 0)) { this.scans = scans; } @@ -208,6 +212,9 @@ export default { this.scans = []; } }, + isOngoing(name) { + return name === this.ongoing + }, async deleteAllScans() { try { await this.modalConfirm(