diff options
Diffstat (limited to 'core/src/views/UserMenu.vue')
-rw-r--r-- | core/src/views/UserMenu.vue | 281 |
1 files changed, 0 insertions, 281 deletions
diff --git a/core/src/views/UserMenu.vue b/core/src/views/UserMenu.vue deleted file mode 100644 index 0c5084842a1..00000000000 --- a/core/src/views/UserMenu.vue +++ /dev/null @@ -1,281 +0,0 @@ -<!-- - - @copyright 2023 Christopher Ng <chrng8@gmail.com> - - - - @author Christopher Ng <chrng8@gmail.com> - - - - @license AGPL-3.0-or-later - - - - This program is free software: you can redistribute it and/or modify - - it under the terms of the GNU Affero General Public License as - - published by the Free Software Foundation, either version 3 of the - - License, or (at your option) any later version. - - - - This program is distributed in the hope that it will be useful, - - but WITHOUT ANY WARRANTY; without even the implied warranty of - - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - - GNU Affero General Public License for more details. - - - - You should have received a copy of the GNU Affero General Public License - - along with this program. If not, see <http://www.gnu.org/licenses/>. - - ---> - -<template> - <NcHeaderMenu id="user-menu" - class="user-menu" - is-nav - :aria-label="t('core', 'Settings menu')" - :description="avatarDescription"> - <template #trigger> - <NcAvatar v-if="!isLoadingUserStatus" - class="user-menu__avatar" - :disable-menu="true" - :disable-tooltip="true" - :user="userId" - :preloaded-user-status="userStatus" /> - </template> - <ul> - <ProfileUserMenuEntry :id="profileEntry.id" - :name="profileEntry.name" - :href="profileEntry.href" - :active="profileEntry.active" /> - <UserMenuEntry v-for="entry in otherEntries" - :id="entry.id" - :key="entry.id" - :name="entry.name" - :href="entry.href" - :active="entry.active" - :icon="entry.icon" /> - </ul> - </NcHeaderMenu> -</template> - -<script> -import axios from '@nextcloud/axios' -import { emit, subscribe } from '@nextcloud/event-bus' -import { loadState } from '@nextcloud/initial-state' -import { generateOcsUrl } from '@nextcloud/router' -import { getCurrentUser } from '@nextcloud/auth' -import { getCapabilities } from '@nextcloud/capabilities' - -import NcAvatar from '@nextcloud/vue/dist/Components/NcAvatar.js' -import NcHeaderMenu from '@nextcloud/vue/dist/Components/NcHeaderMenu.js' - -import { getAllStatusOptions } from '../../../apps/user_status/src/services/statusOptionsService.js' -import ProfileUserMenuEntry from '../components/UserMenu/ProfileUserMenuEntry.vue' -import UserMenuEntry from '../components/UserMenu/UserMenuEntry.vue' - -import logger from '../logger.js' - -/** - * @typedef SettingNavEntry - * @property {string} id - id of the entry, used as HTML ID, for example, "settings" - * @property {string} name - Label of the entry, for example, "Personal Settings" - * @property {string} icon - Icon of the entry, for example, "/apps/settings/img/personal.svg" - * @property {'settings'|'link'|'guest'} type - Type of the entry - * @property {string} href - Link of the entry, for example, "/settings/user" - * @property {boolean} active - Whether the entry is active - * @property {number} order - Order of the entry - * @property {number} unread - Number of unread pf this items - * @property {string} classes - Classes for custom styling - */ - -/** @type {Record<string, SettingNavEntry>} */ -const settingsNavEntries = loadState('core', 'settingsNavEntries', []) -const { profile: profileEntry, ...otherEntries } = settingsNavEntries - -const translateStatus = (status) => { - const statusMap = Object.fromEntries( - getAllStatusOptions() - .map(({ type, label }) => [type, label]), - ) - if (statusMap[status]) { - return statusMap[status] - } - return status -} - -export default { - name: 'UserMenu', - - components: { - NcAvatar, - NcHeaderMenu, - ProfileUserMenuEntry, - UserMenuEntry, - }, - - data() { - return { - profileEntry, - otherEntries, - displayName: getCurrentUser()?.displayName, - userId: getCurrentUser()?.uid, - isLoadingUserStatus: true, - userStatus: { - status: null, - icon: null, - message: null, - }, - } - }, - - computed: { - translatedUserStatus() { - return { - ...this.userStatus, - status: translateStatus(this.userStatus.status), - } - }, - - avatarDescription() { - const description = [ - t('core', 'Avatar of {displayName}', { displayName: this.displayName }), - ...Object.values(this.translatedUserStatus).filter(Boolean), - ].join(' — ') - return description - }, - }, - - async created() { - if (!getCapabilities()?.user_status?.enabled) { - this.isLoadingUserStatus = false - return - } - - const url = generateOcsUrl('/apps/user_status/api/v1/user_status') - try { - const response = await axios.get(url) - const { status, icon, message } = response.data.ocs.data - this.userStatus = { status, icon, message } - } catch (e) { - logger.error('Failed to load user status') - } - this.isLoadingUserStatus = false - }, - - mounted() { - subscribe('user_status:status.updated', this.handleUserStatusUpdated) - emit('core:user-menu:mounted') - }, - - methods: { - handleUserStatusUpdated(state) { - if (this.userId === state.userId) { - this.userStatus = { - status: state.status, - icon: state.icon, - message: state.message, - } - } - }, - }, -} -</script> - -<style lang="scss" scoped> -.user-menu { - margin-right: 12px; - - &:deep { - .header-menu { - &__trigger { - opacity: 1 !important; - &:focus-visible { - .user-menu__avatar { - border: 2px solid var(--color-primary-element); - } - } - } - - &__carret { - display: none !important; - } - - &__content { - width: fit-content !important; - } - } - } - - &__avatar { - &:active, - &:focus, - &:hover { - border: 2px solid var(--color-primary-element-text); - } - } - - ul { - display: flex; - flex-direction: column; - gap: 2px; - - &:deep { - li { - a, - button { - border-radius: 6px; - display: inline-flex; - align-items: center; - height: var(--header-menu-item-height); - color: var(--color-main-text); - padding: 10px 8px; - box-sizing: border-box; - white-space: nowrap; - position: relative; - width: 100%; - - &:hover { - background-color: var(--color-background-hover); - } - - &:focus-visible { - background-color: var(--color-background-hover) !important; - box-shadow: inset 0 0 0 2px var(--color-primary-element) !important; - outline: none !important; - } - - &:active:not(:focus-visible), - &.active:not(:focus-visible) { - background-color: var(--color-primary-element); - color: var(--color-primary-element-text); - - img, - svg { - filter: var(--primary-invert-if-dark); - } - } - - span { - padding-bottom: 0; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - max-width: 210px; - } - - img { - width: 16px; - height: 16px; - margin-right: 10px; - } - - img, - svg { - filter: var(--background-invert-if-dark); - } - } - - // Override global button styles - button { - background-color: transparent; - border: none; - font-weight: normal; - margin: 0; - } - } - } - } -} -</style> |