From 85c184329df0dfbe89b5abb9976986c9a9b2e86d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicol=C3=B2=20Maria=20Mezzopera?= <nmezzopera@gitlab.com>
Date: Wed, 23 Dec 2020 15:53:46 +0000
Subject: [PATCH] Add skeleton loader to title_area

- source
- tests

https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50181
---
 .../components/list_page/registry_header.vue  | 11 ++++++-
 .../registry/explorer/pages/list.vue          |  1 +
 .../components/registry/title_area.vue        | 32 ++++++++++++++-----
 ...ainer-registry-metadata-during-loading.yml |  5 +++
 .../list_page/registry_header_spec.js         |  7 ++--
 .../registry/explorer/pages/list_spec.js      |  7 ++++
 .../components/registry/title_area_spec.js    | 26 ++++++++++++++-
 7 files changed, 77 insertions(+), 12 deletions(-)
 create mode 100644 changelogs/unreleased/290759-adjust-container-registry-metadata-during-loading.yml

diff --git a/app/assets/javascripts/registry/explorer/components/list_page/registry_header.vue b/app/assets/javascripts/registry/explorer/components/list_page/registry_header.vue
index c2bd01701df1..bad804ad1721 100644
--- a/app/assets/javascripts/registry/explorer/components/list_page/registry_header.vue
+++ b/app/assets/javascripts/registry/explorer/components/list_page/registry_header.vue
@@ -43,6 +43,11 @@ export default {
       required: false,
       default: false,
     },
+    metadataLoading: {
+      type: Boolean,
+      required: false,
+      default: false,
+    },
   },
   loader: {
     repeat: 10,
@@ -92,7 +97,11 @@ export default {
 </script>
 
 <template>
-  <title-area :title="$options.i18n.CONTAINER_REGISTRY_TITLE" :info-messages="infoMessages">
+  <title-area
+    :title="$options.i18n.CONTAINER_REGISTRY_TITLE"
+    :info-messages="infoMessages"
+    :metadata-loading="metadataLoading"
+  >
     <template #right-actions>
       <slot name="commands"></slot>
     </template>
diff --git a/app/assets/javascripts/registry/explorer/pages/list.vue b/app/assets/javascripts/registry/explorer/pages/list.vue
index 3192ba82db85..b443d425bfbf 100644
--- a/app/assets/javascripts/registry/explorer/pages/list.vue
+++ b/app/assets/javascripts/registry/explorer/pages/list.vue
@@ -242,6 +242,7 @@ export default {
 
     <template v-else>
       <registry-header
+        :metadata-loading="isLoading"
         :images-count="containerRepositoriesCount"
         :expiration-policy="config.expirationPolicy"
         :help-page-path="config.helpPagePath"
diff --git a/app/assets/javascripts/vue_shared/components/registry/title_area.vue b/app/assets/javascripts/vue_shared/components/registry/title_area.vue
index 4d47a34c9a35..fb60e1c0b1d1 100644
--- a/app/assets/javascripts/vue_shared/components/registry/title_area.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/title_area.vue
@@ -1,5 +1,5 @@
 <script>
-import { GlAvatar, GlSprintf, GlLink } from '@gitlab/ui';
+import { GlAvatar, GlSprintf, GlLink, GlSkeletonLoader } from '@gitlab/ui';
 
 export default {
   name: 'TitleArea',
@@ -7,6 +7,7 @@ export default {
     GlAvatar,
     GlSprintf,
     GlLink,
+    GlSkeletonLoader,
   },
   props: {
     avatar: {
@@ -24,6 +25,11 @@ export default {
       default: () => [],
       required: false,
     },
+    metadataLoading: {
+      type: Boolean,
+      required: false,
+      default: false,
+    },
   },
   data() {
     return {
@@ -68,13 +74,23 @@ export default {
         </div>
 
         <div class="gl-display-flex gl-flex-wrap gl-align-items-center gl-mt-3">
-          <div
-            v-for="(row, metadataIndex) in metadataSlots"
-            :key="metadataIndex"
-            class="gl-display-flex gl-align-items-center gl-mr-5"
-          >
-            <slot :name="row"></slot>
-          </div>
+          <template v-if="!metadataLoading">
+            <div
+              v-for="(row, metadataIndex) in metadataSlots"
+              :key="metadataIndex"
+              class="gl-display-flex gl-align-items-center gl-mr-5"
+            >
+              <slot :name="row"></slot>
+            </div>
+          </template>
+          <template v-else>
+            <div class="gl-w-full">
+              <gl-skeleton-loader :width="200" :height="16" preserve-aspect-ratio="xMinYMax meet">
+                <circle cx="6" cy="8" r="6" />
+                <rect x="16" y="4" width="200" height="8" rx="4" />
+              </gl-skeleton-loader>
+            </div>
+          </template>
         </div>
       </div>
       <div v-if="$slots['right-actions']" class="gl-mt-3">
diff --git a/changelogs/unreleased/290759-adjust-container-registry-metadata-during-loading.yml b/changelogs/unreleased/290759-adjust-container-registry-metadata-during-loading.yml
new file mode 100644
index 000000000000..0fab286b2e50
--- /dev/null
+++ b/changelogs/unreleased/290759-adjust-container-registry-metadata-during-loading.yml
@@ -0,0 +1,5 @@
+---
+title: Adjust container registry metadata during loading
+merge_request: 50181
+author:
+type: changed
diff --git a/spec/frontend/registry/explorer/components/list_page/registry_header_spec.js b/spec/frontend/registry/explorer/components/list_page/registry_header_spec.js
index 3c997093d46f..58439c185e38 100644
--- a/spec/frontend/registry/explorer/components/list_page/registry_header_spec.js
+++ b/spec/frontend/registry/explorer/components/list_page/registry_header_spec.js
@@ -41,9 +41,12 @@ describe('registry_header', () => {
 
   describe('header', () => {
     it('has a title', () => {
-      mountComponent();
+      mountComponent({ metadataLoading: true });
 
-      expect(findTitleArea().props('title')).toBe(CONTAINER_REGISTRY_TITLE);
+      expect(findTitleArea().props()).toMatchObject({
+        title: CONTAINER_REGISTRY_TITLE,
+        metadataLoading: true,
+      });
     });
 
     it('has a commands slot', () => {
diff --git a/spec/frontend/registry/explorer/pages/list_spec.js b/spec/frontend/registry/explorer/pages/list_spec.js
index 7d32a6670111..071b6e85ab2a 100644
--- a/spec/frontend/registry/explorer/pages/list_spec.js
+++ b/spec/frontend/registry/explorer/pages/list_spec.js
@@ -116,6 +116,7 @@ describe('List Page', () => {
     expect(findRegistryHeader().exists()).toBe(true);
     expect(findRegistryHeader().props()).toMatchObject({
       imagesCount: 2,
+      metadataLoading: false,
     });
   });
 
@@ -170,6 +171,12 @@ describe('List Page', () => {
 
       expect(findCliCommands().exists()).toBe(false);
     });
+
+    it('title has the metadataLoading props set to true', () => {
+      mountComponent();
+
+      expect(findRegistryHeader().props('metadataLoading')).toBe(true);
+    });
   });
 
   describe('list is empty', () => {
diff --git a/spec/frontend/vue_shared/components/registry/title_area_spec.js b/spec/frontend/vue_shared/components/registry/title_area_spec.js
index b743a663f062..cb56acd90d33 100644
--- a/spec/frontend/vue_shared/components/registry/title_area_spec.js
+++ b/spec/frontend/vue_shared/components/registry/title_area_spec.js
@@ -1,4 +1,4 @@
-import { GlAvatar, GlSprintf, GlLink } from '@gitlab/ui';
+import { GlAvatar, GlSprintf, GlLink, GlSkeletonLoader } from '@gitlab/ui';
 import { shallowMount } from '@vue/test-utils';
 import component from '~/vue_shared/components/registry/title_area.vue';
 
@@ -15,6 +15,7 @@ describe('title area', () => {
   const findInfoMessages = () => wrapper.findAll('[data-testid="info-message"]');
   const findDynamicSlot = () => wrapper.find(`[data-testid="${DYNAMIC_SLOT}`);
   const findSlotOrderElements = () => wrapper.findAll('[slot-test]');
+  const findSkeletonLoader = () => wrapper.find(GlSkeletonLoader);
 
   const mountComponent = ({ propsData = { title: 'foo' }, slots } = {}) => {
     wrapper = shallowMount(component, {
@@ -100,6 +101,29 @@ describe('title area', () => {
         expect(findMetadataSlot(name).exists()).toBe(true);
       });
     });
+
+    it('is/are hidden when metadata-loading is true', async () => {
+      mountComponent({ slots: slotMocks, propsData: { title: 'foo', metadataLoading: true } });
+
+      await wrapper.vm.$nextTick();
+      slotNames.forEach(name => {
+        expect(findMetadataSlot(name).exists()).toBe(false);
+      });
+    });
+  });
+
+  describe('metadata skeleton loader', () => {
+    it('is hidden when metadata loading is false', () => {
+      mountComponent();
+
+      expect(findSkeletonLoader().exists()).toBe(false);
+    });
+
+    it('is shown when metadata loading is true', () => {
+      mountComponent({ propsData: { metadataLoading: true } });
+
+      expect(findSkeletonLoader().exists()).toBe(true);
+    });
   });
 
   describe('dynamic slots', () => {
-- 
GitLab