mirror of
https://github.com/nextcloud/server.git
synced 2026-02-19 02:38:40 -05:00
Port user menu to Vue
Signed-off-by: Christopher Ng <chrng8@gmail.com>
This commit is contained in:
parent
e47d56ac36
commit
c77998209f
21 changed files with 344 additions and 261 deletions
|
|
@ -13,7 +13,7 @@
|
|||
<bugs>https://github.com/nextcloud/server</bugs>
|
||||
<navigations>
|
||||
<navigation>
|
||||
<id>user_status-menuitem</id>
|
||||
<id>user_status-menu-entry</id>
|
||||
<name>User status</name>
|
||||
<order>1</order>
|
||||
<type>settings</type>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
<a v-if="!inline"
|
||||
class="user-status-menu-item__header"
|
||||
:href="profilePageLink"
|
||||
@click="loadProfilePage">
|
||||
@click.exact="loadProfilePage">
|
||||
<div class="user-status-menu-item__header-content">
|
||||
<div class="user-status-menu-item__header-content-displayname">{{ displayName }}</div>
|
||||
<div v-if="!loadingProfilePage" class="user-status-menu-item__header-content-placeholder" />
|
||||
|
|
@ -234,11 +234,6 @@ export default {
|
|||
align-items: flex-start !important;
|
||||
color: var(--color-main-text) !important;
|
||||
|
||||
&:focus-visible {
|
||||
padding: 6px 8px 1px 8px !important;
|
||||
margin: 2px !important;
|
||||
}
|
||||
|
||||
&:not([href]) {
|
||||
height: var(--header-menu-item-height) !important;
|
||||
color: var(--color-text-maxcontrast) !important;
|
||||
|
|
|
|||
|
|
@ -24,10 +24,11 @@
|
|||
|
||||
import Vue from 'vue'
|
||||
import { getRequestToken } from '@nextcloud/auth'
|
||||
import UserStatus from './UserStatus'
|
||||
import store from './store'
|
||||
import NcAvatar from '@nextcloud/vue/dist/Components/NcAvatar'
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
import { subscribe } from '@nextcloud/event-bus'
|
||||
|
||||
import UserStatus from './UserStatus.vue'
|
||||
|
||||
import store from './store/index.js'
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
__webpack_nonce__ = btoa(getRequestToken())
|
||||
|
|
@ -35,31 +36,23 @@ __webpack_nonce__ = btoa(getRequestToken())
|
|||
Vue.prototype.t = t
|
||||
Vue.prototype.$t = t
|
||||
|
||||
const avatarDiv = document.getElementById('avatardiv-menu')
|
||||
const userStatusData = loadState('user_status', 'status')
|
||||
const propsData = {
|
||||
preloadedUserStatus: {
|
||||
message: userStatusData.message,
|
||||
icon: userStatusData.icon,
|
||||
status: userStatusData.status,
|
||||
},
|
||||
user: avatarDiv.dataset.user,
|
||||
displayName: avatarDiv.dataset.displayname,
|
||||
disableMenu: true,
|
||||
disableTooltip: true,
|
||||
const mountPoint = document.getElementById('user_status-menu-entry')
|
||||
|
||||
const mountMenuEntry = () => {
|
||||
const mountPoint = document.getElementById('user_status-menu-entry')
|
||||
// eslint-disable-next-line no-new
|
||||
new Vue({
|
||||
el: mountPoint,
|
||||
render: h => h(UserStatus),
|
||||
store,
|
||||
})
|
||||
}
|
||||
|
||||
const NcAvatarInMenu = Vue.extend(NcAvatar)
|
||||
new NcAvatarInMenu({ propsData }).$mount('#avatardiv-menu')
|
||||
|
||||
// Register settings menu entry
|
||||
export default new Vue({
|
||||
el: 'li[data-id="user_status-menuitem"]',
|
||||
// eslint-disable-next-line vue/match-component-file-name
|
||||
name: 'UserStatusRoot',
|
||||
render: h => h(UserStatus),
|
||||
store,
|
||||
})
|
||||
if (mountPoint) {
|
||||
mountMenuEntry()
|
||||
} else {
|
||||
subscribe('core:user-menu:mounted', mountMenuEntry)
|
||||
}
|
||||
|
||||
// Register dashboard status
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
{"version":3,"sourceRoot":"","sources":["header.scss","variables.scss"],"names":[],"mappings":"AAiBA,mBAEC,yBACA,sBACA,qBACA,6PACC,aAGD,+QACC,YACA,kBACA,2BACA,WACA,WACA,kBACA,2CACA,SACA,UAGD,gLACC,WAIA,kPACC,WAGD,+HACC,SAOH,+DAGC,oBACA,kBACA,MACA,WACA,aACA,OC2Ce,KD1Cf,sBACA,8BAID,WACC,cACA,kBACA,kBACA,wBACA,sBACA,UACA,mBACA,aACA,eACA,gBACA,WAEA,mCACC,UAaD,gCACC,8CACA,sDACA,yCACA,sBACA,aACA,kBACA,gBAfD,gBACA,oCAgBC,UACA,SACA,SACA,gBAEA,kDACC,aAID,sCACC,gCACA,iDACA,YACA,YACA,SACA,QACA,kBACA,oBACA,WAGD,uEAEC,iCAzCF,gBACA,oCA6CC,iDACC,YACA,aACA,sBACA,QAEC,sDACC,kBACA,oBACA,mBACA,OAlDuB,KAmDvB,6BACA,kBACA,sBACA,mBACA,kBACA,WACA,wHAEC,+CAED,0HAEC,4CAED,oEACC,gDACA,aAED,2DACC,qBACA,iBACA,6BACA,mBACA,gBACA,uBACA,gBAED,0EACC,kBACA,0BAED,oHAEC,WACA,kBACA,YACA,WACA,wCAML,cACC,oBACA,yFACA,4BACA,wBACA,2BACA,WACA,kBACA,UACA,QACA,WAEA,gFAGD,kCACC,aACA,mBACA,cAGD,sFAEC,oBACA,mBAGD,0CACC,SACA,mBACA,YAGD,4CACC,yBACA,cAKA,qDAEC,YACA,kBACA,6EACC,aACA,uBACA,mBACA,MClIY,KDmIZ,YACA,eACA,YACA,UACA,aAEA,yFACC,UAGD,yGACC,aASL,0CACC,YAKD,gBACC,gCACA,eACA,iBACA,SACA,UACA,kBACA,gBACA,uBAEA,cAGD,kBACC,gCACA,kBACA,gBACA,eACA,iBACA,gBACA,uBAID,UACC,qBACA,YACA,eACA,cAGA,kBACC,UACA,kBAEA,yEAGC,gCAEA,4OAEC,kBACA,2CACA,YAED,0GACC,2CAED,kIACC,UAKF,6BACC,eACA,YACA,WAEA,iCACC,UACA,eAGD,gEACC,aAIF,qCACC,YACA,WACA,eAGA,oDACC,UAKF,wCACC,YACA,SACA,QACA,kBACA,oBACA,WACA,YACA,cACA,WACA,WACA,kBACA,2CAIF,2BACC,WAKF,cACC,kBACA,gBACA,aACA,WACA,SACA,YACA,aAEA,2BACC,IC/Qc,KDuRf,gDACC,mBACA,eAED,gJAEC,qBACA,YACA","file":"header.css"}
|
||||
{"version":3,"sourceRoot":"","sources":["header.scss","variables.scss"],"names":[],"mappings":"AAiBA,mBAEC,yBACA,sBACA,qBACA,6PACC,aAGD,+QACC,YACA,kBACA,2BACA,WACA,WACA,kBACA,2CACA,SACA,UAGD,gLACC,WAIA,kPACC,WAGD,+HACC,SAOH,+DAGC,oBACA,kBACA,MACA,WACA,aACA,OC2Ce,KD1Cf,sBACA,8BAID,WACC,cACA,kBACA,kBACA,wBACA,sBACA,UACA,mBACA,aACA,eACA,gBACA,WAEA,mCACC,UAaD,gCACC,8CACA,sDACA,yCACA,sBACA,aACA,kBACA,gBAfD,gBACA,oCAgBC,UACA,SACA,SACA,gBAEA,kDACC,aAID,sCACC,gCACA,iDACA,YACA,YACA,SACA,QACA,kBACA,oBACA,WAGD,uEAEC,iCAzCF,gBACA,oCA4CA,cACC,oBACA,yFACA,4BACA,wBACA,2BACA,WACA,kBACA,UACA,QACA,WAEA,gFAGD,kCACC,aACA,mBACA,cAGD,sFAEC,oBACA,mBAGD,0CACC,SACA,mBACA,YAGD,4CACC,yBACA,cAKA,qDAEC,YACA,kBACA,6EACC,aACA,uBACA,mBACA,MC3EY,KD4EZ,YACA,eACA,YACA,UACA,aAEA,yFACC,UAGD,yGACC,aASL,0CACC,YAKD,gBACC,gCACA,eACA,iBACA,SACA,UACA,kBACA,gBACA,uBAEA,cAGD,kBACC,gCACA,kBACA,gBACA,eACA,iBACA,gBACA,uBAID,cACC,kBACA,gBACA,aACA,WACA,SACA,YACA,aAEA,2BACC,ICxIc,KD+If,gDACC,mBACA,eAED,gJAEC,qBACA,YACA","file":"header.css"}
|
||||
|
|
@ -130,61 +130,6 @@
|
|||
-webkit-overflow-scrolling: touch;
|
||||
@include header-menu-height();
|
||||
}
|
||||
|
||||
/* Use by the settings right menu */
|
||||
&.settings-menu > ul {
|
||||
padding: 4px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
li {
|
||||
a {
|
||||
border-radius: 6px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
height: $header-menu-entry-height;
|
||||
color: var(--color-main-text);
|
||||
padding: 10px 12px;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: var(--color-background-hover);
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
background-color: var(--color-primary-light);
|
||||
}
|
||||
&:focus-visible {
|
||||
box-shadow: inset 0 0 0 2px var(--color-primary);
|
||||
outline: none;
|
||||
}
|
||||
span {
|
||||
display: inline-block;
|
||||
padding-bottom: 0;
|
||||
color: var(--color-main-text);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 110px;
|
||||
}
|
||||
.icon-loading-small {
|
||||
margin-right: 10px;
|
||||
background-size: 16px 16px;
|
||||
}
|
||||
img,
|
||||
svg {
|
||||
opacity: .7;
|
||||
margin-right: 10px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
filter: var(--background-invert-if-dark);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.logo {
|
||||
display: inline-flex;
|
||||
|
|
@ -284,86 +229,6 @@
|
|||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
/* USER MENU -----------------------------------------------------------------*/
|
||||
#settings {
|
||||
display: inline-block;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
flex: 0 0 auto;
|
||||
|
||||
/* User menu on the right */
|
||||
#expand {
|
||||
opacity: 1; /* override icon opacity */
|
||||
margin-right: 12px;
|
||||
|
||||
&:hover,
|
||||
&:focus,
|
||||
&:active {
|
||||
color: var(--color-primary-text);
|
||||
|
||||
#expandDisplayName,
|
||||
.avatardiv{
|
||||
border-radius: 50%;
|
||||
border: 2px solid var(--color-primary-text);
|
||||
margin: -2px;
|
||||
}
|
||||
.avatardiv{
|
||||
background-color: var(--color-primary-text);
|
||||
}
|
||||
#expandDisplayName {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Profile picture in header */
|
||||
.avatardiv {
|
||||
cursor: pointer;
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
|
||||
img {
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
/* do not show display name when profile picture is present */
|
||||
&.avatardiv-shown + #expandDisplayName {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
#expandDisplayName {
|
||||
padding: 8px;
|
||||
opacity: .6;
|
||||
cursor: pointer;
|
||||
|
||||
/* full opacity for gear icon if active */
|
||||
#body-settings & {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* show triangle below user menu if active */
|
||||
#body-settings &:before {
|
||||
content: ' ';
|
||||
height: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
bottom: 2px;
|
||||
z-index: 100;
|
||||
display: block;
|
||||
width: 10px;
|
||||
height: 5px;
|
||||
border-radius: 3px;
|
||||
background-color: var(--color-primary-text);
|
||||
}
|
||||
}
|
||||
|
||||
#expanddiv:after {
|
||||
right: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Skip navigation links – show only on keyboard focus */
|
||||
#skip-actions {
|
||||
position: absolute;
|
||||
|
|
@ -379,7 +244,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* Empty content messages in the header e.g. notifications, contacts menu, … */
|
||||
header #emptycontent,
|
||||
header .emptycontent {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -2,6 +2,7 @@
|
|||
* @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
|
||||
*
|
||||
* @author Christoph Wurst <christoph@winzerhof-wurst.at>
|
||||
* @author Christopher Ng <chrng8@gmail.com>
|
||||
*
|
||||
* @license AGPL-3.0-or-later
|
||||
*
|
||||
|
|
@ -20,41 +21,17 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import OC from '../OC'
|
||||
import Vue from 'vue'
|
||||
|
||||
import $ from 'jquery'
|
||||
import UserMenu from '../views/UserMenu.vue'
|
||||
|
||||
export const setUp = () => {
|
||||
const $menu = $('#header #settings')
|
||||
// Using page terminoogy as below
|
||||
const $excludedPageClasses = [
|
||||
'user-status-menu-item__header',
|
||||
]
|
||||
|
||||
// show loading feedback
|
||||
$menu.delegate('a', 'click', event => {
|
||||
let $page = $(event.target)
|
||||
if (!$page.is('a')) {
|
||||
$page = $page.closest('a')
|
||||
}
|
||||
if (event.which === 1 && !event.ctrlKey && !event.metaKey) {
|
||||
if (!$excludedPageClasses.includes($page.attr('class'))) {
|
||||
$page.find('img').remove()
|
||||
$page.find('div').remove() // prevent odd double-clicks
|
||||
$page.prepend($('<div></div>').addClass('icon-loading-small'))
|
||||
}
|
||||
} else {
|
||||
// Close navigation when opening menu entry in
|
||||
// a new tab
|
||||
OC.hideMenus(() => false)
|
||||
}
|
||||
})
|
||||
|
||||
$menu.delegate('a', 'mouseup', event => {
|
||||
if (event.which === 2) {
|
||||
// Close navigation when opening app in
|
||||
// a new tab via middle click
|
||||
OC.hideMenus(() => false)
|
||||
}
|
||||
})
|
||||
const mountPoint = document.getElementById('user-menu')
|
||||
if (mountPoint) {
|
||||
// eslint-disable-next-line no-new
|
||||
new Vue({
|
||||
el: mountPoint,
|
||||
render: h => h(UserMenu),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
106
core/src/components/UserMenu/UserMenuEntry.vue
Normal file
106
core/src/components/UserMenu/UserMenuEntry.vue
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
<!--
|
||||
- @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>
|
||||
<li :id="id"
|
||||
class="menu-entry">
|
||||
<a v-if="href"
|
||||
:href="href"
|
||||
:class="{ active }"
|
||||
@click.exact="handleClick">
|
||||
<NcLoadingIcon v-if="loading"
|
||||
class="menu-entry__loading-icon"
|
||||
:size="18" />
|
||||
<img v-else :src="cachedIcon" alt="" />
|
||||
{{ name }}
|
||||
</a>
|
||||
<button v-else>
|
||||
<img :src="cachedIcon" alt="" />
|
||||
{{ name }}
|
||||
</button>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
|
||||
import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
|
||||
|
||||
const versionHash = loadState('core', 'versionHash', '')
|
||||
|
||||
export default {
|
||||
name: 'UserMenuEntry',
|
||||
|
||||
components: {
|
||||
NcLoadingIcon,
|
||||
},
|
||||
|
||||
props: {
|
||||
id: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
href: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
active: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
cachedIcon() {
|
||||
return `${this.icon}?v=${versionHash}`
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
handleClick() {
|
||||
this.loading = true
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.menu-entry {
|
||||
&__loading-icon {
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
184
core/src/views/UserMenu.vue
Normal file
184
core/src/views/UserMenu.vue
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
<!--
|
||||
- @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"
|
||||
:aria-label="t('core', 'Open settings menu')">
|
||||
<template #trigger>
|
||||
<NcAvatar class="user-menu__avatar"
|
||||
:disable-menu="true"
|
||||
:disable-tooltip="true"
|
||||
:user="userId" />
|
||||
</template>
|
||||
<nav class="user-menu__nav"
|
||||
:aria-label="t('core', 'Settings menu')">
|
||||
<ul>
|
||||
<UserMenuEntry v-for="entry in settingsNavEntries"
|
||||
v-bind="entry"
|
||||
:key="entry.id" />
|
||||
</ul>
|
||||
</nav>
|
||||
</NcHeaderMenu>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { emit } from '@nextcloud/event-bus'
|
||||
import { getCurrentUser } from '@nextcloud/auth'
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
|
||||
import NcAvatar from '@nextcloud/vue/dist/Components/NcAvatar.js'
|
||||
import NcHeaderMenu from '@nextcloud/vue/dist/Components/NcHeaderMenu.js'
|
||||
|
||||
import UserMenuEntry from '../components/UserMenu/UserMenuEntry.vue'
|
||||
|
||||
const settingsNavEntries = loadState('core', 'settingsNavEntries', [])
|
||||
|
||||
export default {
|
||||
name: 'UserMenu',
|
||||
|
||||
components: {
|
||||
NcAvatar,
|
||||
NcHeaderMenu,
|
||||
UserMenuEntry,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
settingsNavEntries,
|
||||
userId: getCurrentUser()?.uid,
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
emit('core:user-menu:mounted')
|
||||
},
|
||||
}
|
||||
</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-text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__carret {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
&__content {
|
||||
width: fit-content !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__avatar {
|
||||
&:active,
|
||||
&:focus,
|
||||
&:hover {
|
||||
border: 2px solid var(--color-primary-text);
|
||||
}
|
||||
}
|
||||
|
||||
&__nav {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
|
||||
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) !important;
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
&:active,
|
||||
&.active {
|
||||
background-color: var(--color-primary-light);
|
||||
}
|
||||
|
||||
span {
|
||||
padding-bottom: 0;
|
||||
color: var(--color-main-text);
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 110px;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
img,
|
||||
svg {
|
||||
opacity: .7;
|
||||
filter: var(--background-invert-if-dark);
|
||||
}
|
||||
}
|
||||
|
||||
// Override global button styles
|
||||
button {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -70,45 +70,7 @@ p($theme->getTitle());
|
|||
<div id="unified-search"></div>
|
||||
<div id="notifications"></div>
|
||||
<div id="contactsmenu"></div>
|
||||
<div id="settings">
|
||||
<div id="expand" tabindex="0" role="button" class="menutoggle"
|
||||
aria-label="<?php p($l->t('Open settings menu'));?>"
|
||||
aria-haspopup="true" aria-controls="expanddiv" aria-expanded="false">
|
||||
<div id="avatardiv-menu" class="avatardiv<?php if ($_['userAvatarSet']) {
|
||||
print_unescaped(' avatardiv-shown');
|
||||
} else {
|
||||
print_unescaped('" style="display: none');
|
||||
} ?>"
|
||||
data-user="<?php p($_['user_uid']); ?>"
|
||||
data-displayname="<?php p($_['user_displayname']); ?>"
|
||||
<?php
|
||||
if ($_['userAvatarSet']) {
|
||||
$avatar32 = $getUserAvatar(32); ?> data-avatar="<?php p($avatar32); ?>"
|
||||
<?php
|
||||
} ?>>
|
||||
<?php
|
||||
if ($_['userAvatarSet']) {?>
|
||||
<img alt="" width="32" height="32"
|
||||
src="<?php p($avatar32);?>"
|
||||
srcset="<?php p($getUserAvatar(64));?> 2x, <?php p($getUserAvatar(128));?> 4x"
|
||||
>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
<nav class="settings-menu" id="expanddiv" style="display:none;">
|
||||
<ul>
|
||||
<?php foreach ($_['settingsnavigation'] as $entry):?>
|
||||
<li data-id="<?php p($entry['id']); ?>">
|
||||
<a href="<?php print_unescaped($entry['href'] !== '' ? $entry['href'] : '#'); ?>"
|
||||
<?php if ($entry["active"]): ?> class="active"<?php endif; ?>>
|
||||
<img alt="" src="<?php print_unescaped($entry['icon'] . '?v=' . $_['versionHash']); ?>">
|
||||
<?php p($entry['name']) ?>
|
||||
</a>
|
||||
</li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
<div id="user-menu"></div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
|
|
|||
4
dist/core-common.js
vendored
4
dist/core-common.js
vendored
File diff suppressed because one or more lines are too long
2
dist/core-common.js.LICENSE.txt
vendored
2
dist/core-common.js.LICENSE.txt
vendored
|
|
@ -366,6 +366,8 @@ object-assign
|
|||
|
||||
/*! For license information please see NcEmojiPicker.js.LICENSE.txt */
|
||||
|
||||
/*! For license information please see NcLoadingIcon.js.LICENSE.txt */
|
||||
|
||||
/*! For license information please see NcModal.js.LICENSE.txt */
|
||||
|
||||
/*! For license information please see NcNoteCard.js.LICENSE.txt */
|
||||
|
|
|
|||
2
dist/core-common.js.map
vendored
2
dist/core-common.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/core-main.js
vendored
4
dist/core-main.js
vendored
File diff suppressed because one or more lines are too long
2
dist/core-main.js.map
vendored
2
dist/core-main.js.map
vendored
File diff suppressed because one or more lines are too long
4
dist/user_status-menu.js
vendored
4
dist/user_status-menu.js
vendored
File diff suppressed because one or more lines are too long
2
dist/user_status-menu.js.map
vendored
2
dist/user_status-menu.js.map
vendored
File diff suppressed because one or more lines are too long
|
|
@ -130,7 +130,7 @@ class TemplateLayout extends \OC_Template {
|
|||
$navigation = $this->navigationManager->getAll();
|
||||
$this->assign('navigation', $navigation);
|
||||
$settingsNavigation = $this->navigationManager->getAll('settings');
|
||||
$this->assign('settingsnavigation', $settingsNavigation);
|
||||
$this->initialState->provideInitialState('core', 'settingsNavEntries', $settingsNavigation);
|
||||
|
||||
foreach ($navigation as $entry) {
|
||||
if ($entry['active']) {
|
||||
|
|
@ -268,7 +268,7 @@ class TemplateLayout extends \OC_Template {
|
|||
|
||||
$this->assign('cssfiles', []);
|
||||
$this->assign('printcssfiles', []);
|
||||
$this->assign('versionHash', self::$versionHash);
|
||||
$this->initialState->provideInitialState('core', 'versionHash', self::$versionHash);
|
||||
foreach ($cssFiles as $info) {
|
||||
$web = $info[1];
|
||||
$file = $info[2];
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class SettingsMenuContext implements Context, ActorAwareInterface {
|
|||
* @return Locator
|
||||
*/
|
||||
public static function settingsSectionInHeader() {
|
||||
return Locator::forThe()->xpath("//*[@id = 'header']//*[@id = 'settings']")->
|
||||
return Locator::forThe()->xpath("//*[@id = 'header']//*[@id = 'user-menu']")->
|
||||
describedAs("Settings menu section in the header");
|
||||
}
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ class SettingsMenuContext implements Context, ActorAwareInterface {
|
|||
* @return Locator
|
||||
*/
|
||||
public static function settingsMenuButton() {
|
||||
return Locator::forThe()->id("expand")->
|
||||
return Locator::forThe()->css(".header-menu__trigger")->
|
||||
descendantOf(self::settingsSectionInHeader())->
|
||||
describedAs("Settings menu button");
|
||||
}
|
||||
|
|
@ -49,7 +49,7 @@ class SettingsMenuContext implements Context, ActorAwareInterface {
|
|||
* @return Locator
|
||||
*/
|
||||
public static function settingsMenu() {
|
||||
return Locator::forThe()->id("expanddiv")->
|
||||
return Locator::forThe()->css(".user-menu__nav")->
|
||||
descendantOf(self::settingsSectionInHeader())->
|
||||
describedAs("Settings menu");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue