mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
fix(webapp): mobile optimization (#8516)
* - optimized header - added possibility of extra mobile logo * - changed behavior of NotificationMenu link get directly open for mobile * - moved notification links to the top of the menu * - optimized chat view for mobile * - added logo branding structure * - added logo branding structure * - fixed chat height * - fixed paddings for internal pages * Fix linting * Fix linting --------- Co-authored-by: Sebastian Stein <sebastian@codepassion.de> Co-authored-by: Wolfgang Huß <wolle.huss@pjannto.com>
This commit is contained in:
parent
ca5b1fa0b5
commit
ff366a4075
@ -1,10 +1,3 @@
|
|||||||
// this file is duplicated in `backend/src/config/logos` and `webapp/constants/logos.js` and replaced on rebranding
|
// this file is duplicated in `backend/src/config/logos.ts` and `webapp/constants/logos.js` and replaced on rebranding
|
||||||
// this are the paths in the webapp
|
// this are the paths in the webapp
|
||||||
export default {
|
export default {}
|
||||||
LOGO_HEADER_PATH: '/img/custom/logo-horizontal.svg',
|
|
||||||
LOGO_SIGNUP_PATH: '/img/custom/logo-squared.svg',
|
|
||||||
LOGO_WELCOME_PATH: '/img/custom/logo-squared.svg',
|
|
||||||
LOGO_LOGOUT_PATH: '/img/custom/logo-squared.svg',
|
|
||||||
LOGO_PASSWORD_RESET_PATH: '/img/custom/logo-squared.svg',
|
|
||||||
LOGO_MAINTENACE_RESET_PATH: '/img/custom/logo-squared.svg',
|
|
||||||
}
|
|
||||||
|
|||||||
32
backend/src/config/logosBranded.ts
Normal file
32
backend/src/config/logosBranded.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// this file is duplicated in `backend/src/config/logos.ts` and `webapp/constants/logos.js` and replaced on rebranding
|
||||||
|
// this are the paths in the webapp
|
||||||
|
import { merge } from 'lodash'
|
||||||
|
|
||||||
|
import logos from '@config/logos'
|
||||||
|
|
||||||
|
const defaultLogos = {
|
||||||
|
LOGO_HEADER_PATH: '/img/custom/logo-horizontal.svg',
|
||||||
|
LOGO_HEADER_MOBILE_PATH: '/img/custom/logo-horizontal.svg',
|
||||||
|
LOGO_HEADER_WIDTH: '130px',
|
||||||
|
LOGO_HEADER_MOBILE_WIDTH: '100px',
|
||||||
|
LOGO_HEADER_CLICK: {
|
||||||
|
// externalLink: {
|
||||||
|
// url: 'https://ocelot.social',
|
||||||
|
// target: '_blank',
|
||||||
|
// },
|
||||||
|
externalLink: null,
|
||||||
|
internalPath: {
|
||||||
|
to: {
|
||||||
|
name: 'index',
|
||||||
|
},
|
||||||
|
scrollTo: '.main-navigation',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
LOGO_SIGNUP_PATH: '/img/custom/logo-squared.svg',
|
||||||
|
LOGO_WELCOME_PATH: '/img/custom/logo-squared.svg',
|
||||||
|
LOGO_LOGOUT_PATH: '/img/custom/logo-squared.svg',
|
||||||
|
LOGO_PASSWORD_RESET_PATH: '/img/custom/logo-squared.svg',
|
||||||
|
LOGO_MAINTENACE_RESET_PATH: '/img/custom/logo-squared.svg',
|
||||||
|
}
|
||||||
|
|
||||||
|
export default merge(defaultLogos, logos)
|
||||||
@ -11,7 +11,7 @@ import { createTransport } from 'nodemailer'
|
|||||||
// import type Email as EmailType from '@types/email-templates'
|
// import type Email as EmailType from '@types/email-templates'
|
||||||
|
|
||||||
import CONFIG, { nodemailerTransportOptions } from '@config/index'
|
import CONFIG, { nodemailerTransportOptions } from '@config/index'
|
||||||
import logosWebapp from '@config/logos'
|
import logosWebapp from '@config/logosBranded'
|
||||||
import metadata from '@config/metadata'
|
import metadata from '@config/metadata'
|
||||||
import { UserDbProperties } from '@db/types/User'
|
import { UserDbProperties } from '@db/types/User'
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
:loading-rooms="loadingRooms"
|
:loading-rooms="loadingRooms"
|
||||||
show-files="false"
|
show-files="false"
|
||||||
show-audio="false"
|
show-audio="false"
|
||||||
|
:height="'calc(100dvh - 190px)'"
|
||||||
:styles="JSON.stringify(computedChatStyle)"
|
:styles="JSON.stringify(computedChatStyle)"
|
||||||
:show-footer="true"
|
:show-footer="true"
|
||||||
:responsive-breakpoint="responsiveBreakpoint"
|
:responsive-breakpoint="responsiveBreakpoint"
|
||||||
|
|||||||
@ -136,12 +136,12 @@
|
|||||||
<ds-flex-item class="mobile-hamburger-menu">
|
<ds-flex-item class="mobile-hamburger-menu">
|
||||||
<client-only>
|
<client-only>
|
||||||
<!-- chat menu -->
|
<!-- chat menu -->
|
||||||
<div style="display: inline-flex">
|
<div>
|
||||||
<chat-notification-menu />
|
<chat-notification-menu />
|
||||||
</div>
|
</div>
|
||||||
<!-- notification menu -->
|
<!-- notification menu -->
|
||||||
<div style="display: inline-flex; padding-right: clamp(10px, 2.5vw, 20px)">
|
<div>
|
||||||
<notification-menu />
|
<notification-menu no-menu />
|
||||||
</div>
|
</div>
|
||||||
</client-only>
|
</client-only>
|
||||||
<!-- hamburger menu -->
|
<!-- hamburger menu -->
|
||||||
@ -284,7 +284,7 @@ import { mapGetters } from 'vuex'
|
|||||||
import isEmpty from 'lodash/isEmpty'
|
import isEmpty from 'lodash/isEmpty'
|
||||||
import { SHOW_GROUP_BUTTON_IN_HEADER } from '~/constants/groups.js'
|
import { SHOW_GROUP_BUTTON_IN_HEADER } from '~/constants/groups.js'
|
||||||
import { SHOW_CONTENT_FILTER_HEADER_MENU } from '~/constants/filter.js'
|
import { SHOW_CONTENT_FILTER_HEADER_MENU } from '~/constants/filter.js'
|
||||||
import LOGOS from '~/constants/logos.js'
|
import LOGOS from '~/constants/logosBranded.js'
|
||||||
import AvatarMenu from '~/components/AvatarMenu/AvatarMenu'
|
import AvatarMenu from '~/components/AvatarMenu/AvatarMenu'
|
||||||
import ChatNotificationMenu from '~/components/ChatNotificationMenu/ChatNotificationMenu'
|
import ChatNotificationMenu from '~/components/ChatNotificationMenu/ChatNotificationMenu'
|
||||||
import CustomButton from '~/components/CustomButton/CustomButton'
|
import CustomButton from '~/components/CustomButton/CustomButton'
|
||||||
@ -409,6 +409,25 @@ export default {
|
|||||||
flex-flow: row nowrap;
|
flex-flow: row nowrap;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
& > div {
|
||||||
|
display: inline-flex;
|
||||||
|
|
||||||
|
padding-right: 15px;
|
||||||
|
&:first-child {
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
overflow: visible;
|
||||||
|
.svg {
|
||||||
|
height: 1.8em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.hamburger-button .svg {
|
||||||
|
height: 1.5em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.mobile-menu {
|
.mobile-menu {
|
||||||
margin: 0 20px;
|
margin: 0 20px;
|
||||||
|
|||||||
@ -1,29 +1,30 @@
|
|||||||
<template>
|
<template>
|
||||||
<component :is="tag" class="ds-logo" :class="[inverse && 'ds-logo-inverse']">
|
<component :is="tag" class="ds-logo" :class="[inverse && 'ds-logo-inverse']">
|
||||||
|
<!-- Desktop logo -->
|
||||||
<img
|
<img
|
||||||
v-if="!inverse"
|
class="ds-logo-svg ds-logo-desktop"
|
||||||
class="ds-logo-svg"
|
|
||||||
:alt="metadata.APPLICATION_NAME + ' ' + logo.alt"
|
:alt="metadata.APPLICATION_NAME + ' ' + logo.alt"
|
||||||
:src="logo.path"
|
:src="logo.path"
|
||||||
:style="logoWidthStyle"
|
:style="logoWidthStyle"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!-- Mobile logo (falls back to desktop if not provided) -->
|
||||||
<img
|
<img
|
||||||
v-else
|
class="ds-logo-svg ds-logo-mobile"
|
||||||
class="ds-logo-svg"
|
:alt="metadata.APPLICATION_NAME + ' ' + logo.alt + ' Mobile'"
|
||||||
:alt="metadata.APPLICATION_NAME + ' ' + logo.alt"
|
:src="logo.mobilePath || logo.path"
|
||||||
:src="logo.path"
|
:style="mobileLogoWidthStyle"
|
||||||
:style="logoWidthStyle"
|
|
||||||
/>
|
/>
|
||||||
</component>
|
</component>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import logos from '~/constants/logos.js'
|
import logos from '~/constants/logosBranded.js'
|
||||||
import metadata from '~/constants/metadata.js'
|
import metadata from '~/constants/metadata.js'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component displays the brand's logo.
|
* This component displays the brand's logo.
|
||||||
* @version 1.0.0
|
* @version 1.1.0
|
||||||
*/
|
*/
|
||||||
export default {
|
export default {
|
||||||
name: 'Logo',
|
name: 'Logo',
|
||||||
@ -42,6 +43,13 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* Mobile logo width
|
||||||
|
*/
|
||||||
|
mobileLogoWidth: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* Inverse the logo
|
* Inverse the logo
|
||||||
*/
|
*/
|
||||||
@ -61,8 +69,10 @@ export default {
|
|||||||
const logosObject = {
|
const logosObject = {
|
||||||
header: {
|
header: {
|
||||||
path: logos.LOGO_HEADER_PATH,
|
path: logos.LOGO_HEADER_PATH,
|
||||||
|
mobilePath: logos.LOGO_HEADER_MOBILE_PATH || null,
|
||||||
alt: 'Header',
|
alt: 'Header',
|
||||||
widthDefault: logos.LOGO_HEADER_WIDTH,
|
widthDefault: logos.LOGO_HEADER_WIDTH,
|
||||||
|
mobileWidthDefault: logos.LOGO_HEADER_MOBILE_WIDTH || logos.LOGO_HEADER_WIDTH,
|
||||||
},
|
},
|
||||||
welcome: { path: logos.LOGO_WELCOME_PATH, alt: 'Welcome', widthDefault: '200px' },
|
welcome: { path: logos.LOGO_WELCOME_PATH, alt: 'Welcome', widthDefault: '200px' },
|
||||||
signup: { path: logos.LOGO_SIGNUP_PATH, alt: 'Sign Up', widthDefault: '200px' },
|
signup: { path: logos.LOGO_SIGNUP_PATH, alt: 'Sign Up', widthDefault: '200px' },
|
||||||
@ -85,12 +95,12 @@ export default {
|
|||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
logoWidthStyle() {
|
logoWidthStyle() {
|
||||||
let width = ''
|
const width = this.logoWidth === null ? this.logo.widthDefault : this.logoWidth
|
||||||
if (this.logoWidth === null) {
|
return `width: ${width};`
|
||||||
width = this.logo.widthDefault
|
},
|
||||||
} else {
|
mobileLogoWidthStyle() {
|
||||||
width = this.logoWidth
|
const width =
|
||||||
}
|
this.mobileLogoWidth === null ? this.logo.mobileWidthDefault : this.mobileLogoWidth
|
||||||
return `width: ${width};`
|
return `width: ${width};`
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -115,6 +125,25 @@ export default {
|
|||||||
fill: #000000;
|
fill: #000000;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Show desktop logo by default and hide mobile logo */
|
||||||
|
.ds-logo-desktop {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds-logo-mobile {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.ds-logo-desktop {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ds-logo-mobile {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<docs src="./demo.md"></docs>
|
<docs src="./demo.md"></docs>
|
||||||
|
|||||||
@ -14,6 +14,18 @@
|
|||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
|
<nuxt-link v-else-if="noMenu" class="notifications-menu" :to="{ name: 'notifications' }">
|
||||||
|
<base-button
|
||||||
|
ghost
|
||||||
|
circle
|
||||||
|
v-tooltip="{
|
||||||
|
content: $t('header.notifications.tooltip'),
|
||||||
|
placement: 'bottom-start',
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<counter-icon icon="bell" :count="unreadNotificationsCount" danger />
|
||||||
|
</base-button>
|
||||||
|
</nuxt-link>
|
||||||
<dropdown v-else class="notifications-menu" offset="8" :placement="placement">
|
<dropdown v-else class="notifications-menu" offset="8" :placement="placement">
|
||||||
<template #default="{ toggleMenu }">
|
<template #default="{ toggleMenu }">
|
||||||
<base-button
|
<base-button
|
||||||
@ -29,9 +41,6 @@
|
|||||||
</base-button>
|
</base-button>
|
||||||
</template>
|
</template>
|
||||||
<template #popover="{ closeMenu }">
|
<template #popover="{ closeMenu }">
|
||||||
<div class="notifications-menu-popover">
|
|
||||||
<notification-list :notifications="notifications" @markAsRead="markAsRead" />
|
|
||||||
</div>
|
|
||||||
<ds-flex class="notifications-link-container">
|
<ds-flex class="notifications-link-container">
|
||||||
<ds-flex-item class="notifications-link-container-item" :width="{ base: '100%' }" centered>
|
<ds-flex-item class="notifications-link-container-item" :width="{ base: '100%' }" centered>
|
||||||
<nuxt-link :to="{ name: 'notifications' }">
|
<nuxt-link :to="{ name: 'notifications' }">
|
||||||
@ -51,6 +60,9 @@
|
|||||||
</base-button>
|
</base-button>
|
||||||
</ds-flex-item>
|
</ds-flex-item>
|
||||||
</ds-flex>
|
</ds-flex>
|
||||||
|
<div class="notifications-menu-popover">
|
||||||
|
<notification-list :notifications="notifications" @markAsRead="markAsRead" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</dropdown>
|
</dropdown>
|
||||||
</template>
|
</template>
|
||||||
@ -82,6 +94,7 @@ export default {
|
|||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
placement: { type: String },
|
placement: { type: String },
|
||||||
|
noMenu: { type: Boolean, default: false },
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async markAsRead(notificationSourceId) {
|
async markAsRead(notificationSourceId) {
|
||||||
|
|||||||
@ -32,3 +32,16 @@ export default {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@media only screen and (max-width: 500px) {
|
||||||
|
.ds-container {
|
||||||
|
padding-left: 0 !important;
|
||||||
|
padding-right: 0 !important;
|
||||||
|
|
||||||
|
.base-card {
|
||||||
|
padding: 16px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { storiesOf } from '@storybook/vue'
|
import { storiesOf } from '@storybook/vue'
|
||||||
import helpers from '~/storybook/helpers'
|
import helpers from '~/storybook/helpers'
|
||||||
import logos from '~/constants/logos.js'
|
import logos from '~/constants/logosBranded.js'
|
||||||
import BaseCard from './BaseCard.vue'
|
import BaseCard from './BaseCard.vue'
|
||||||
|
|
||||||
storiesOf('Generic/BaseCard', module)
|
storiesOf('Generic/BaseCard', module)
|
||||||
|
|||||||
@ -1,24 +1,3 @@
|
|||||||
// this file is duplicated in `backend/src/config/logos.js` and `webapp/constants/logos.js` and replaced on rebranding
|
// this file is duplicated in `backend/src/config/logos.js` and `webapp/constants/logos.js` and replaced on rebranding
|
||||||
// this are the paths in the webapp
|
// this are the paths in the webapp
|
||||||
export default {
|
export default {}
|
||||||
LOGO_HEADER_PATH: '/img/custom/logo-horizontal.svg',
|
|
||||||
LOGO_HEADER_WIDTH: '130px',
|
|
||||||
LOGO_HEADER_CLICK: {
|
|
||||||
// externalLink: {
|
|
||||||
// url: 'https://ocelot.social',
|
|
||||||
// target: '_blank',
|
|
||||||
// },
|
|
||||||
externalLink: null,
|
|
||||||
internalPath: {
|
|
||||||
to: {
|
|
||||||
name: 'index',
|
|
||||||
},
|
|
||||||
scrollTo: '.main-navigation',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
LOGO_SIGNUP_PATH: '/img/custom/logo-squared.svg',
|
|
||||||
LOGO_WELCOME_PATH: '/img/custom/logo-squared.svg',
|
|
||||||
LOGO_LOGOUT_PATH: '/img/custom/logo-squared.svg',
|
|
||||||
LOGO_PASSWORD_RESET_PATH: '/img/custom/logo-squared.svg',
|
|
||||||
LOGO_MAINTENACE_RESET_PATH: '/img/custom/logo-squared.svg',
|
|
||||||
}
|
|
||||||
|
|||||||
31
webapp/constants/logosBranded.js
Normal file
31
webapp/constants/logosBranded.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// this file is duplicated in `backend/src/config/logos.js` and `webapp/constants/logos.js` and replaced on rebranding
|
||||||
|
// this are the paths in the webapp
|
||||||
|
import { merge } from 'lodash'
|
||||||
|
import logos from '~/constants/logos'
|
||||||
|
|
||||||
|
const defaultLogos = {
|
||||||
|
LOGO_HEADER_PATH: '/img/custom/logo-horizontal.svg',
|
||||||
|
LOGO_HEADER_MOBILE_PATH: '/img/custom/logo-horizontal.svg',
|
||||||
|
LOGO_HEADER_WIDTH: '130px',
|
||||||
|
LOGO_HEADER_MOBILE_WIDTH: '100px',
|
||||||
|
LOGO_HEADER_CLICK: {
|
||||||
|
// externalLink: {
|
||||||
|
// url: 'https://ocelot.social',
|
||||||
|
// target: '_blank',
|
||||||
|
// },
|
||||||
|
externalLink: null,
|
||||||
|
internalPath: {
|
||||||
|
to: {
|
||||||
|
name: 'index',
|
||||||
|
},
|
||||||
|
scrollTo: '.main-navigation',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
LOGO_SIGNUP_PATH: '/img/custom/logo-squared.svg',
|
||||||
|
LOGO_WELCOME_PATH: '/img/custom/logo-squared.svg',
|
||||||
|
LOGO_LOGOUT_PATH: '/img/custom/logo-squared.svg',
|
||||||
|
LOGO_PASSWORD_RESET_PATH: '/img/custom/logo-squared.svg',
|
||||||
|
LOGO_MAINTENACE_RESET_PATH: '/img/custom/logo-squared.svg',
|
||||||
|
}
|
||||||
|
|
||||||
|
export default merge(defaultLogos, logos)
|
||||||
@ -23,7 +23,7 @@
|
|||||||
</ds-container>
|
</ds-container>
|
||||||
</div>
|
</div>
|
||||||
<ds-container>
|
<ds-container>
|
||||||
<div style="padding: 5rem 2rem">
|
<div class="content">
|
||||||
<nuxt />
|
<nuxt />
|
||||||
</div>
|
</div>
|
||||||
</ds-container>
|
</ds-container>
|
||||||
@ -61,7 +61,7 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss" scoped>
|
||||||
.main-navigation-right {
|
.main-navigation-right {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
@ -69,4 +69,14 @@ export default {
|
|||||||
.main-navigation-right .desktop-view {
|
.main-navigation-right .desktop-view {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.layout-blank .content {
|
||||||
|
padding: 5rem 2rem;
|
||||||
|
}
|
||||||
|
@media only screen and (max-width: 500px) {
|
||||||
|
.layout-blank .content {
|
||||||
|
padding-left: 0 !important;
|
||||||
|
padding-right: 0 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1,12 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<ds-heading tag="h1">{{ $t('chat.page.headline') }}</ds-heading>
|
|
||||||
<add-chat-room-by-user-search
|
<add-chat-room-by-user-search
|
||||||
v-if="showUserSearch"
|
v-if="showUserSearch"
|
||||||
@add-chat-room="addChatRoom"
|
@add-chat-room="addChatRoom"
|
||||||
@close-user-search="showUserSearch = false"
|
@close-user-search="showUserSearch = false"
|
||||||
/>
|
/>
|
||||||
<ds-space margin-bottom="small" />
|
|
||||||
<chat
|
<chat
|
||||||
:roomId="getShowChat.showChat ? getShowChat.roomID : null"
|
:roomId="getShowChat.showChat ? getShowChat.roomID : null"
|
||||||
ref="chat"
|
ref="chat"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user