feat: make profile picture clickable (#1531)

Co-authored-by: Dominik Pschenitschni <mail@celement.de>
Reviewed-on: https://kolaente.dev/vikunja/frontend/pulls/1531
Reviewed-by: konrad <k@knt.li>
Co-authored-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
Co-committed-by: Dominik Pschenitschni <dpschen@noreply.kolaente.de>
This commit is contained in:
Dominik Pschenitschni 2022-02-13 21:57:33 +00:00 committed by konrad
parent 72d6701404
commit eac07d3169
3 changed files with 72 additions and 66 deletions

View file

@ -6,7 +6,7 @@ describe('Log out', () => {
cy.get('.navbar .user .username') cy.get('.navbar .user .username')
.click() .click()
cy.get('.navbar .user .dropdown-menu a.dropdown-item') cy.get('.navbar .user .dropdown-menu .dropdown-item')
.contains('Logout') .contains('Logout')
.click() .click()

View file

@ -1,7 +1,7 @@
<template> <template>
<ready> <ready>
<template v-if="authUser"> <template v-if="authUser">
<top-navigation/> <TheNavigation/>
<content-auth/> <content-auth/>
</template> </template>
<content-link-share v-else-if="authLinkShare"/> <content-link-share v-else-if="authLinkShare"/>
@ -27,7 +27,7 @@ import {success} from '@/message'
import Notification from '@/components/misc/notification.vue' import Notification from '@/components/misc/notification.vue'
import KeyboardShortcuts from './components/misc/keyboard-shortcuts/index.vue' import KeyboardShortcuts from './components/misc/keyboard-shortcuts/index.vue'
import TopNavigation from './components/home/topNavigation.vue' import TheNavigation from '@/components/home/TheNavigation.vue'
import ContentAuth from './components/home/contentAuth.vue' import ContentAuth from './components/home/contentAuth.vue'
import ContentLinkShare from './components/home/contentLinkShare.vue' import ContentLinkShare from './components/home/contentLinkShare.vue'
import NoAuthWrapper from '@/components/misc/no-auth-wrapper.vue' import NoAuthWrapper from '@/components/misc/no-auth-wrapper.vue'

View file

@ -32,12 +32,13 @@
</a> </a>
<notifications/> <notifications/>
<div class="user"> <div class="user">
<img :src="userAvatar" alt="" class="avatar" width="40" height="40"/>
<dropdown class="is-right" ref="usernameDropdown"> <dropdown class="is-right" ref="usernameDropdown">
<template #trigger> <template #trigger>
<x-button <x-button
variant="secondary" variant="secondary"
:shadow="false"> :shadow="false"
>
<img :src="userAvatar" alt="" class="avatar" width="40" height="40"/>
<span class="username">{{ userInfo.name !== '' ? userInfo.name : userInfo.username }}</span> <span class="username">{{ userInfo.name !== '' ? userInfo.name : userInfo.username }}</span>
<span class="icon is-small"> <span class="icon is-small">
<icon icon="chevron-down"/> <icon icon="chevron-down"/>
@ -45,92 +46,96 @@
</x-button> </x-button>
</template> </template>
<router-link :to="{name: 'user.settings'}" class="dropdown-item"> <BaseButton
:to="{name: 'user.settings'}"
class="dropdown-item"
>
{{ $t('user.settings.title') }} {{ $t('user.settings.title') }}
</router-link> </BaseButton>
<a <BaseButton
v-if="imprintUrl"
:href="imprintUrl" :href="imprintUrl"
class="dropdown-item" class="dropdown-item"
target="_blank" >
rel="noreferrer noopener nofollow"
v-if="imprintUrl">
{{ $t('navigation.imprint') }} {{ $t('navigation.imprint') }}
</a> </BaseButton>
<a <BaseButton
v-if="privacyPolicyUrl"
:href="privacyPolicyUrl" :href="privacyPolicyUrl"
class="dropdown-item" class="dropdown-item"
target="_blank" >
rel="noreferrer noopener nofollow"
v-if="privacyPolicyUrl">
{{ $t('navigation.privacy') }} {{ $t('navigation.privacy') }}
</a> </BaseButton>
<a @click="$store.commit('keyboardShortcutsActive', true)" class="dropdown-item"> <BaseButton
@click="$store.commit('keyboardShortcutsActive', true)"
class="dropdown-item"
>
{{ $t('keyboardShortcuts.title') }} {{ $t('keyboardShortcuts.title') }}
</a> </BaseButton>
<router-link :to="{name: 'about'}" class="dropdown-item"> <BaseButton
:to="{name: 'about'}"
class="dropdown-item"
>
{{ $t('about.title') }} {{ $t('about.title') }}
</router-link> </BaseButton>
<a @click="logout()" class="dropdown-item"> <BaseButton
@click="logout()"
class="dropdown-item"
>
{{ $t('user.auth.logout') }} {{ $t('user.auth.logout') }}
</a> </BaseButton>
</dropdown> </dropdown>
</div> </div>
</div> </div>
</header> </header>
</template> </template>
<script> <script setup langs="ts">
import {mapState} from 'vuex' import {ref, computed, onMounted, nextTick} from 'vue'
import {CURRENT_LIST, QUICK_ACTIONS_ACTIVE} from '@/store/mutation-types' import {useStore} from 'vuex'
import {useRouter} from 'vue-router'
import {QUICK_ACTIONS_ACTIVE} from '@/store/mutation-types'
import Rights from '@/models/constants/rights.json' import Rights from '@/models/constants/rights.json'
import Update from '@/components/home/update.vue' import Update from '@/components/home/update.vue'
import ListSettingsDropdown from '@/components/list/list-settings-dropdown.vue' import ListSettingsDropdown from '@/components/list/list-settings-dropdown.vue'
import Dropdown from '@/components/misc/dropdown.vue' import Dropdown from '@/components/misc/dropdown.vue'
import Notifications from '@/components/notifications/notifications.vue' import Notifications from '@/components/notifications/notifications.vue'
import Logo from '@/components/home/Logo.vue' import Logo from '@/components/home/Logo.vue'
import BaseButton from '@/components/base/BaseButton.vue'
import MenuButton from '@/components/home/MenuButton.vue' import MenuButton from '@/components/home/MenuButton.vue'
export default { const store = useStore()
name: 'topNavigation',
components: { const userInfo = computed(() => store.state.auth.info)
Notifications, const userAvatar = computed(() => store.state.auth.avatarUrl)
Dropdown, const currentList = computed(() => store.state.currentList)
ListSettingsDropdown, const background = computed(() => store.state.background)
Update, const imprintUrl = computed(() => store.state.config.legal.imprintUrl)
Logo, const privacyPolicyUrl = computed(() => store.state.config.legal.privacyPolicyUrl)
MenuButton, const canWriteCurrentList = computed(() => store.state.currentList.maxRight > Rights.READ)
},
computed: { const usernameDropdown = ref()
...mapState({ const listTitle = ref()
userInfo: state => state.auth.info, onMounted(async () => {
userAvatar: state => state.auth.avatarUrl, await nextTick()
userAuthenticated: state => state.auth.authenticated, if (typeof usernameDropdown.value === 'undefined' || typeof listTitle.value === 'undefined') {
currentList: CURRENT_LIST,
background: 'background',
imprintUrl: state => state.config.legal.imprintUrl,
privacyPolicyUrl: state => state.config.legal.privacyPolicyUrl,
canWriteCurrentList: state => state.currentList.maxRight > Rights.READ,
}),
},
mounted() {
this.$nextTick(() => {
if (typeof this.$refs.usernameDropdown === 'undefined' || typeof this.$refs.listTitle === 'undefined') {
return return
} }
const usernameWidth = this.$refs.usernameDropdown.$el.clientWidth const usernameWidth = usernameDropdown.value.$el.clientWidth
this.$refs.listTitle.style.setProperty('--nav-username-width', `${usernameWidth}px`) listTitle.value.style.setProperty('--nav-username-width', `${usernameWidth}px`)
}) })
},
methods: { const router = useRouter()
logout() { function logout() {
this.$store.dispatch('auth/logout') store.dispatch('auth/logout')
this.$router.push({name: 'user.login'}) router.push({name: 'user.login'})
}, }
openQuickActions() {
this.$store.commit(QUICK_ACTIONS_ACTIVE, true) function openQuickActions() {
}, store.commit(QUICK_ACTIONS_ACTIVE, true)
},
} }
</script> </script>
@ -246,6 +251,7 @@ $hamburger-menu-icon-width: 28px;
border-radius: 100%; border-radius: 100%;
vertical-align: middle; vertical-align: middle;
height: 40px; height: 40px;
margin-right: var(--button-padding-horizontal);
} }
:deep(.dropdown-trigger .button) { :deep(.dropdown-trigger .button) {