This repository has been archived on 2024-02-08. You can view files and clone it, but cannot push or open issues or pull requests.
frontend/src/components/home/TheNavigation.vue

288 lines
6.2 KiB
Vue
Raw Normal View History

<template>
2024-02-07 11:18:19 +00:00
<header
:class="{ 'has-background': background, 'menu-active': menuActive }"
aria-label="main navigation"
class="navbar d-print-none"
>
<router-link
:to="{ name: 'home' }"
class="logo-link"
>
<Logo
width="164"
height="48"
/>
</router-link>
2023-01-24 20:55:09 +00:00
<MenuButton class="menu-button" />
2023-01-24 20:55:09 +00:00
2024-02-07 11:18:19 +00:00
<div
v-if="currentProject?.id"
class="project-title-wrapper"
>
<h1 class="project-title">
{{ currentProject.title === '' ? $t('misc.loading') : getProjectTitle(currentProject) }}
</h1>
2024-02-07 11:18:19 +00:00
<BaseButton
:to="{ name: 'project.info', params: { projectId: currentProject.id } }"
class="project-title-button"
>
<icon icon="circle-info" />
2023-01-24 20:55:09 +00:00
</BaseButton>
2024-02-07 11:18:19 +00:00
<ProjectSettingsDropdown
v-if="canWriteCurrentProject && currentProject.id !== -1"
class="project-title-dropdown"
:project="currentProject"
>
<template #trigger="{ toggleOpen }">
2024-02-07 11:18:19 +00:00
<BaseButton
class="project-title-button"
@click="toggleOpen"
>
<icon
icon="ellipsis-h"
class="icon"
/>
2023-01-24 20:55:09 +00:00
</BaseButton>
</template>
2024-02-07 11:18:19 +00:00
</ProjectSettingsDropdown>
</div>
<div class="navbar-end">
2024-02-07 11:18:19 +00:00
<OpenQuickActions />
2023-01-24 20:55:09 +00:00
<Notifications />
2024-02-07 11:18:19 +00:00
<Dropdown>
<template #trigger="{ toggleOpen, open }">
2024-02-07 11:18:19 +00:00
<BaseButton
class="username-dropdown-trigger"
variant="secondary"
:shadow="false"
@click="toggleOpen"
>
<img
:src="authStore.avatarUrl"
alt=""
class="avatar"
width="40"
height="40"
>
2023-01-24 20:55:09 +00:00
<span class="username">{{ authStore.userDisplayName }}</span>
2024-02-07 11:18:19 +00:00
<span
class="icon is-small"
:style="{
transform: open ? 'rotate(180deg)' : 'rotate(0)',
}"
>
<icon icon="chevron-down" />
2023-01-24 20:55:09 +00:00
</span>
</BaseButton>
</template>
2024-02-07 11:18:19 +00:00
<DropdownItem :to="{ name: 'user.settings' }">
2023-01-24 20:55:09 +00:00
{{ $t('user.settings.title') }}
2024-02-07 11:18:19 +00:00
</DropdownItem>
<DropdownItem
v-if="imprintUrl"
:href="imprintUrl"
>
2023-01-24 20:55:09 +00:00
{{ $t('navigation.imprint') }}
2024-02-07 11:18:19 +00:00
</DropdownItem>
<DropdownItem
v-if="privacyPolicyUrl"
:href="privacyPolicyUrl"
>
2023-01-24 20:55:09 +00:00
{{ $t('navigation.privacy') }}
2024-02-07 11:18:19 +00:00
</DropdownItem>
<DropdownItem @click="baseStore.setKeyboardShortcutsActive(true)">
2023-01-24 20:55:09 +00:00
{{ $t('keyboardShortcuts.title') }}
2024-02-07 11:18:19 +00:00
</DropdownItem>
<DropdownItem :to="{ name: 'about' }">
2023-01-24 20:55:09 +00:00
{{ $t('about.title') }}
2024-02-07 11:18:19 +00:00
</DropdownItem>
<DropdownItem @click="authStore.logout()">
2023-01-24 20:55:09 +00:00
{{ $t('user.auth.logout') }}
2024-02-07 11:18:19 +00:00
</DropdownItem>
</Dropdown>
</div>
</header>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { RIGHTS as Rights } from '@/constants/rights'
import ProjectSettingsDropdown from '@/components/project/project-settings-dropdown.vue'
import Dropdown from '@/components/misc/dropdown.vue'
import DropdownItem from '@/components/misc/dropdown-item.vue'
import Notifications from '@/components/notifications/notifications.vue'
import Logo from '@/components/home/Logo.vue'
import BaseButton from '@/components/base/BaseButton.vue'
import MenuButton from '@/components/home/MenuButton.vue'
import OpenQuickActions from '@/components/misc/OpenQuickActions.vue'
import { getProjectTitle } from '@/helpers/getProjectTitle'
2022-09-24 13:20:40 +00:00
import { useBaseStore } from '@/stores/base'
import { useConfigStore } from '@/stores/config'
import { useAuthStore } from '@/stores/auth'
2022-06-23 01:23:39 +00:00
2022-09-24 13:20:40 +00:00
const baseStore = useBaseStore()
const currentProject = computed(() => baseStore.currentProject)
2022-09-24 13:20:40 +00:00
const background = computed(() => baseStore.background)
const canWriteCurrentProject = computed(() => baseStore.currentProject?.maxRight > Rights.READ)
2022-09-24 13:20:40 +00:00
const menuActive = computed(() => baseStore.menuActive)
2022-09-24 13:20:40 +00:00
const authStore = useAuthStore()
const configStore = useConfigStore()
2022-09-21 00:21:22 +00:00
const imprintUrl = computed(() => configStore.legal.imprintUrl)
const privacyPolicyUrl = computed(() => configStore.legal.privacyPolicyUrl)
</script>
<style lang="scss" scoped>
$user-dropdown-width-mobile: 5rem;
2023-01-24 20:55:09 +00:00
.navbar {
--navbar-button-min-width: 40px;
--navbar-gap-width: 1rem;
--navbar-icon-size: 1.25rem;
2023-01-24 20:55:09 +00:00
position: fixed;
top: 0;
left: 0;
right: 0;
2023-01-24 20:55:09 +00:00
display: flex;
justify-content: space-between;
2023-01-24 20:55:09 +00:00
gap: var(--navbar-gap-width);
2023-01-24 20:55:09 +00:00
background: var(--site-background);
2023-01-24 20:55:09 +00:00
@media screen and (max-width: $tablet) {
padding-right: .5rem;
}
2023-01-24 20:55:09 +00:00
@media screen and (min-width: $tablet) {
padding-left: 2rem;
padding-right: 1rem;
align-items: stretch;
}
2023-01-24 20:55:09 +00:00
&.menu-active {
@media screen and (max-width: $tablet) {
z-index: 0;
}
}
// FIXME: notifications should provide a slot for the icon instead, so that we can style it as we want
:deep() {
.trigger-button {
color: var(--grey-400);
2023-01-24 20:55:09 +00:00
font-size: var(--navbar-icon-size);
}
}
2023-01-24 20:55:09 +00:00
}
2023-01-24 20:55:09 +00:00
.logo-link {
display: none;
2023-01-24 20:55:09 +00:00
@media screen and (min-width: $tablet) {
align-self: stretch;
display: flex;
align-items: center;
2023-01-24 20:55:09 +00:00
margin-right: .5rem;
}
}
2023-01-24 20:55:09 +00:00
.menu-button {
margin-right: auto;
align-self: stretch;
flex: 0 0 auto;
2023-01-24 20:55:09 +00:00
@media screen and (max-width: $tablet) {
margin-left: 1rem;
}
}
.project-title-wrapper {
2023-01-24 20:55:09 +00:00
margin-inline: auto;
display: flex;
align-items: center;
// this makes the truncated text of the project title work
2023-01-24 20:55:09 +00:00
// inside the flexbox parent
min-width: 0;
@media screen and (min-width: $tablet) {
2023-01-24 20:55:09 +00:00
padding-inline: var(--navbar-gap-width);
}
2023-01-24 20:55:09 +00:00
}
.project-title {
2023-01-24 20:55:09 +00:00
font-size: 1rem;
// We need the following for overflowing ellipsis to work
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
2023-01-24 20:55:09 +00:00
@media screen and (min-width: $tablet) {
font-size: 1.75rem;
}
2023-01-24 20:55:09 +00:00
}
.project-title-dropdown {
2023-01-24 20:55:09 +00:00
align-self: stretch;
.project-title-button {
2023-01-24 20:55:09 +00:00
flex-grow: 1;
}
}
.project-title-button {
2023-01-24 20:55:09 +00:00
align-self: stretch;
min-width: var(--navbar-button-min-width);
display: flex;
place-items: center;
justify-content: center;
font-size: var(--navbar-icon-size);
color: var(--grey-400);
2023-01-24 20:55:09 +00:00
}
.navbar-end {
margin-left: auto;
flex: 0 0 auto;
display: flex;
align-items: stretch;
>* {
2023-01-24 20:55:09 +00:00
min-width: var(--navbar-button-min-width);
}
}
.username-dropdown-trigger {
padding-left: 1rem;
display: inline-flex;
align-items: center;
text-transform: uppercase;
font-size: .85rem;
font-weight: 700;
}
.username {
font-family: $vikunja-font;
@media screen and (max-width: $tablet) {
display: none;
}
}
.avatar {
border-radius: 100%;
vertical-align: middle;
height: 40px;
margin-right: .5rem;
}
</style>