Replace the local VueFooter with 2fauth/ui VueFooter component

This commit is contained in:
Bubka
2025-06-24 14:18:51 +02:00
parent 4a8f251d92
commit 026515aa26
22 changed files with 128 additions and 181 deletions

18
resources/js/app.js vendored
View File

@ -18,6 +18,7 @@ const $2fauth = {
isTestingApp: window.isTestingApp,
langs: window.appLocales,
urls: window.urls,
context: 'webapp',
}
app.provide('2fauth', readonly($2fauth))
@ -41,7 +42,6 @@ app.use(Notifications)
// Global components registration
import ResponsiveWidthWrapper from '@/layouts/ResponsiveWidthWrapper.vue'
import FormWrapper from '@/layouts/FormWrapper.vue'
import Footer from '@/layouts/Footer.vue'
import Kicker from '@/components/Kicker.vue'
import {
@ -57,6 +57,7 @@ import {
} from '@2fauth/formcontrols'
import {
VueFooter,
Modal
} from '@2fauth/ui'
@ -64,7 +65,7 @@ app
.component('FontAwesomeIcon', FontAwesomeIcon)
.component('ResponsiveWidthWrapper', ResponsiveWidthWrapper)
.component('FormWrapper', FormWrapper)
.component('VueFooter', Footer)
.component('VueFooter', VueFooter)
.component('Modal', Modal)
.component('VueButton', VueButton)
.component('NavigationButton', NavigationButton)
@ -92,6 +93,15 @@ app
// App mounting
app.mount('#app')
// Theme
// App inject for footer
// TODO : Try to avoid those global injection
import { useUserStore } from '@/stores/user'
useUserStore().applyUserPrefs()
import { useAppSettingsStore } from '@/stores/appSettings'
const user = useUserStore()
const appSettings = useAppSettingsStore()
user.applyUserPrefs()
app.provide('userStore', user)
app.provide('appSettingsStore', appSettings)

View File

@ -57,12 +57,14 @@
</div>
</div>
</div>
<VueFooter :showButtons="true">
<VueFooter>
<template #default>
<!-- Move to selected group button -->
<p class="control">
<button type="button" class="button is-link is-rounded" @click="moveAccounts">{{ $t('message.move') }}</button>
</p>
<NavigationButton action="cancel" :useLinkTag="false" @canceled="$emit('update:showDestinationGroupSelector', false)" />
</template>
</VueFooter>
</div>
</template>

View File

@ -44,8 +44,10 @@
</div>
</div>
</div>
<VueFooter :showButtons="true">
<VueFooter>
<template #default>
<NavigationButton action="close" :useLinkTag="false" @closed="$emit('update:showGroupSwitch', false)" />
</template>
</VueFooter>
</div>
</template>

View File

@ -1,110 +0,0 @@
<script setup>
import { useAppSettingsStore } from '@/stores/appSettings'
import { useUserStore } from '@/stores/user'
import { UseColorMode } from '@vueuse/components'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const appSettings = useAppSettingsStore()
const user = useUserStore()
const $2fauth = inject('2fauth')
const showMenu = ref(false)
const props = defineProps({
showButtons: true,
internalFooterType: {
type: String,
default: 'navLinks'
}
})
function logout() {
if(confirm(t('message.auth.confirm.logout'))) {
user.logout()
}
}
</script>
<template>
<footer class="main" :class="{ 'menu' : showMenu }">
<!-- action buttons -->
<div class="columns is-gapless" v-if="showButtons && ! showMenu">
<div class="column has-text-centered">
<div class="field is-grouped">
<slot></slot>
</div>
</div>
</div>
<!-- sub-links -->
<div v-if="internalFooterType == 'doneButton'" class="content has-text-centered">
<!-- done link -->
<button type="button" id="lnkExitEdit" class="button is-ghost is-like-text" @click.stop="$emit('doneButtonClicked', true)">{{ $t('message.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('message.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">
<!-- about link -->
<router-link v-if="$route.name != 'about'" id="lnkAbout" :to="{ name: 'about' }" class="has-text-grey">
<span v-if="user.isAuthenticated && $route.meta.watchedByKicker" class="has-text-weight-bold">2FAuth v{{ $2fauth.version }}</span>
<span v-else class="">{{ $t('message.about') }}</span>
</router-link>
<span v-else>&nbsp;</span>
</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('message.settings.settings') }}
</router-link>
</li>
<!-- admin link -->
<li v-if="user.isAdmin" class="column">
<router-link id="lnkAdmin" :to="{ name: 'admin.appSetup' }" >
<span v-if="appSettings.latestRelease && appSettings.checkForUpdate" class="release-flag"></span>
{{ $t('message.admin.admin_panel') }}
</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 type="button" id="lnkSignOut" class="button is-text is-like-text" :class="mode == 'dark' ? 'has-text-grey-lighter' : 'has-text-grey-darker'" @click="logout">
{{ $t('message.auth.sign_out') }}
</button>
</UseColorMode>
</li>
</ul>
<!-- email link -->
<button type="button" id="btnEmailMenu" @click="showMenu = !showMenu" class="button is-text is-like-text has-text-grey" style="width: 100%;">
<span v-if="user.isAdmin && appSettings.latestRelease && appSettings.checkForUpdate" class="release-flag"></span>
<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('message.settings.settings') }}
</router-link>
<!-- admin link -->
<span v-if="user.isAdmin"> -
<router-link id="lnkAdmin" :to="{ name: 'admin.appSetup' }" class="has-text-grey">
{{ $t('message.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 type="button" id="lnkSignOut" class="button is-text is-like-text has-text-grey" @click="logout">{{ $t('message.auth.sign_out') }}</button>
</span>
</div>
</div>
</footer>
</template>

View File

@ -64,8 +64,10 @@
<li>{{ $t('message.logos_by') }}&nbsp;<a href="https://2fa.directory/">2FA Directory</a>&nbsp;<a class="is-size-7" href="https://github.com/2factorauth/twofactorauth/blob/master/LICENSE.md">(MIT License)</a></li>
</ul>
<!-- footer -->
<VueFooter :showButtons="true">
<VueFooter>
<template #default>
<NavigationButton action="back" @goback="router.push({ name: returnTo })" :previous-page-title="$t('title.' + returnTo)" />
</template>
</VueFooter>
</UseColorMode>
</ResponsiveWidthWrapper>

View File

@ -107,8 +107,10 @@
</div>
</div>
<!-- Footer -->
<VueFooter :showButtons="true" >
<VueFooter >
<template #default>
<NavigationButton v-if="!twofaccounts.isEmpty" action="back" @goback="router.push({ name: 'accounts' })" :previous-page-title="$t('title.accounts')" />
</template>
</VueFooter>
</div>
</template>

View File

@ -147,8 +147,10 @@
</div>
</FormWrapper>
</div>
<VueFooter :showButtons="true">
<VueFooter>
<template #default>
<NavigationButton action="close" @closed="router.push({ name: returnTo })" :current-page-title="$t('title.admin.appSetup')" />
</template>
</VueFooter>
</div>
</template>

View File

@ -101,8 +101,10 @@
</form>
</FormWrapper>
</div>
<VueFooter :showButtons="true">
<VueFooter>
<template #default>
<NavigationButton action="close" @closed="router.push({ name: returnTo })" :current-page-title="$t('title.admin.auth')" />
</template>
</VueFooter>
</div>
</template>

View File

@ -173,8 +173,10 @@
</div>
<Spinner :isVisible="isFetching && users.length === 0" />
<!-- footer -->
<VueFooter :showButtons="true">
<VueFooter>
<template #default>
<NavigationButton action="close" @closed="router.push({ name: returnTo })" :current-page-title="$t('title.admin.users')" />
</template>
</VueFooter>
</FormWrapper>
</div>

View File

@ -39,9 +39,11 @@
</div>
<AccessLogViewer :userId="props.userId" :lastOnly="false" :showSearch="true" :period="1" />
<!-- footer -->
<VueFooter :showButtons="true">
<VueFooter>
<template #default>
<NavigationButton action="back" @goback="router.push({ name: 'admin.manageUser', params: { userId: props.userId }})" :previous-page-title="$t('title.admin.manageUser')" />
<NavigationButton action="close" @closed="router.push({ name: 'accounts' })" :current-page-title="$t('title.admin.logs.access')" />
</template>
</VueFooter>
</ResponsiveWidthWrapper>
</template>

View File

@ -327,9 +327,11 @@
</div>
</div>
<!-- footer -->
<VueFooter :showButtons="true">
<VueFooter>
<template #default>
<NavigationButton action="back" @goback="router.push({ name: 'admin.users' })" :previous-page-title="$t('title.admin.users')" />
<NavigationButton action="close" @closed="router.push({ name: 'accounts' })" :current-page-title="$t('title.admin.manageUser')" />
</template>
</VueFooter>
</ResponsiveWidthWrapper>
</UseColorMode>

View File

@ -277,6 +277,5 @@
</div>
</div>
</FormWrapper>
<!-- footer -->
<VueFooter />
</template>

View File

@ -116,7 +116,6 @@
<p>{{ $t('message.auth.forms.already_register') }}&nbsp;<RouterLink id="lnkSignIn" :to="{ name: 'login' }" class="is-link">{{ $t('message.auth.sign_in') }}</RouterLink></p>
</div>
</FormWrapper>
<!-- footer -->
<VueFooter />
</div>
</template>

View File

@ -69,8 +69,10 @@
</span>
</div>
<!-- footer -->
<VueFooter :showButtons="true">
<VueFooter>
<template #default>
<NavigationButton action="close" @closed="router.push({ name: 'accounts' })" :current-page-title="$t('title.groups')" />
</template>
</VueFooter>
</ResponsiveWidthWrapper>
</template>

View File

@ -159,8 +159,10 @@
</form>
</FormWrapper>
</div>
<VueFooter :showButtons="true">
<VueFooter>
<template #default>
<NavigationButton action="close" @closed="router.push({ name: returnTo })" :current-page-title="$t('title.settings.account')" />
</template>
</VueFooter>
</div>
</template>

View File

@ -197,8 +197,10 @@
</div>
<Spinner :isVisible="isFetching && tokens.length === 0" />
<!-- footer -->
<VueFooter :showButtons="true">
<VueFooter>
<template #default>
<NavigationButton action="close" @closed="router.push({ name: returnTo })" :current-page-title="$t('title.settings.oauth.tokens')" />
</template>
</VueFooter>
</FormWrapper>
</div>

View File

@ -262,8 +262,10 @@
</form>
</FormWrapper>
</div>
<VueFooter :showButtons="true">
<VueFooter>
<template #default>
<NavigationButton action="close" @closed="router.push({ name: returnTo })" :current-page-title="$t('title.settings.options')" />
</template>
</VueFooter>
</div>
</template>

View File

@ -180,8 +180,10 @@
/>
</form>
<!-- footer -->
<VueFooter :showButtons="true">
<VueFooter>
<template #default>
<NavigationButton action="close" @closed="router.push({ name: returnTo })" :current-page-title="$t('title.settings.webauthn.devices')" />
</template>
</VueFooter>
</FormWrapper>
</div>

View File

@ -486,7 +486,8 @@
</div>
</span>
</div>
<VueFooter :showButtons="true" :internalFooterType="bus.inManagementMode && !showDestinationGroupSelector ? 'doneButton' : 'navLinks'" @done-button-clicked="exitManagementMode">
<VueFooter v-if="bus.inManagementMode && !showDestinationGroupSelector">
<template #default>
<ActionButtons
v-model:inManagementMode="bus.inManagementMode"
:areDisabled="twofaccounts.hasNoneSelected"
@ -494,6 +495,15 @@
@delete-button-clicked="deleteAccounts"
@export-button-clicked="showExportFormatSelector = true">
</ActionButtons>
</template>
<template #subpart>
<button type="button" id="lnkExitEdit" class="button is-ghost is-like-text" @click.stop="exitManagementMode">{{ $t('message.done') }}</button>
</template>
</VueFooter>
<VueFooter v-else>
<template #default>
<ActionButtons v-model:inManagementMode="bus.inManagementMode" />
</template>
</VueFooter>
</div>
</div>

View File

@ -596,7 +596,8 @@
<FormProtectedField v-if="form.otp_type === 'hotp'" pattern="[0-9]{1,4}" :enableProtection="isEditMode" :isExpanded="false" v-model="form.counter" fieldName="counter" :errorMessage="form.errors.get('counter')" label="message.twofaccounts.forms.counter.label" :placeholder="$t('message.twofaccounts.forms.counter.placeholder')" :help="isEditMode ? 'message.twofaccounts.forms.counter.help_lock' : 'message.twofaccounts.forms.counter.help'" />
</div>
</div>
<VueFooter :showButtons="true">
<VueFooter>
<template #default>
<p class="control">
<VueButton nativeType="submit" :id="isEditMode ? 'btnUpdate' : 'btnCreate'" :isLoading="form.isBusy" class="is-rounded" >{{ isEditMode ? $t('message.save') : $t('message.create') }}</VueButton>
</p>
@ -604,6 +605,7 @@
<button id="btnPreview" type="button" class="button is-success is-rounded" @click="previewOTP">{{ $t('message.twofaccounts.forms.test') }}</button>
</p>
<NavigationButton action="cancel" :useLinkTag="false" @canceled="cancelCreation" />
</template>
</VueFooter>
</form>
<!-- modal -->

View File

@ -450,7 +450,8 @@
</div>
</div>
<!-- footer -->
<VueFooter :showButtons="true">
<VueFooter>
<template #default>
<!-- Import all button -->
<p class="control" v-if="importableCount > 0">
<button type="button" class="button is-link is-rounded is-focus" @click="createAccounts">
@ -462,6 +463,7 @@
</p>
<NavigationButton v-if="importableCount > 0" action="cancel" @canceled="router.push({ name: 'accounts' })" />
<NavigationButton v-else action="close" @closed="router.push({ name: 'accounts' })" :current-page-title="$t('title.importAccounts')" />
</template>
</VueFooter>
</ResponsiveWidthWrapper>
<!-- modal -->

View File

@ -28,8 +28,15 @@
<Spinner :isVisible="!qrcode" :type="'raw'" class="is-size-1" />
</p>
</div>
<VueFooter :showButtons="true" :internalFooterType="'modal'">
<VueFooter>
<template #default>
<NavigationButton action="close" @closed="router.push({ name: 'accounts' })" :current-page-title="$t('title.showQRcode')" />
</template>
<template #subpart>
<!-- we add a subpart to hide the default slot value -->
<router-link v-if="$route.name != 'accounts'" id="lnkBackToHome" :to="{ name: 'accounts' }" class="has-text-grey">{{ $t('message.back_to_home') }}</router-link>
<span v-else>&nbsp;</span>
</template>
</VueFooter>
</div>
</template>