From 1b0455bb6e059be33178719663c0e884563eb601 Mon Sep 17 00:00:00 2001
From: ManUtopiK <emmanuel.salomon@gmail.com>
Date: Wed, 9 Jun 2021 23:36:41 +0200
Subject: [PATCH] Admin menu + gitlab repo info for admins

---
 components/layout/LayoutHeaderMenu.vue       |   4 +-
 components/layout/LayoutHeaderMenuAvatar.vue | 209 ++++++++++++++++++-
 2 files changed, 202 insertions(+), 11 deletions(-)

diff --git a/components/layout/LayoutHeaderMenu.vue b/components/layout/LayoutHeaderMenu.vue
index 7d374e14..1d18b737 100644
--- a/components/layout/LayoutHeaderMenu.vue
+++ b/components/layout/LayoutHeaderMenu.vue
@@ -4,7 +4,7 @@
       <nuxt-link
         v-if="item.url.startsWith('/')"
         :key="index"
-        class="inline-flex items-center relative cursor-pointer whitespace-nowrap py-2 px-3 hover:bg-hover-light dark-hover:bg-hover-dark rounded-full focus:outline-none focus:ring-2 transition-shadow"
+        class="inline-flex items-center relative cursor-pointer whitespace-nowrap py-2 px-3 hover:bg-hover-light dark-hover:bg-hover-dark rounded-full focus:outline-none focus:ring-2"
         :to="item.url"
       >
         {{ item.title }}
@@ -20,7 +20,7 @@
     >
       <a
         slot="trigger"
-        class="inline-flex items-center relative cursor-pointer whitespace-nowrap py-2 px-3 hover:bg-hover-light dark-hover:bg-hover-dark rounded-full focus:outline-none focus:ring-2 transition-shadow"
+        class="inline-flex items-center relative cursor-pointer whitespace-nowrap py-2 px-3 hover:bg-hover-light dark-hover:bg-hover-dark rounded-full focus:outline-none focus:ring-2"
         href="https://forum.monnaie-libre.fr/"
         target="_blank"
         rel="noopener noreferrer"
diff --git a/components/layout/LayoutHeaderMenuAvatar.vue b/components/layout/LayoutHeaderMenuAvatar.vue
index 4b3612a2..4505dffb 100644
--- a/components/layout/LayoutHeaderMenuAvatar.vue
+++ b/components/layout/LayoutHeaderMenuAvatar.vue
@@ -1,16 +1,150 @@
 <template>
-  <button
-    type="button"
-    class="inline-flex items-center relative px-2 dark:border-gray-500 border-2 rounded-full hover:shadow-lg focus:outline-none focus:ring-2 transition-shadow"
-    aria-label="User menu"
+  <t-dropdown
+    toggle-on-hover
+    :hide-on-leave-timeout="0"
+    :show.sync="show"
+    :classes="{
+      dropdown:
+        'absolute right-0 rounded-md shadow-lg bg-white dark:bg-gray-600 border-gray-100 border transform translate-y-1',
+    }"
   >
-    <fa icon="bars" class="ml-2 text-gray-500" />
+    <div
+      slot="trigger"
+      slot-scope="{
+        mousedownHandler,
+        focusHandler,
+        blurHandler,
+        keydownHandler,
+        isShown,
+      }"
+    >
+      <button
+        type="button"
+        class="inline-flex items-center relative px-2 dark:border-gray-500 border-2 rounded-full hover:shadow-lg focus:outline-none focus:ring-2 transition-shadow"
+        :class="{ 'shadow-lg': isShown }"
+        aria-label="User menu"
+        aria-haspopup="true"
+        @mousedown="mousedownHandler"
+        @focus="focusHandler"
+        @blur="blurHandler"
+        @keydown="keydownHandler"
+      >
+        <fa icon="bars" class="ml-2 text-gray-500" />
 
-    <div class="flex items-center h-10 w-10 pl-3">
-      <img v-if="user" :src="user.avatar_url" class="rounded-full" />
-      <fa v-else icon="user-circle" class="text-3xl" />
+        <div class="flex items-center h-10 w-10 pl-3">
+          <img v-if="user" :src="user.avatar_url" class="rounded-full" />
+          <fa v-else icon="user-circle" class="text-3xl" />
+        </div>
+      </button>
     </div>
-  </button>
+
+    <div v-if="user" class="pb-1" style="min-width: 15rem">
+      <div class="p-3 border-b mb-1">
+        <div>{{ user.name }}</div>
+        <div class="text-sm text-gray-600 dark:text-gray-400">
+          @{{ user.username }}
+        </div>
+      </div>
+      <a
+        class="block hover:bg-hover-light hover:text-gray-700 px-3 py-1 text-gray-600 dark:text-gray-200 w-full flex items-center"
+        href="/admin/#/"
+        target="_blank"
+        ><svg
+          xmlns="http://www.w3.org/2000/svg"
+          width="24"
+          height="24"
+          viewBox="0 0 24 24"
+          class="fill-current text-gray-400 mr-1"
+        >
+          <path
+            d="m13.366 3 5.625 5.493L19 19.169C19 20.176 18.156 21 17.125 21H5.865C4.836 21 4 20.176 4 19.17V4.83C4 3.825 4.834 3 5.866 3h7.5zM6.94 12.11a.94.94 0 1 0 0 1.88h9.12a.94.94 0 0 0 0-1.88H6.94zm0 3.89a.94.94 0 1 0 0 1.88h9.12a.94.94 0 1 0 0-1.88H6.94zm5.073-6h5.139l-5.14-5.053V10z"
+          ></path></svg
+        >Contenus
+      </a>
+      <a
+        class="block hover:bg-hover-light hover:text-gray-700 px-3 py-1 text-gray-600 dark:text-gray-200 w-full flex items-center justify-between"
+        href="/admin/#/workflow"
+        target="_blank"
+      >
+        <div class="flex items-center">
+          <svg
+            xmlns="http://www.w3.org/2000/svg"
+            width="24"
+            height="24"
+            viewBox="0 0 24 24"
+            class="fill-current text-gray-400 mr-1"
+          >
+            <path
+              d="M10 4h3a1 1 0 0 1 1 1v9a1 1 0 0 1-1 1h-3a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1zm7 0h3a1 1 0 0 1 1 1v10a1 1 0 0 1-1 1h-3a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1zM3 4h3a1 1 0 0 1 1 1v14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1z"
+            ></path></svg
+          >Flux
+        </div>
+        <div v-if="git">
+          <span
+            class="bg-purple-200 text-purple-800 font-medium py-0.5 px-1 text-sm rounded"
+            v-text="git.draft.count"
+          />
+          <span
+            class="bg-yellow-200 text-yellow-800 font-medium py-0.5 px-1 text-sm rounded"
+            v-text="git.pending_review.count"
+          />
+          <span
+            class="bg-green-200 text-green-800 font-medium py-0.5 px-1 text-sm rounded"
+            v-text="git.pending_publish.count"
+          />
+        </div>
+      </a>
+
+      <div class="border-t my-1" />
+
+      <a
+        class="block hover:bg-hover-light hover:text-gray-700 px-3 py-1 text-gray-600 dark:text-gray-200 w-full flex items-center justify-between"
+        href="https://git.duniter.org/websites/monnaie-libre-fr"
+        target="_blank"
+      >
+        <div>Dépôt gitlab</div>
+        <span v-if="isLoading" class="loading-state h-6 w-6 border-gray-500" />
+      </a>
+      <template v-if="git">
+        <div class="flex text-xs">
+          <a
+            class="block hover:bg-hover-light hover:text-gray-600 px-3 py-1 text-gray-600 dark:text-gray-200 w-full whitespace-nowrap"
+            href="https://git.duniter.org/websites/monnaie-libre-fr/-/issues"
+            target="_blank"
+            v-text="`${git.issueStatusCounts.opened} tickets`"
+          />
+          <a
+            class="block hover:bg-hover-light hover:text-gray-600 px-3 py-1 text-gray-600 dark:text-gray-200 w-full whitespace-nowrap"
+            href="https://git.duniter.org/websites/monnaie-libre-fr/-/merge_requests"
+            target="_blank"
+            v-text="`${git.mergeRequests.count} demandes de fusion`"
+          />
+        </div>
+        <a
+          class="block hover:bg-hover-light hover:text-gray-700 px-3 py-1 text-gray-600 dark:text-gray-200 w-full flex items-center justify-between"
+          :href="`https://git.duniter.org/websites/monnaie-libre-fr/-/issues?scope=all&utf8=%E2%9C%93&state=opened&author_username=${user.username}`"
+          target="_blank"
+        >
+          <div>Mes tickets</div>
+          <div
+            class="bg-gray-200 text-gray-800 font-medium w-5 h-5 text-center text-sm rounded-full"
+            v-text="git.my_issues.count"
+          />
+        </a>
+        <a
+          class="block hover:bg-hover-light hover:text-gray-700 px-3 py-1 text-gray-600 dark:text-gray-200 w-full flex items-center justify-between"
+          :href="`https://git.duniter.org/websites/monnaie-libre-fr/-/merge_requests?scope=all&utf8=%E2%9C%93&state=opened&author_username=${user.username}`"
+          target="_blank"
+        >
+          <div>Mes demandes de fusion</div>
+          <div
+            class="bg-gray-200 text-gray-800 font-medium w-5 h-5 text-center text-sm rounded-full"
+            v-text="git.my_merge_requests.count"
+          />
+        </a>
+      </template>
+    </div>
+  </t-dropdown>
 </template>
 
 <script>
@@ -18,13 +152,70 @@ export default {
   name: 'LayoutHeaderMenuAvatar',
   data() {
     return {
+      show: false,
       user: null,
+      git: null,
+      lastFetch: null,
+      isLoading: false,
     }
   },
+  watch: {
+    show(newVal) {
+      // Debounce fetch under 10s
+      if (newVal && this.user && Date.now() - this.lastFetch > 10000) {
+        // Fetch gitlab data
+        this.fetchGitlab()
+      }
+    },
+  },
   mounted() {
     if (localStorage.getItem('netlify-cms-user')) {
       this.user = JSON.parse(localStorage.getItem('netlify-cms-user'))
     }
   },
+  methods: {
+    fetchGitlab() {
+      this.isLoading = true
+      this.$axios
+        .$post('https://git.duniter.org/api/graphql', {
+          query: `#graphql
+            query projectML($authorUsername: String) {
+              project(fullPath: "websites/monnaie-libre-fr") {
+                lastActivityAt
+                issueStatusCounts {
+                  opened
+                }
+                mergeRequests(state: opened) {
+                  count
+                }
+                my_issues: issues(authorUsername: $authorUsername, state: opened) {
+                  count
+                }
+                my_merge_requests:mergeRequests(authorUsername: $authorUsername, state: opened) {
+                  count
+                }
+                draft: mergeRequests(labels: "netlify-cms/draft", state: opened) {
+                  count
+                }
+                pending_review: mergeRequests(labels: "netlify-cms/pending_review", state: opened) {
+                  count
+                }
+                pending_publish: mergeRequests(labels: "netlify-cms/pending_publish", state: opened) {
+                  count
+                }
+              }
+            }
+          `,
+          variables: {
+            authorUsername: this.user.username,
+          },
+        })
+        .then(({ data }) => {
+          this.git = data.project
+          this.lastFetch = Date.now()
+          this.isLoading = false
+        })
+    },
+  },
 }
 </script>
-- 
GitLab