diff --git a/components/app/AppA11y.vue b/components/app/AppA11y.vue new file mode 100644 index 0000000000000000000000000000000000000000..904307ee26895f1d38828c94e7fd1f4613ca3275 --- /dev/null +++ b/components/app/AppA11y.vue @@ -0,0 +1,46 @@ +<template> + <div class="flex items-center text-gray-400"> + <div class="flex items-end"> + <fa + icon="font" + class="text-xs hover:text-hover cursor-pointer" + @click="onChangeSize(documentFontSize - 0.1)" + /> + <fa + icon="font" + class="text-sm px-1 hover:text-hover cursor-pointer" + @click="onChangeSize(1)" + /> + <fa + icon="font" + class="text-base hover:text-hover cursor-pointer" + @click="onChangeSize(documentFontSize + 0.1)" + /> + </div> + + <div class="hover:text-hover mx-3 cursor-pointer" @click="onA11y"> + <fa icon="wheelchair" /> + </div> + </div> +</template> + +<script> +export default { + data() { + return { + documentFontSize: 1, + } + }, + methods: { + onChangeSize(size) { + this.documentFontSize = size < 0.8 ? 0.8 : size > 1.2 ? 1.2 : size + document.documentElement.style.fontSize = this.documentFontSize + 'em' + }, + onA11y() { + console.log('a11y') + }, + }, +} +</script> + +<style lang="scss" scoped></style> diff --git a/components/layout/LayoutHeader.vue b/components/layout/LayoutHeader.vue index a0a62d33a983fc9bef9164e2751f3875747d877e..ae5df3fd575c40fbb8db084133181d72a924c227 100644 --- a/components/layout/LayoutHeader.vue +++ b/components/layout/LayoutHeader.vue @@ -9,7 +9,7 @@ <div class="flex justify-end items-center relative"> <LayoutHeaderMenu /> - <AppDarkMode class="ml-2 mr-4" /> + <AppDarkMode /> <LayoutHeaderMenuAvatar /> </div> diff --git a/components/layout/LayoutHeaderMenu.vue b/components/layout/LayoutHeaderMenu.vue index 7d374e1429ab5ec91b400a89c471698e389b7710..11a0a160259b6b6cbc9db123613a36dbb28229a1 100644 --- a/components/layout/LayoutHeaderMenu.vue +++ b/components/layout/LayoutHeaderMenu.vue @@ -1,10 +1,10 @@ <template> - <div class="flex"> + <div class="flex mr-3"> <template v-for="(item, index) of menu"> <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,13 +20,16 @@ > <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" > Forum - <fa icon="external-link-alt" class="w-3 ml-1 text-gray-500" /> + <fa + icon="external-link-alt" + class="w-3 ml-1.5 text-gray-500 opacity-75" + /> </a> <LayoutHeaderMenuForum /> </t-dropdown> diff --git a/components/layout/LayoutHeaderMenuAvatar.vue b/components/layout/LayoutHeaderMenuAvatar.vue index 74a222e7299787c95891917dfac8aa9a03aa101b..88afd31251616311543f37075d0e1b2875a71be3 100644 --- a/components/layout/LayoutHeaderMenuAvatar.vue +++ b/components/layout/LayoutHeaderMenuAvatar.vue @@ -1,19 +1,260 @@ -<template functional> - <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" +<template> + <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 dark:border-gray-500 border transform translate-y-1', + }" > - <fa icon="bars" class="ml-2 text-gray-500" /> + <div slot="trigger" class="flex items-center ml-5"> + <button + type="button" + aria-label="User menu" + aria-haspopup="true" + class="h-8 w-8 focus:ring-2 focus:outline-none rounded-full" + > + <img v-if="user" :src="user.avatar_url" class="rounded-full" /> + <fa v-else icon="user-circle" class="text-3xl" /> + </button> + <fa icon="caret-down" class="pl-1.5" /> + </div> + + <div class="my-1" style="min-width: 15rem"> + <template v-if="user"> + <div class="px-3 py-2"> + <div>{{ user.name }}</div> + <div class="text-sm text-gray-600 dark:text-gray-400"> + @{{ user.username }} + </div> + </div> + + <hr class="border-t dark:border-gray-500 my-1" /> + + <a class="menu-item" 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="menu-item 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.5" + > + <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> + + <hr class="border-t dark:border-gray-500 my-1" /> - <div class="flex items-center h-10 w-10 pl-3"> - <fa icon="user-circle" class="text-3xl" /> + <a + class="menu-item justify-between" + href="https://git.duniter.org/websites/monnaie-libre-fr" + target="_blank" + > + <div>Dépôt gitlab</div> + <span + v-if="isLoading === true" + class="loading-state h-6 w-6 border-gray-500" + /> + <fa + v-if="isLoading === 'error'" + icon="exclamation-triangle" + class="w-3 ml-1.5 text-gray-500 opacity-75" + /> + </a> + <template v-if="git"> + <div class="flex text-xs"> + <a + class="menu-item whitespace-nowrap" + href="https://git.duniter.org/websites/monnaie-libre-fr/-/issues" + target="_blank" + v-text="`${git.issueStatusCounts.opened} tickets`" + /> + <a + class="menu-item 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="menu-item 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="menu-item 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> + </template> + + <template v-else> + <a + href="/admin/#/" + target="_blank" + class="menu-item group" + @click="fetchLocalStorageChange" + > + <span>Se connecter</span> + <fa + icon="external-link-alt" + class="w-3 ml-1.5 text-gray-500 opacity-75" + /> + </a> + <nuxt-link to="/contribuer" class="menu-item"> + <span>Contribuer</span> + </nuxt-link> + </template> + + <hr class="border-t dark:border-gray-500 my-1" /> + + <div class="flex"> + <nuxt-link to="/aide" class="menu-item"> + <fa icon="info-circle" class="text-gray-400 mr-2" /> + <span>Aide</span> + </nuxt-link> + + <AppA11y class="ml-2" /> + </div> </div> - </button> + </t-dropdown> </template> <script> 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() { + this.fetchCmsUser() + }, + methods: { + fetchCmsUser() { + if (localStorage.getItem('netlify-cms-user')) { + this.user = JSON.parse(localStorage.getItem('netlify-cms-user')) + } + }, + // if User click on "Connect" link, wait for authentification + fetchLocalStorageChange() { + setInterval(() => { + this.fetchCmsUser() + }, 1000) + }, + 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 + }) + .catch(() => { + this.isLoading = 'error' + }) + }, + }, } </script> +<style lang="postcss" scoped> +.menu-item { + @apply flex items-center hover:bg-hover-light hover:text-gray-700 px-3 py-1 text-gray-600 dark:text-gray-200 w-full; +} +</style> diff --git a/nuxt.config.js b/nuxt.config.js index 92c3a443c0737d7472bc1f9a0ca9c9cc88a5435f..a32fe1991ea36ede2ad88d2a5eb8b3df7179ca80 100644 --- a/nuxt.config.js +++ b/nuxt.config.js @@ -88,6 +88,9 @@ export default { 'faAngry', 'faCompressArrowsAlt', 'faExpandArrowsAlt', + 'faFont', + 'faWheelchair', + 'faCaretDown', ], brands: [ 'faCreativeCommonsNcEu',