Show image thumbnails in layout views - 4884 (#5099)

* Only show thumbnails if image view is > 400px high

Co-authored-by: Andrew Henry <akhenry@gmail.com>
Co-authored-by: Charles Hacskaylo <charlesh88@gmail.com>
This commit is contained in:
Michael Rogers 2022-04-22 18:14:59 -05:00 committed by GitHub
parent a6553ba010
commit 1ed253cb07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 17 deletions

View File

@ -163,10 +163,13 @@
</div> </div>
</div> </div>
<div <div
v-if="displayThumbnails"
class="c-imagery__thumbs-wrapper" class="c-imagery__thumbs-wrapper"
:class="[ :class="[
{ 'is-paused': isPaused && !isFixed }, { 'is-paused': isPaused && !isFixed },
{ 'is-autoscroll-off': !resizingWindow && !autoScroll && !isPaused } { 'is-autoscroll-off': !resizingWindow && !autoScroll && !isPaused },
{ 'is-small-thumbs': displayThumbnailsSmall },
{ 'hide': !displayThumbnails }
]" ]"
> >
<div <div
@ -179,6 +182,7 @@
:key="image.url + image.time" :key="image.url + image.time"
class="c-imagery__thumb c-thumb" class="c-imagery__thumb c-thumb"
:class="{ selected: focusedImageIndex === index && isPaused }" :class="{ selected: focusedImageIndex === index && isPaused }"
:title="image.formattedTime"
@click="thumbnailClicked(index)" @click="thumbnailClicked(index)"
> >
<a <a
@ -232,6 +236,8 @@ const ARROW_LEFT = 37;
const SCROLL_LATENCY = 250; const SCROLL_LATENCY = 250;
const ZOOM_SCALE_DEFAULT = 1; const ZOOM_SCALE_DEFAULT = 1;
const SHOW_THUMBS_THRESHOLD_HEIGHT = 200;
const SHOW_THUMBS_FULLSIZE_THRESHOLD_HEIGHT = 600;
export default { export default {
components: { components: {
@ -272,6 +278,7 @@ export default {
imageContainerHeight: undefined, imageContainerHeight: undefined,
sizedImageWidth: 0, sizedImageWidth: 0,
sizedImageHeight: 0, sizedImageHeight: 0,
viewHeight: 0,
lockCompass: true, lockCompass: true,
resizingWindow: false, resizingWindow: false,
timeContext: undefined, timeContext: undefined,
@ -290,7 +297,8 @@ export default {
imageTranslateY: 0, imageTranslateY: 0,
pan: undefined, pan: undefined,
animateZoom: true, animateZoom: true,
imagePanned: false imagePanned: false,
forceShowThumbnails: false
}; };
}, },
computed: { computed: {
@ -306,6 +314,15 @@ export default {
return compassRoseSizingClasses; return compassRoseSizingClasses;
}, },
displayThumbnails() {
return (
this.forceShowThumbnails
|| this.viewHeight >= SHOW_THUMBS_THRESHOLD_HEIGHT
);
},
displayThumbnailsSmall() {
return this.viewHeight > SHOW_THUMBS_THRESHOLD_HEIGHT && this.viewHeight <= SHOW_THUMBS_FULLSIZE_THRESHOLD_HEIGHT;
},
time() { time() {
return this.formatTime(this.focusedImage); return this.formatTime(this.focusedImage);
}, },
@ -583,6 +600,9 @@ export default {
}, },
methods: { methods: {
calculateViewHeight() {
this.viewHeight = this.$el.clientHeight;
},
setTimeContext() { setTimeContext() {
this.stopFollowingTimeContext(); this.stopFollowingTimeContext();
this.timeContext = this.openmct.time.getContextForView(this.objectPath); this.timeContext = this.openmct.time.getContextForView(this.objectPath);
@ -956,6 +976,7 @@ export default {
} }
this.setSizedImageDimensions(); this.setSizedImageDimensions();
this.calculateViewHeight();
}, },
setSizedImageDimensions() { setSizedImageDimensions() {
this.focusedImageNaturalAspectRatio = this.$refs.focusedImage.naturalWidth / this.$refs.focusedImage.naturalHeight; this.focusedImageNaturalAspectRatio = this.$refs.focusedImage.naturalWidth / this.$refs.focusedImage.naturalHeight;
@ -984,6 +1005,8 @@ export default {
this.scrollToRight('reset'); this.scrollToRight('reset');
} }
this.calculateViewHeight();
this.$nextTick(() => { this.$nextTick(() => {
this.resizingWindow = false; this.resizingWindow = false;
}); });

View File

@ -161,17 +161,11 @@
flex: 0 1 auto; flex: 0 1 auto;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
height: 135px; height: 145px;
overflow-x: auto; overflow-x: auto;
overflow-y: hidden; overflow-y: hidden;
margin-bottom: 1px; margin-bottom: 1px;
padding-bottom: $interiorMarginSm; padding-bottom: $interiorMarginSm;
.c-thumb:last-child {
// Hilite the lastest thumb
background: $colorBodyFg;
color: $colorBodyBg;
}
} }
&__auto-scroll-resume-button { &__auto-scroll-resume-button {
@ -184,10 +178,12 @@
/*************************************** THUMBS */ /*************************************** THUMBS */
.c-thumb { .c-thumb {
$w: $imageThumbsD;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 4px; padding: 4px;
width: $imageThumbsD; min-width: $w;
width: $w;
&:hover { &:hover {
background: $colorThumbHoverBg; background: $colorThumbHoverBg;
@ -209,11 +205,19 @@
} }
} }
.l-layout, .is-small-thumbs {
.c-fl {
.c-imagery__thumbs-scroll-area { .c-imagery__thumbs-scroll-area {
// When Imagery is in a layout, hide the thumbs area height: 60px; // Allow room for scrollbar
display: none; }
.c-thumb {
$w: $imageThumbsD / 2;
min-width: $w;
width: $w;
&__timestamp {
display: none;
}
} }
} }

View File

@ -344,6 +344,8 @@ describe("The Imagery View Layouts", () => {
); );
openmct.install(clearDataPlugin); openmct.install(clearDataPlugin);
clearDataAction = openmct.actions.getAction('clear-data-action'); clearDataAction = openmct.actions.getAction('clear-data-action');
// force show the thumbnails
imageryView._getInstance().$children[0].forceShowThumbnails = true;
return Vue.nextTick(); return Vue.nextTick();
}); });
@ -523,7 +525,10 @@ describe("The Imagery View Layouts", () => {
expect(clearDataAction).toBeDefined(); expect(clearDataAction).toBeDefined();
}); });
it('on clearData action should clear data for object is selected', (done) => { it('on clearData action should clear data for object is selected', async (done) => {
// force show the thumbnails
imageryView._getInstance().$children[0].forceShowThumbnails = true;
await Vue.nextTick();
expect(parent.querySelectorAll('.c-imagery__thumb').length).not.toBe(0); expect(parent.querySelectorAll('.c-imagery__thumb').length).not.toBe(0);
openmct.objectViews.on('clearData', async (_domainObject) => { openmct.objectViews.on('clearData', async (_domainObject) => {
await Vue.nextTick(); await Vue.nextTick();