Commit 3ba33e92 authored by Natalia Tepluhina's avatar Natalia Tepluhina

Lazy-loading design images with IntersectionObserver

parent 07f96c73
<script> <script>
import { GlLoadingIcon } from '@gitlab/ui'; import { GlLoadingIcon, GlIntersectionObserver } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue'; import Icon from '~/vue_shared/components/icon.vue';
import Timeago from '~/vue_shared/components/time_ago_tooltip.vue'; import Timeago from '~/vue_shared/components/time_ago_tooltip.vue';
import { n__, __ } from '~/locale'; import { n__, __ } from '~/locale';
...@@ -8,6 +8,7 @@ import { DESIGN_ROUTE_NAME } from '../../router/constants'; ...@@ -8,6 +8,7 @@ import { DESIGN_ROUTE_NAME } from '../../router/constants';
export default { export default {
components: { components: {
GlLoadingIcon, GlLoadingIcon,
GlIntersectionObserver,
Icon, Icon,
Timeago, Timeago,
}, },
...@@ -46,6 +47,7 @@ export default { ...@@ -46,6 +47,7 @@ export default {
data() { data() {
return { return {
imageLoading: true, imageLoading: true,
isInView: false,
}; };
}, },
computed: { computed: {
...@@ -77,6 +79,9 @@ export default { ...@@ -77,6 +79,9 @@ export default {
showLoadingSpinner() { showLoadingSpinner() {
return this.imageLoading || this.isUploading; return this.imageLoading || this.isUploading;
}, },
imageLink() {
return this.isInView ? this.image : '';
},
}, },
methods: { methods: {
onImageLoad() { onImageLoad() {
...@@ -103,14 +108,16 @@ export default { ...@@ -103,14 +108,16 @@ export default {
</span> </span>
</div> </div>
<gl-loading-icon v-show="showLoadingSpinner" size="md" /> <gl-loading-icon v-show="showLoadingSpinner" size="md" />
<img <gl-intersection-observer @appear="isInView = true">
v-show="!showLoadingSpinner" <img
:src="image" v-show="!showLoadingSpinner"
:alt="filename" :src="imageLink"
class="block ml-auto mr-auto mw-100 mh-100 design-img" :alt="filename"
data-qa-selector="design_image" class="block mx-auto mw-100 mh-100 design-img"
@load="onImageLoad" data-qa-selector="design_image"
/> @load="onImageLoad"
/>
</gl-intersection-observer>
</div> </div>
<div class="card-footer d-flex w-100"> <div class="card-footer d-flex w-100">
<div class="d-flex flex-column str-truncated-100"> <div class="d-flex flex-column str-truncated-100">
......
---
title: Lazy-loading design images with IntersectionObserver
merge_request: 28555
author:
type: added
...@@ -30,12 +30,16 @@ exports[`Design management list item component with no notes renders item with c ...@@ -30,12 +30,16 @@ exports[`Design management list item component with no notes renders item with c
style="display: none;" style="display: none;"
/> />
<img <gl-intersection-observer-stub
alt="test" options="[object Object]"
class="block ml-auto mr-auto mw-100 mh-100 design-img" >
data-qa-selector="design_image" <img
src="http://via.placeholder.com/300" alt="test"
/> class="block mx-auto mw-100 mh-100 design-img"
data-qa-selector="design_image"
src=""
/>
</gl-intersection-observer-stub>
</div> </div>
<div <div
...@@ -99,12 +103,16 @@ exports[`Design management list item component with no notes renders item with c ...@@ -99,12 +103,16 @@ exports[`Design management list item component with no notes renders item with c
style="display: none;" style="display: none;"
/> />
<img <gl-intersection-observer-stub
alt="test" options="[object Object]"
class="block ml-auto mr-auto mw-100 mh-100 design-img" >
data-qa-selector="design_image" <img
src="http://via.placeholder.com/300" alt="test"
/> class="block mx-auto mw-100 mh-100 design-img"
data-qa-selector="design_image"
src=""
/>
</gl-intersection-observer-stub>
</div> </div>
<div <div
...@@ -168,12 +176,16 @@ exports[`Design management list item component with no notes renders item with c ...@@ -168,12 +176,16 @@ exports[`Design management list item component with no notes renders item with c
style="display: none;" style="display: none;"
/> />
<img <gl-intersection-observer-stub
alt="test" options="[object Object]"
class="block ml-auto mr-auto mw-100 mh-100 design-img" >
data-qa-selector="design_image" <img
src="http://via.placeholder.com/300" alt="test"
/> class="block mx-auto mw-100 mh-100 design-img"
data-qa-selector="design_image"
src=""
/>
</gl-intersection-observer-stub>
</div> </div>
<div <div
...@@ -224,12 +236,16 @@ exports[`Design management list item component with no notes renders item with n ...@@ -224,12 +236,16 @@ exports[`Design management list item component with no notes renders item with n
style="display: none;" style="display: none;"
/> />
<img <gl-intersection-observer-stub
alt="test" options="[object Object]"
class="block ml-auto mr-auto mw-100 mh-100 design-img" >
data-qa-selector="design_image" <img
src="http://via.placeholder.com/300" alt="test"
/> class="block mx-auto mw-100 mh-100 design-img"
data-qa-selector="design_image"
src=""
/>
</gl-intersection-observer-stub>
</div> </div>
<div <div
...@@ -279,13 +295,17 @@ exports[`Design management list item component with no notes renders loading spi ...@@ -279,13 +295,17 @@ exports[`Design management list item component with no notes renders loading spi
size="md" size="md"
/> />
<img <gl-intersection-observer-stub
alt="test" options="[object Object]"
class="block ml-auto mr-auto mw-100 mh-100 design-img" >
data-qa-selector="design_image" <img
src="http://via.placeholder.com/300" alt="test"
style="display: none;" class="block mx-auto mw-100 mh-100 design-img"
/> data-qa-selector="design_image"
src=""
style="display: none;"
/>
</gl-intersection-observer-stub>
</div> </div>
<div <div
...@@ -336,12 +356,16 @@ exports[`Design management list item component with notes renders item with mult ...@@ -336,12 +356,16 @@ exports[`Design management list item component with notes renders item with mult
style="display: none;" style="display: none;"
/> />
<img <gl-intersection-observer-stub
alt="test" options="[object Object]"
class="block ml-auto mr-auto mw-100 mh-100 design-img" >
data-qa-selector="design_image" <img
src="http://via.placeholder.com/300" alt="test"
/> class="block mx-auto mw-100 mh-100 design-img"
data-qa-selector="design_image"
src=""
/>
</gl-intersection-observer-stub>
</div> </div>
<div <div
...@@ -409,12 +433,16 @@ exports[`Design management list item component with notes renders item with sing ...@@ -409,12 +433,16 @@ exports[`Design management list item component with notes renders item with sing
style="display: none;" style="display: none;"
/> />
<img <gl-intersection-observer-stub
alt="test" options="[object Object]"
class="block ml-auto mr-auto mw-100 mh-100 design-img" >
data-qa-selector="design_image" <img
src="http://via.placeholder.com/300" alt="test"
/> class="block mx-auto mw-100 mh-100 design-img"
data-qa-selector="design_image"
src=""
/>
</gl-intersection-observer-stub>
</div> </div>
<div <div
......
import { createLocalVue, shallowMount } from '@vue/test-utils'; import { createLocalVue, shallowMount } from '@vue/test-utils';
import VueRouter from 'vue-router'; import VueRouter from 'vue-router';
import Item from 'ee/design_management/components/list/item.vue'; import Item from 'ee/design_management/components/list/item.vue';
import { GlIntersectionObserver } from '@gitlab/ui';
const localVue = createLocalVue(); const localVue = createLocalVue();
localVue.use(VueRouter); localVue.use(VueRouter);
...@@ -47,6 +48,19 @@ describe('Design management list item component', () => { ...@@ -47,6 +48,19 @@ describe('Design management list item component', () => {
wrapper.destroy(); wrapper.destroy();
}); });
it('renders an image when it appears in view', () => {
createComponent();
const image = wrapper.find('img');
expect(image.attributes('src')).toBe('');
wrapper.find(GlIntersectionObserver).vm.$emit('appear');
return wrapper.vm.$nextTick().then(() => {
expect(image.attributes('src')).toBe('http://via.placeholder.com/300');
});
});
describe('with notes', () => { describe('with notes', () => {
it('renders item with single comment', () => { it('renders item with single comment', () => {
createComponent({ notesCount: 1 }); createComponent({ notesCount: 1 });
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment