diff --git a/webapp/src/components/appContent.vue b/webapp/src/components/appContent.vue index 29af3e5e..9ddf17ae 100644 --- a/webapp/src/components/appContent.vue +++ b/webapp/src/components/appContent.vue @@ -85,7 +85,7 @@ import aboutContent from "./tabContentComponents/aboutContent.vue"; import controlContent from "./tabContentComponents/controlContent.vue"; import loggingContent from "./tabContentComponents/loggingContent.vue"; import powerContent from "./tabContentComponents/powerContent.vue"; -import scanListContent from "./tabContentComponents/scanListContent.vue"; +import galleryContent from "./tabContentComponents/galleryContent.vue"; import settingsContent from "./tabContentComponents/settingsContent.vue"; import slideScanContent from "./tabContentComponents/slideScanContent.vue"; import viewContent from "./tabContentComponents/viewContent.vue"; @@ -158,10 +158,10 @@ export default { requiredThings: ["smart_scan"], }, { - id: "scan-list", - title: "Scan List", + id: "gallery", + title: "Gallery", icon: "photo_library", - component: markRaw(scanListContent), + component: markRaw(galleryContent), requiredThings: ["smart_scan"], }, ], diff --git a/webapp/src/components/tabContentComponents/scanListComponents/scanCard.vue b/webapp/src/components/tabContentComponents/galleryComponents/galleryCard.vue similarity index 77% rename from webapp/src/components/tabContentComponents/scanListComponents/scanCard.vue rename to webapp/src/components/tabContentComponents/galleryComponents/galleryCard.vue index 8f448815..d9b32d11 100644 --- a/webapp/src/components/tabContentComponents/scanListComponents/scanCard.vue +++ b/webapp/src/components/tabContentComponents/galleryComponents/galleryCard.vue @@ -12,16 +12,16 @@ /> -

{{ scanData.name }}

+
-
+
-
+
    -
  • {{ scanData.number_of_images }} images
  • -
  • Created: {{ formatDate(scanData.created) }}
  • -
  • Duration: {{ formatDuration(scanData.duration) }}
  • +
  • {{ itemData.number_of_images }} images
  • +
  • Created: {{ formatDate(itemData.created) }}
  • +
  • Duration: {{ formatDuration(itemData.duration) }}
    -
  • +
  • Not enough images to stitch
  • -
  • +
  • Interactive preview not available
  • -
  • +
  • High quality stitch not available
@@ -85,21 +85,17 @@ import { useSettingsStore } from "@/stores/settings.js"; // Export main app export default { - name: "ScanCard", + name: "GalleryCard", components: { actionButton, EndpointButton, }, props: { - scanData: { + itemData: { type: Object, required: true, }, - scansUri: { - type: String, - required: true, - }, }, emits: ["viewer-requested", "update-requested"], @@ -107,10 +103,10 @@ export default { computed: { ...mapState(useSettingsStore, ["baseUri"]), downloadStitchFile() { - return `${this.baseUri}/smart_scan/get_stitch/${this.scanData.name}`; + return `${this.baseUri}/smart_scan/get_stitch/${this.itemData.name}`; }, thumbnailPath() { - return `${this.baseUri}/smart_scan/scans/stitched_thumbnail.jpg?scan_name=${this.scanData.name}&modified=${this.scanData.modified}`; + return `${this.baseUri}/smart_scan/scans/stitched_thumbnail.jpg?scan_name=${this.itemData.name}&modified=${this.itemData.modified}`; }, }, @@ -142,14 +138,14 @@ export default { }, requestViewer() { // Notify parent that thumbnail was clicked - this.$emit("viewer-requested", this.scanData); + this.$emit("viewer-requested", this.itemData); }, async deleteScan() { try { - await this.modalConfirm(`Are you sure you want to delete ${this.scanData.name}?`); - await axios.delete(`${this.scansUri}/${this.scanData.name}`); + await this.modalConfirm(`Are you sure you want to delete ${this.itemData.name}?`); + await axios.delete(`${this.baseUri}/smart_scan/scans/${this.itemData.name}`); this.$emit("update-requested"); - this.modalNotify(`Deleted ${this.scanData.name}`); + this.modalNotify(`Deleted ${this.itemData.name}`); } catch (e) { // if the confirmation was cancelled, it's rejected with null error if (e) this.modalError(e); @@ -189,11 +185,11 @@ ul { font-weight: bold; } -.scan-card-buttons { +.gallery-card-buttons { width: 100%; } -.scan-card-title { +.gallery-card-title { text-align: center; } diff --git a/webapp/src/components/tabContentComponents/scanListComponents/openSeadragonViewer.vue b/webapp/src/components/tabContentComponents/galleryComponents/openSeadragonViewer.vue similarity index 100% rename from webapp/src/components/tabContentComponents/scanListComponents/openSeadragonViewer.vue rename to webapp/src/components/tabContentComponents/galleryComponents/openSeadragonViewer.vue diff --git a/webapp/src/components/tabContentComponents/scanListComponents/scanViewer.vue b/webapp/src/components/tabContentComponents/galleryComponents/scanViewer.vue similarity index 100% rename from webapp/src/components/tabContentComponents/scanListComponents/scanViewer.vue rename to webapp/src/components/tabContentComponents/galleryComponents/scanViewer.vue diff --git a/webapp/src/components/tabContentComponents/scanListContent.vue b/webapp/src/components/tabContentComponents/galleryContent.vue similarity index 69% rename from webapp/src/components/tabContentComponents/scanListContent.vue rename to webapp/src/components/tabContentComponents/galleryContent.vue index b8b85319..0b3313cf 100644 --- a/webapp/src/components/tabContentComponents/scanListContent.vue +++ b/webapp/src/components/tabContentComponents/galleryContent.vue @@ -5,7 +5,7 @@
-
+ @@ -47,22 +47,21 @@
@@ -73,8 +72,8 @@ import axios from "axios"; import PaginateLinks from "@/components/genericComponents/paginateLinks.vue"; import actionButton from "../labThingsComponents/actionButton.vue"; -import scanCard from "./scanListComponents/scanCard.vue"; -import ScanViewerModal from "./scanListComponents/scanViewer.vue"; +import galleryCard from "./galleryComponents/galleryCard.vue"; +import ScanViewerModal from "./galleryComponents/scanViewer.vue"; import { eventBus } from "../../eventBus.js"; import { useIntersectionObserver } from "@vueuse/core"; import { useSettingsStore } from "@/stores/settings.js"; @@ -83,10 +82,10 @@ import { watch } from "vue"; // Export main app export default { - name: "ScanListContent", + name: "GalleryContent", components: { actionButton, - scanCard, + galleryCard, ScanViewerModal, PaginateLinks, }, @@ -95,7 +94,7 @@ export default { data: function () { return { - scans: [], + all_items: [], selectedScan: null, osdViewer: null, currentPage: 1, @@ -110,8 +109,8 @@ export default { // The actual property does not exist. So allowUndefined=true return this.thingPropertyUrl("smart_scan", "scans", true); }, - scansEmpty() { - return this.scans.length == 0; + noItems() { + return !this.all_items || this.all_items?.length === 0; }, selectedScanDZI() { if (this.selectedScan && this.selectedScan.dzi != "") { @@ -120,23 +119,24 @@ export default { return null; } }, - totalPages() { - return Math.ceil(this.scans.length / this.itemsPerPage); + // name changed as paginateLinks has the prop totalPages + numberOfPages() { + return Math.ceil((this.all_items?.length || 0) / this.itemsPerPage); }, - paginatedScans() { + paginatedItems() { const start = (this.currentPage - 1) * this.itemsPerPage; - return this.scans.slice(start, start + this.itemsPerPage); + return (this.all_items || []).slice(start, start + this.itemsPerPage); }, }, async mounted() { const store = useSettingsStore(); const { ready } = storeToRefs(store); - watch(ready, (isReady) => { + this.unwatchStoreFunction = watch(ready, (isReady) => { if (isReady) { - this.updateScans(); + this.refreshGallery(); } else { - this.scans = []; + this.all_items = []; } }); useIntersectionObserver( @@ -149,51 +149,52 @@ export default { }, ); // Update on mount (does nothing if not connected) - await this.updateScans(); + await this.refreshGallery(); // A global signal listener to perform a gallery refresh - eventBus.on("globalUpdateScans", () => { - this.updateScans(); - }); - eventBus.on("modalClosed", () => { - // Handle the modal closed event here - this.updateScans(); - }); + eventBus.on("globalRefreshGallery", this.refreshGallery); + // Handle the modal closed event here + eventBus.on("modalClosed", this.refreshGallery); }, beforeUnmount() { // Remove global signal listener to perform a gallery refresh - eventBus.off("globalUpdateScans", this.updateScans); + eventBus.off("globalRefreshGallery", this.refreshGallery); // Then we call that function here to unwatch if (this.unwatchStoreFunction) { this.unwatchStoreFunction(); this.unwatchStoreFunction = null; } - eventBus.off("modalClosed", this.updateScans); // Clean up event listener + eventBus.off("modalClosed", this.refreshGallery); // Clean up event listener }, methods: { visibilityChanged(isVisible) { if (isVisible) { - this.updateScans(); + this.refreshGallery(); } }, - async updateScans() { + async refreshGallery() { try { - let scans = await this.readThingProperty("gallery", "list_data"); - if (!scans | (scans.length == 0)) { - this.scans = scans; + let all_items = await this.readThingProperty("gallery", "list_data"); + // if all_items is "falsey" or the number of items in all_items is zero then + // all_items is equal to empty list. + // stop refresh gallery as all_items is empty list. + if (!all_items || all_items?.length === 0) { + this.all_items = []; + return; } - scans.forEach((scan) => { - scan.can_stitch = !scan.stitch_available && scan.number_of_images > 3; + all_items.forEach((item) => { + item.can_stitch = !item.stitch_available && item.number_of_images > 3; }); - scans.sort((a, b) => { + all_items.sort((a, b) => { return b.created - a.created; }); - this.scans = scans; + this.all_items = all_items; + console.debug("Gallery size: %s", this.all_items.length); } catch (err) { - console.error("Failed to refresh scans"); + console.error("Failed to refresh gallery items."); console.error(err); - this.scans = []; + this.all_items = []; } }, async deleteAllScans() { @@ -203,7 +204,7 @@ export default { "This is irreversible!", ); await axios.delete(`${this.scansUri}`); - await this.updateScans(); + await this.refreshGallery(); this.modalNotify("Deleted all scans."); } catch (e) { // if the confirmation was cancelled, it's rejected with null error @@ -240,7 +241,7 @@ export default { margin-bottom: 30px; } -.scan-list-button { +.gallery-button { margin-top: 5px; margin-bottom: 2px; }