瀏覽代碼

Add & Enable logged-in user's email in footer with new menu for nav links - Closes #404

Bubka 9 月之前
父節點
當前提交
fd42ad8b3e

+ 1 - 0
config/2fauth.php

@@ -134,6 +134,7 @@ return [
         'sortCaseSensitive' => false,
         'autoCloseTimeout' => 2,
         'AutoSaveQrcodedAccount' => false,
+        'showEmailInFooter' => true,
     ],
 
 ];

+ 8 - 0
resources/js/assets/app.scss

@@ -962,6 +962,14 @@ footer.main .field.is-grouped {
   justify-content: center;
 }
 
+footer.menu {
+  box-shadow: 0px 3px 10px 5px rgba(0,0,0,0.05);
+}
+
+:root[data-theme="dark"] footer.menu {
+  box-shadow: 0px 3px 10px 5px rgba(0,0,0,0.25);
+}
+
 .notification {
   padding: 0.4rem 1.5rem;
 }

+ 44 - 3
resources/js/layouts/Footer.vue

@@ -1,10 +1,12 @@
 <script setup>
     import { useAppSettingsStore } from '@/stores/appSettings'
     import { useUserStore } from '@/stores/user'
+    import { UseColorMode } from '@vueuse/components'
 
     const appSettings = useAppSettingsStore()
     const user = useUserStore()
     const $2fauth = inject('2fauth')
+    const showMenu = ref(false)
 
     const props = defineProps({
         showButtons: true,
@@ -22,9 +24,9 @@
 </script>
 
 <template>
-    <footer class="main">
+    <footer class="main" :class="{ 'menu' : showMenu }">
         <!-- action buttons -->
-        <div class="columns is-gapless" v-if="showButtons">
+        <div class="columns is-gapless" v-if="showButtons && ! showMenu">
             <div class="column has-text-centered">
                 <div class="field is-grouped">
                     <slot></slot>
@@ -33,27 +35,66 @@
         </div>
         <!-- sub-links -->
         <div v-if="internalFooterType == 'doneButton'" class="content has-text-centered">
+            <!-- done link -->
             <button id="lnkExitEdit" class="button is-ghost is-like-text" @click.stop="$emit('doneButtonClicked', true)">{{ $t('commons.done') }}</button>
         </div>
         <div v-else-if="internalFooterType == 'modal'" class="content has-text-centered">
+            <!-- back to home link -->
             <router-link v-if="$route.name != 'accounts'" id="lnkBackToHome" :to="{ name: 'accounts' }" class="has-text-grey">{{ $t('commons.back_to_home') }}</router-link>
             <span v-else>&nbsp;</span>
         </div>
         <div v-else class="content has-text-centered">
-            <div v-if="$route.meta.showAbout === true" class="is-size-6">
+            <div v-if="$route.meta.showAbout === true">
+                <!-- about link -->
                 <router-link id="lnkAbout" :to="{ name: 'about' }" class="has-text-grey">
                     2FAuth – <span class="has-text-weight-bold">v{{ $2fauth.version }}</span>
                 </router-link>
             </div>
+            <!-- email + menu links -->
+            <div v-else-if="user.preferences.showEmailInFooter">
+                <ul v-if="showMenu == true" class="ml-0 mt-1">
+                    <!-- settings link -->
+                    <li class="column">
+                        <router-link id="lnkSettings" :to="{ name: 'settings.options' }">
+                            {{ $t('settings.settings') }}
+                        </router-link>
+                    </li>
+                    <!-- admin link -->
+                    <li v-if="user.isAdmin" class="column">
+                        <router-link id="lnkAdmin" :to="{ name: 'admin.appSetup' }" >
+                            {{ $t('admin.admin_panel') }}<span v-if="appSettings.latestRelease && appSettings.checkForUpdate" class="release-flag"></span>
+                        </router-link>
+                    </li>
+                    <!-- sign-out button -->
+                    <li v-if="!$2fauth.config.proxyAuth || ($2fauth.config.proxyAuth && $2fauth.config.proxyLogoutUrl)" class="column">
+                        <UseColorMode v-slot="{ mode }">
+                            <button id="lnkSignOut" class="button is-text is-like-text" :class="mode == 'dark' ? 'has-text-grey-lighter' : 'has-text-grey-darker'" @click="logout">
+                                {{ $t('auth.sign_out') }}
+                            </button>
+                        </UseColorMode>
+                    </li>
+                </ul>
+                <!-- email link -->
+                <button id="btnEmailMenu" @click="showMenu = !showMenu" class="button is-text is-like-text has-text-grey" style="width: 100%;">
+                    <span class="mx-2 has-ellipsis">{{ user.email }}</span>
+                    <FontAwesomeIcon v-if="!showMenu" :icon="['fas', 'bars']" class="mr-2" />
+                    <!-- <button v-else class="delete ml-3"></button> -->
+                    <FontAwesomeIcon v-else :icon="['fas', 'times']" class="mr-2" />
+                </button>
+            </div>
+            <!-- legacy links -->
             <div v-else>
+                <!-- settings link -->
                 <router-link id="lnkSettings" :to="{ name: 'settings.options' }" class="has-text-grey">
                     {{ $t('settings.settings') }}
                 </router-link>
+                <!-- admin link -->
                 <span v-if="user.isAdmin"> -
                     <router-link id="lnkAdmin" :to="{ name: 'admin.appSetup' }" class="has-text-grey">
                         {{ $t('admin.admin') }}<span v-if="appSettings.latestRelease && appSettings.checkForUpdate" class="release-flag"></span>
                     </router-link>
                 </span>
+                <!-- sign-out button -->
                 <span v-if="!$2fauth.config.proxyAuth || ($2fauth.config.proxyAuth && $2fauth.config.proxyLogoutUrl)">
                     - <button id="lnkSignOut" class="button is-text is-like-text has-text-grey" @click="logout">{{ $t('auth.sign_out') }}</button>
                 </span>

+ 2 - 0
resources/js/views/settings/Options.vue

@@ -147,6 +147,8 @@
                         <FormCheckbox v-model="user.preferences.clearSearchOnCopy" @update:model-value="val => savePreference('clearSearchOnCopy', val)" fieldName="clearSearchOnCopy" label="settings.forms.clear_search_on_copy.label" help="settings.forms.clear_search_on_copy.help" />
                         <!-- sort case sensitive -->
                         <FormCheckbox v-model="user.preferences.sortCaseSensitive" @update:model-value="val => savePreference('sortCaseSensitive', val)" fieldName="sortCaseSensitive" label="settings.forms.sort_case_sensitive.label" help="settings.forms.sort_case_sensitive.help" />
+                        <!-- show email in footer -->
+                        <FormCheckbox v-model="user.preferences.showEmailInFooter" @update:model-value="val => savePreference('showEmailInFooter', val)" fieldName="showEmailInFooter" label="settings.forms.show_email_in_footer.label" help="settings.forms.show_email_in_footer.help" />
                         
                         <h4 class="title is-4 pt-4 has-text-grey-light">{{ $t('groups.groups') }}</h4>
                         <!-- default group -->

+ 1 - 0
resources/lang/en/admin.php

@@ -14,6 +14,7 @@ return [
     */
 
     'admin' => 'Admin',
+    'admin_panel' => 'Admin panel',
     'app_setup' => 'App setup',
     'auth' => 'Auth',
     'registrations' => 'Registrations',

+ 5 - 1
resources/lang/en/settings.php

@@ -114,7 +114,7 @@ return [
         'automatic' => 'Auto',
         'show_accounts_icons' => [
             'label' => 'Show icons',
-            'help' => 'Show icons accounts in the main view'
+            'help' => 'Show account icons in the main view'
         ],
         'get_official_icons' => [
             'label' => 'Get official icons',
@@ -160,6 +160,10 @@ return [
             'label' => 'On failed login',
             'help' => 'Get an email each time an attempt to connect to your 2FAuth account fails'
         ],
+        'show_email_in_footer' => [
+            'label' => 'Show email in footer',
+            'help' => 'Display the logged-in user\'s email in the footer instead of direct navigation links. The links are then available in a menu behind a click/tap on the email address.'
+        ],
         'otp_generation_on_request' => 'After a click/tap',
         'otp_generation_on_request_legend' => 'Alone, in its own view',
         'otp_generation_on_request_title' => 'Click an account to get a password in a dedicated view',