Loading openflexure_microscope/api/static/src/components/appContent.vue +1 −1 Original line number Diff line number Diff line Loading @@ -360,7 +360,7 @@ export default { enterApp: function() { // Stuff to do once connected and all init modals are finished console.log("Entering main application"); this.currentTab = "view"; //this.currentTab = "view"; } } }; Loading openflexure_microscope/api/static/src/components/tabContentComponents/galleryComponents/captureCard.vue +71 −30 Original line number Diff line number Diff line Loading @@ -4,11 +4,11 @@ :class="{ 'uk-card-secondary': $store.state.globalSettings.darkMode }" > <div class="uk-card-media-top"> <a class="lightbox-link" :href="imgURL" :data-caption="fileName"> <a class="lightbox-link" :href="imgURL" :data-caption="name"> <img class="uk-width-1-1" :data-src="thumbURL" :alt="captureState.metadata.image.id" :alt="id" width="300" height="225" uk-img Loading @@ -22,7 +22,7 @@ uk-grid > <div class="uk-margin-remove-top uk-padding-remove uk-width-expand"> {{ fileName }} {{ name }} </div> <div class="uk-margin-remove-top uk-padding-remove uk-width-auto"> <a href="#" class="uk-icon" @click="delCaptureConfirm()"> Loading @@ -34,7 +34,7 @@ <div class="uk-text-meta uk-margin-remove-top uk-padding-remove uk-width-expand" > <time>{{ captureState.metadata.image.acquisitionDate }}</time> <time>{{ time }}</time> </div> <div class="uk-text-meta uk-margin-remove-top uk-padding-remove uk-width-auto" Loading Loading @@ -75,11 +75,11 @@ }" > <button class="uk-modal-close-default" type="button" uk-close></button> <h2 class="uk-modal-title">{{ fileName }}</h2> <p><b>Path: </b>{{ captureState.path }}</p> <p><b>Time: </b>{{ captureState.metadata.image.acquisitionDate }}</p> <p><b>ID: </b>{{ captureState.metadata.image.id }}</p> <p><b>Format: </b>{{ captureState.metadata.image.format }}</p> <h2 class="uk-modal-title">{{ name }}</h2> <p><b>Path: </b>{{ path }}</p> <p><b>Time: </b>{{ time }}</p> <p><b>ID: </b>{{ id }}</p> <p><b>Format: </b>{{ format }}</p> <hr /> Loading Loading @@ -161,27 +161,54 @@ export default { }, props: { captureState: { id: { type: String, required: true }, name: { type: String, required: true }, time: { type: String, required: true }, path: { type: String, required: true }, format: { type: String, required: true }, links: { type: Object, required: true }, tags: { type: Array, required: false, default: function() { return []; } }, annotations: { type: Object, required: false, default: function() { return {}; } } }, data: function() { return { tags: [], newTag: "", annotations: {}, newAnnotations: {} }; }, computed: { fileName: function() { return this.captureState.name // If this.captureState.filename exists ? this.captureState.name // Use this.captureState.filename : this.captureState.metadata.filename; // Otherwise use old this.captureState.metadata.filename }, tagModalID: function() { return this.makeModalName("tag-modal-"); }, Loading @@ -195,29 +222,41 @@ export default { return "#" + this.metadataModalID; }, thumbURL: function() { return `${this.captureState.links.download.href}?thumbnail=true`; return `${this.links.download.href}?thumbnail=true`; }, imgURL: function() { return this.captureState.links.download.href; return this.links.download.href; }, tagsURL: function() { return this.captureState.links.tags.href; return this.links.tags.href; }, annotationsURL: function() { return this.captureState.links.annotations.href; return this.links.annotations.href; }, captureURL: function() { return this.captureState.links.self.href; return this.links.self.href; } }, created: function() { // Get initial metadata from prop this.tags = this.captureState.metadata.image.tags; this.annotations = this.captureState.metadata.annotations; }, created: function() {}, methods: { getMetadata: function() { // Send metadata request console.log("Loading capture metadata..."); axios .get(this.captureURL) .then(response => { this.$emit("update:tags", response.data.metadata.image.tags); this.$emit( "update:annotations", response.data.metadata.image.annotations ); }) .catch(error => { this.modalError(error); // Let mixin handle error }); }, handleTagSubmit: function(event) { if (this.newTag !== "") { this.newTagRequest(this.newTag); Loading Loading @@ -303,7 +342,8 @@ export default { axios .get(this.tagsURL) .then(response => { this.tags = response.data; // Pass the update tag array to the parent this.$emit("update:tags", response.data); }) .catch(error => { this.modalError(error); // Let mixin handle error Loading @@ -315,7 +355,8 @@ export default { axios .get(this.annotationsURL) .then(response => { this.annotations = response.data; // Pass the update annotation array to the parent this.$emit("update:annotations", response.data); }) .catch(error => { this.modalError(error); // Let mixin handle error Loading @@ -323,7 +364,7 @@ export default { }, makeModalName: function(prefix) { return prefix + this.captureState.metadata.image.id; return prefix + this.id; } } }; Loading openflexure_microscope/api/static/src/components/tabContentComponents/galleryComponents/scanCard.vue +33 −50 Original line number Diff line number Diff line Loading @@ -6,8 +6,8 @@ <a href="#"> <img class="uk-width-1-1" :data-src="scanState.thumbnail" :alt="scanState.metadata.image.id" :data-src="thumbnail" :alt="id" width="300" height="225" uk-img Loading @@ -22,8 +22,8 @@ uk-grid > <div class="uk-margin-remove-top uk-padding-remove uk-width-expand"> <b>{{ scanState.metadata.type || "Dataset" }}: </b> {{ scanState.metadata.image.name }} <b>{{ type }}: </b> {{ name }} </div> <div class="uk-margin-remove-top uk-padding-remove uk-width-auto"> <a href="#" class="uk-icon" @click="delAllConfirm()"> Loading @@ -35,44 +35,19 @@ <div class="uk-text-meta uk-margin-remove-top uk-padding-remove uk-width-expand" > <time>{{ scanState.metadata.image.acquisitionDate }}</time> </div> <div class="uk-text-meta uk-margin-remove-top uk-padding-remove uk-width-auto" > <a :href="metadataModalTarget" uk-toggle>More...</a> <time>{{ time }}</time> </div> </div> <div class="uk-card-footer uk-padding-small"> <span v-for="tag in scanState.metadata.image.tags" v-for="tag in tags" :key="tag" class="uk-label uk-margin-small-right deletable-label" > {{ tag }} </span> </div> <div :id="metadataModalID" uk-modal> <div class="uk-modal-dialog uk-modal-body"> <button class="uk-modal-close-default" type="button" uk-close></button> <h2 class="uk-modal-title">{{ scanState.metadata.image.name }}</h2> <p><b>Time: </b>{{ scanState.metadata.image.acquisitionDate }}</p> <p><b>ID: </b>{{ scanState.metadata.image.id }}</p> <hr /> <div v-for="(value, key) in scanState.metadata.image.annotations" :key="key" > <p> <b>{{ key }}: </b>{{ value }} </p> </div> </div> </div> </div> </template> Loading @@ -84,25 +59,37 @@ export default { name: "ScanCard", props: { scanState: { type: Object, id: { type: String, required: true } }, computed: { tagModalID: function() { return this.makeModalName("tag-modal-"); name: { type: String, required: true }, tagModalTarget: function() { return "#" + this.tagModalID; time: { type: String, required: true }, type: { type: String, required: false, default: "Dataset" }, metadataModalID: function() { return this.makeModalName("metadata-modal-"); thumbnail: { type: String, required: true }, metadataModalTarget: function() { return "#" + this.metadataModalID; tags: { type: Array, required: false, default: function() { return []; } } }, computed: { allURLs: function() { var urls = []; for (var capture of this.scanState.captures) { Loading @@ -114,11 +101,7 @@ export default { methods: { onClick: function() { this.$emit("selectFolder", this.scanState.metadata.image.id); }, makeModalName: function(prefix) { return prefix + this.scanState.metadata.image.id; this.$emit("selectFolder", this.id); }, delAllConfirm: function() { Loading openflexure_microscope/api/static/src/components/tabContentComponents/galleryContent.vue +38 −38 Original line number Diff line number Diff line Loading @@ -91,20 +91,37 @@ <div class="uk-margin-left"> <h3 class="uk-margin-remove uk-margin-left"> <b>SCAN</b> {{ allScans[galleryFolder].metadata.image.name }} {{ allScans[galleryFolder].name }} </h3> </div> </div> <!-- Gallery capture cards --> <div class="gallery-grid"> <div v-for="item in pagedItems" :key="item.metadata.id"> <div v-for="item in pagedItems" :key="item.id"> <scanCard v-if="'isScan' in item" :scan-state="item" :id="item.id" :name="item.name" :time="item.time" :tags="item.tags" :type="item.type" :thumbnail="item.thumbnail" @selectFolder="selectFolder" /> <captureCard v-else :capture-state="item" /> <captureCard v-else :id="item.id" :links="item.links" :name="item.name" :format="item.format" :path="item.path" :time="item.time" :tags="item.tags" :annotations="item.annotations" @update:tags="item.tags = $event" @update:annotations="item.annotations = $event" /> </div> </div> Loading Loading @@ -164,7 +181,7 @@ export default { // Return an array of unique tags across all captures var tags = []; for (var capture of this.captures) { for (var tag of capture.metadata.image.tags) { for (var tag of capture.tags) { if (!tags.includes(tag)) { tags.push(tag); } Loading @@ -178,7 +195,7 @@ export default { var captures = []; for (var capture of this.captures) { // Add to capture list if matched if (!capture.metadata.dataset) { if (!capture.dataset) { captures.push(capture); } } Loading @@ -191,9 +208,7 @@ export default { var scans = {}; for (var capture of this.captures) { var annotations = capture.metadata.image.annotations; var tags = capture.metadata.image.tags; var dataset = capture.metadata.dataset; var dataset = capture.dataset; if (dataset) { var id = dataset["id"]; Loading @@ -201,34 +216,22 @@ export default { // If this scan ID hasn't been seen before if (!(id in scans)) { scans[id] = {}; scans[id].id = id; scans[id].name = dataset.name; scans[id].type = dataset.type; // Use time of first found capture in dataset scans[id].time = capture.time; scans[id].isScan = true; scans[id].captures = []; scans[id].metadata = { image: { name: dataset.name, acquisitionDate: dataset.acquisitionDate, id: dataset.id, tags: [], annotations: {} }, type: dataset.type }; scans[id].tags = []; } // Add the capture object to the scan scans[id].captures.push(capture); // Add missing scan metadata, prioritising first capture for (var key of Object.keys(annotations)) { if (!(key in scans[id].metadata.image.annotations)) { scans[id].metadata.image.annotations[key] = annotations[key]; } } // Append missing tags for (var tag of tags) { if (!scans[id].metadata.image.tags.includes(tag)) { scans[id].metadata.image.tags.push(tag); for (var tag of capture.tags) { if (!scans[id].tags.includes(tag)) { scans[id].tags.push(tag); } } Loading Loading @@ -272,11 +275,11 @@ export default { if ("captures" in item) { for (var capture of item.captures) { // Get the ID of each capture in the set captures[capture.metadata.image.id] = capture; captures[capture.id] = capture; } } else { // If it's a single capture, get the ID of the capture captures[item.metadata.image.id] = item; captures[item.id] = item; } } Loading Loading @@ -360,7 +363,7 @@ export default { var includeCapture = false; // Filter by selected tags var tags = capture.metadata.image.tags; var tags = capture.tags; let checker = (arr, target) => target.every(v => arr.includes(v)); // True if all tags match includeCapture = checker(tags, filterTags); Loading @@ -377,10 +380,8 @@ export default { sortCaptures: function(list) { // Sort a list of captures by metadata time function compare(a, b) { if (a.metadata.image.acquisitionDate < b.metadata.image.acquisitionDate) return -1; if (a.metadata.image.acquisitionDate > b.metadata.image.acquisitionDate) return 1; if (a.time < b.time) return -1; if (a.time > b.time) return 1; return 0; } Loading @@ -397,7 +398,6 @@ export default { }, selectFolder: function(folderID) { console.log(folderID); this.galleryFolder = folderID; } } Loading Loading
openflexure_microscope/api/static/src/components/appContent.vue +1 −1 Original line number Diff line number Diff line Loading @@ -360,7 +360,7 @@ export default { enterApp: function() { // Stuff to do once connected and all init modals are finished console.log("Entering main application"); this.currentTab = "view"; //this.currentTab = "view"; } } }; Loading
openflexure_microscope/api/static/src/components/tabContentComponents/galleryComponents/captureCard.vue +71 −30 Original line number Diff line number Diff line Loading @@ -4,11 +4,11 @@ :class="{ 'uk-card-secondary': $store.state.globalSettings.darkMode }" > <div class="uk-card-media-top"> <a class="lightbox-link" :href="imgURL" :data-caption="fileName"> <a class="lightbox-link" :href="imgURL" :data-caption="name"> <img class="uk-width-1-1" :data-src="thumbURL" :alt="captureState.metadata.image.id" :alt="id" width="300" height="225" uk-img Loading @@ -22,7 +22,7 @@ uk-grid > <div class="uk-margin-remove-top uk-padding-remove uk-width-expand"> {{ fileName }} {{ name }} </div> <div class="uk-margin-remove-top uk-padding-remove uk-width-auto"> <a href="#" class="uk-icon" @click="delCaptureConfirm()"> Loading @@ -34,7 +34,7 @@ <div class="uk-text-meta uk-margin-remove-top uk-padding-remove uk-width-expand" > <time>{{ captureState.metadata.image.acquisitionDate }}</time> <time>{{ time }}</time> </div> <div class="uk-text-meta uk-margin-remove-top uk-padding-remove uk-width-auto" Loading Loading @@ -75,11 +75,11 @@ }" > <button class="uk-modal-close-default" type="button" uk-close></button> <h2 class="uk-modal-title">{{ fileName }}</h2> <p><b>Path: </b>{{ captureState.path }}</p> <p><b>Time: </b>{{ captureState.metadata.image.acquisitionDate }}</p> <p><b>ID: </b>{{ captureState.metadata.image.id }}</p> <p><b>Format: </b>{{ captureState.metadata.image.format }}</p> <h2 class="uk-modal-title">{{ name }}</h2> <p><b>Path: </b>{{ path }}</p> <p><b>Time: </b>{{ time }}</p> <p><b>ID: </b>{{ id }}</p> <p><b>Format: </b>{{ format }}</p> <hr /> Loading Loading @@ -161,27 +161,54 @@ export default { }, props: { captureState: { id: { type: String, required: true }, name: { type: String, required: true }, time: { type: String, required: true }, path: { type: String, required: true }, format: { type: String, required: true }, links: { type: Object, required: true }, tags: { type: Array, required: false, default: function() { return []; } }, annotations: { type: Object, required: false, default: function() { return {}; } } }, data: function() { return { tags: [], newTag: "", annotations: {}, newAnnotations: {} }; }, computed: { fileName: function() { return this.captureState.name // If this.captureState.filename exists ? this.captureState.name // Use this.captureState.filename : this.captureState.metadata.filename; // Otherwise use old this.captureState.metadata.filename }, tagModalID: function() { return this.makeModalName("tag-modal-"); }, Loading @@ -195,29 +222,41 @@ export default { return "#" + this.metadataModalID; }, thumbURL: function() { return `${this.captureState.links.download.href}?thumbnail=true`; return `${this.links.download.href}?thumbnail=true`; }, imgURL: function() { return this.captureState.links.download.href; return this.links.download.href; }, tagsURL: function() { return this.captureState.links.tags.href; return this.links.tags.href; }, annotationsURL: function() { return this.captureState.links.annotations.href; return this.links.annotations.href; }, captureURL: function() { return this.captureState.links.self.href; return this.links.self.href; } }, created: function() { // Get initial metadata from prop this.tags = this.captureState.metadata.image.tags; this.annotations = this.captureState.metadata.annotations; }, created: function() {}, methods: { getMetadata: function() { // Send metadata request console.log("Loading capture metadata..."); axios .get(this.captureURL) .then(response => { this.$emit("update:tags", response.data.metadata.image.tags); this.$emit( "update:annotations", response.data.metadata.image.annotations ); }) .catch(error => { this.modalError(error); // Let mixin handle error }); }, handleTagSubmit: function(event) { if (this.newTag !== "") { this.newTagRequest(this.newTag); Loading Loading @@ -303,7 +342,8 @@ export default { axios .get(this.tagsURL) .then(response => { this.tags = response.data; // Pass the update tag array to the parent this.$emit("update:tags", response.data); }) .catch(error => { this.modalError(error); // Let mixin handle error Loading @@ -315,7 +355,8 @@ export default { axios .get(this.annotationsURL) .then(response => { this.annotations = response.data; // Pass the update annotation array to the parent this.$emit("update:annotations", response.data); }) .catch(error => { this.modalError(error); // Let mixin handle error Loading @@ -323,7 +364,7 @@ export default { }, makeModalName: function(prefix) { return prefix + this.captureState.metadata.image.id; return prefix + this.id; } } }; Loading
openflexure_microscope/api/static/src/components/tabContentComponents/galleryComponents/scanCard.vue +33 −50 Original line number Diff line number Diff line Loading @@ -6,8 +6,8 @@ <a href="#"> <img class="uk-width-1-1" :data-src="scanState.thumbnail" :alt="scanState.metadata.image.id" :data-src="thumbnail" :alt="id" width="300" height="225" uk-img Loading @@ -22,8 +22,8 @@ uk-grid > <div class="uk-margin-remove-top uk-padding-remove uk-width-expand"> <b>{{ scanState.metadata.type || "Dataset" }}: </b> {{ scanState.metadata.image.name }} <b>{{ type }}: </b> {{ name }} </div> <div class="uk-margin-remove-top uk-padding-remove uk-width-auto"> <a href="#" class="uk-icon" @click="delAllConfirm()"> Loading @@ -35,44 +35,19 @@ <div class="uk-text-meta uk-margin-remove-top uk-padding-remove uk-width-expand" > <time>{{ scanState.metadata.image.acquisitionDate }}</time> </div> <div class="uk-text-meta uk-margin-remove-top uk-padding-remove uk-width-auto" > <a :href="metadataModalTarget" uk-toggle>More...</a> <time>{{ time }}</time> </div> </div> <div class="uk-card-footer uk-padding-small"> <span v-for="tag in scanState.metadata.image.tags" v-for="tag in tags" :key="tag" class="uk-label uk-margin-small-right deletable-label" > {{ tag }} </span> </div> <div :id="metadataModalID" uk-modal> <div class="uk-modal-dialog uk-modal-body"> <button class="uk-modal-close-default" type="button" uk-close></button> <h2 class="uk-modal-title">{{ scanState.metadata.image.name }}</h2> <p><b>Time: </b>{{ scanState.metadata.image.acquisitionDate }}</p> <p><b>ID: </b>{{ scanState.metadata.image.id }}</p> <hr /> <div v-for="(value, key) in scanState.metadata.image.annotations" :key="key" > <p> <b>{{ key }}: </b>{{ value }} </p> </div> </div> </div> </div> </template> Loading @@ -84,25 +59,37 @@ export default { name: "ScanCard", props: { scanState: { type: Object, id: { type: String, required: true } }, computed: { tagModalID: function() { return this.makeModalName("tag-modal-"); name: { type: String, required: true }, tagModalTarget: function() { return "#" + this.tagModalID; time: { type: String, required: true }, type: { type: String, required: false, default: "Dataset" }, metadataModalID: function() { return this.makeModalName("metadata-modal-"); thumbnail: { type: String, required: true }, metadataModalTarget: function() { return "#" + this.metadataModalID; tags: { type: Array, required: false, default: function() { return []; } } }, computed: { allURLs: function() { var urls = []; for (var capture of this.scanState.captures) { Loading @@ -114,11 +101,7 @@ export default { methods: { onClick: function() { this.$emit("selectFolder", this.scanState.metadata.image.id); }, makeModalName: function(prefix) { return prefix + this.scanState.metadata.image.id; this.$emit("selectFolder", this.id); }, delAllConfirm: function() { Loading
openflexure_microscope/api/static/src/components/tabContentComponents/galleryContent.vue +38 −38 Original line number Diff line number Diff line Loading @@ -91,20 +91,37 @@ <div class="uk-margin-left"> <h3 class="uk-margin-remove uk-margin-left"> <b>SCAN</b> {{ allScans[galleryFolder].metadata.image.name }} {{ allScans[galleryFolder].name }} </h3> </div> </div> <!-- Gallery capture cards --> <div class="gallery-grid"> <div v-for="item in pagedItems" :key="item.metadata.id"> <div v-for="item in pagedItems" :key="item.id"> <scanCard v-if="'isScan' in item" :scan-state="item" :id="item.id" :name="item.name" :time="item.time" :tags="item.tags" :type="item.type" :thumbnail="item.thumbnail" @selectFolder="selectFolder" /> <captureCard v-else :capture-state="item" /> <captureCard v-else :id="item.id" :links="item.links" :name="item.name" :format="item.format" :path="item.path" :time="item.time" :tags="item.tags" :annotations="item.annotations" @update:tags="item.tags = $event" @update:annotations="item.annotations = $event" /> </div> </div> Loading Loading @@ -164,7 +181,7 @@ export default { // Return an array of unique tags across all captures var tags = []; for (var capture of this.captures) { for (var tag of capture.metadata.image.tags) { for (var tag of capture.tags) { if (!tags.includes(tag)) { tags.push(tag); } Loading @@ -178,7 +195,7 @@ export default { var captures = []; for (var capture of this.captures) { // Add to capture list if matched if (!capture.metadata.dataset) { if (!capture.dataset) { captures.push(capture); } } Loading @@ -191,9 +208,7 @@ export default { var scans = {}; for (var capture of this.captures) { var annotations = capture.metadata.image.annotations; var tags = capture.metadata.image.tags; var dataset = capture.metadata.dataset; var dataset = capture.dataset; if (dataset) { var id = dataset["id"]; Loading @@ -201,34 +216,22 @@ export default { // If this scan ID hasn't been seen before if (!(id in scans)) { scans[id] = {}; scans[id].id = id; scans[id].name = dataset.name; scans[id].type = dataset.type; // Use time of first found capture in dataset scans[id].time = capture.time; scans[id].isScan = true; scans[id].captures = []; scans[id].metadata = { image: { name: dataset.name, acquisitionDate: dataset.acquisitionDate, id: dataset.id, tags: [], annotations: {} }, type: dataset.type }; scans[id].tags = []; } // Add the capture object to the scan scans[id].captures.push(capture); // Add missing scan metadata, prioritising first capture for (var key of Object.keys(annotations)) { if (!(key in scans[id].metadata.image.annotations)) { scans[id].metadata.image.annotations[key] = annotations[key]; } } // Append missing tags for (var tag of tags) { if (!scans[id].metadata.image.tags.includes(tag)) { scans[id].metadata.image.tags.push(tag); for (var tag of capture.tags) { if (!scans[id].tags.includes(tag)) { scans[id].tags.push(tag); } } Loading Loading @@ -272,11 +275,11 @@ export default { if ("captures" in item) { for (var capture of item.captures) { // Get the ID of each capture in the set captures[capture.metadata.image.id] = capture; captures[capture.id] = capture; } } else { // If it's a single capture, get the ID of the capture captures[item.metadata.image.id] = item; captures[item.id] = item; } } Loading Loading @@ -360,7 +363,7 @@ export default { var includeCapture = false; // Filter by selected tags var tags = capture.metadata.image.tags; var tags = capture.tags; let checker = (arr, target) => target.every(v => arr.includes(v)); // True if all tags match includeCapture = checker(tags, filterTags); Loading @@ -377,10 +380,8 @@ export default { sortCaptures: function(list) { // Sort a list of captures by metadata time function compare(a, b) { if (a.metadata.image.acquisitionDate < b.metadata.image.acquisitionDate) return -1; if (a.metadata.image.acquisitionDate > b.metadata.image.acquisitionDate) return 1; if (a.time < b.time) return -1; if (a.time > b.time) return 1; return 0; } Loading @@ -397,7 +398,6 @@ export default { }, selectFolder: function(folderID) { console.log(folderID); this.galleryFolder = folderID; } } Loading