Merge branch 'master' into 93-minimize-docker-image-size-with-multi-stage-build

This commit is contained in:
Robert Schäfer 2019-01-11 01:31:10 +01:00 committed by GitHub
commit 8ee883954c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 233 additions and 143 deletions

View File

@ -126,3 +126,23 @@ hr {
background-color: $color-neutral-80;
height: 1px !important;
}
#overlay {
display: block;
opacity: 0;
width: 100%;
height: 100%;
top: 0;
left: 0;
position: fixed;
background: rgba(0, 0, 0, 0.15);
z-index: 99;
pointer-events: none;
transition: opacity 150ms ease-out;
transition-delay: 50ms;
.dropdown-open & {
opacity: 1;
transition-delay: 0;
}
}

View File

@ -1,127 +1,127 @@
<template>
<v-popover
:open.sync="isPopoverOpen"
<dropdown
:disabled="!hasAuthor || !showAuthorPopover"
:open-group="Math.random().toString()"
placement="top-start"
trigger="manual"
offset="0"
>
<a
v-router-link
:href="author.slug ? $router.resolve({ name: 'profile-slug', params: { slug: author.slug } }).href : null"
style="white-space: nowrap; display: flex; align-items: center;"
@mouseover="popoverMouseEnter"
@mouseleave="popoveMouseLeave"
<template
slot="default"
slot-scope="{openMenu, closeMenu, isOpen}"
>
<div style="display: inline-block; float: left; margin-right: 4px; height: 100%; vertical-align: middle;">
<ds-avatar
:image="author.avatar"
:name="author.name"
style="display: inline-block; vertical-align: middle;"
size="32px"
/>
</div>
<div style="display: inline-block; height: 100%; vertical-align: middle;">
<b
class="username"
style="vertical-align: middle;"
>
{{ author.name | truncate(trunc, 18) }}
</b>
<template v-if="post.createdAt">
<br>
<ds-text
size="small"
color="soft"
>
{{ post.createdAt | dateTime('dd. MMMM yyyy HH:mm') }}
</ds-text>
</template>
</div>
</a>
<div
slot="popover"
style="min-width: 250px;"
@mouseover="popoverMouseEnter"
@mouseleave="popoveMouseLeave"
>
<!--<ds-avatar
:image="author.avatar"
:name="author.name || 'Anonymus'"
class="profile-avatar"
size="90px" />-->
<hc-badges
v-if="author.badges && author.badges.length"
:badges="author.badges"
style="margin-bottom: -10px"
/>
<ds-flex>
<ds-flex-item class="ds-tab-nav-item">
<ds-space margin="small">
<ds-number
:count="fanCount"
:label="$t('profile.followers')"
size="x-large"
/>
</ds-space>
</ds-flex-item>
<ds-flex-item class="ds-tab-nav-item ds-tab-nav-item-active">
<ds-space margin="small">
<ds-number
:count="author.contributionsCount"
:label="$t('common.post', null, author.contributionsCount)"
/>
</ds-space>
</ds-flex-item>
<ds-flex-item class="ds-tab-nav-item">
<ds-space margin="small">
<ds-number
:count="author.commentsCount"
:label="$t('common.comment', null, author.commentsCount)"
/>
</ds-space>
</ds-flex-item>
</ds-flex>
<!--<ds-text
color="soft"
size="small">
<ds-icon name="map-marker" /> Hamburg, Deutschland
</ds-text>-->
<ds-flex
v-if="!itsMe"
gutter="x-small"
style="margin-bottom: 0;"
<a
v-router-link
:href="author.slug ? $router.resolve({ name: 'profile-slug', params: { slug: author.slug } }).href : null"
:class="['author', isOpen && 'active']"
@mouseover="openMenu(true)"
@mouseleave="closeMenu(true)"
>
<ds-flex-item :width="{base: 3}">
<hc-follow-button
:follow-id="author.id"
@update="voted = true"
<div style="display: inline-block; float: left; margin-right: 4px; height: 100%; vertical-align: middle;">
<ds-avatar
:image="author.avatar"
:name="author.name"
style="display: inline-block; vertical-align: middle;"
size="32px"
/>
</ds-flex-item>
<ds-flex-item :width="{base: 1}">
<ds-button full-width>
<ds-icon name="user-times" />
</ds-button>
</ds-flex-item>
</ds-flex>
<!--<ds-space margin-bottom="x-small" />-->
</div>
</v-popover>
</div>
<div style="display: inline-block; height: 100%; vertical-align: middle;">
<b
class="username"
style="vertical-align: middle;"
>
{{ author.name | truncate(trunc, 18) }}
</b>
<template v-if="post.createdAt">
<br>
<ds-text
size="small"
color="soft"
>
{{ post.createdAt | dateTime('dd. MMMM yyyy HH:mm') }}
</ds-text>
</template>
</div>
</a>
</template>
<template
slot="popover"
>
<div style="min-width: 250px">
<!--<ds-avatar
:image="author.avatar"
:name="author.name || 'Anonymus'"
class="profile-avatar"
size="90px" />-->
<hc-badges
v-if="author.badges && author.badges.length"
:badges="author.badges"
style="margin-bottom: -10px"
/>
<ds-flex>
<ds-flex-item class="ds-tab-nav-item">
<ds-space margin="small">
<ds-number
:count="fanCount"
:label="$t('profile.followers')"
size="x-large"
/>
</ds-space>
</ds-flex-item>
<ds-flex-item class="ds-tab-nav-item ds-tab-nav-item-active">
<ds-space margin="small">
<ds-number
:count="author.contributionsCount"
:label="$t('common.post', null, author.contributionsCount)"
/>
</ds-space>
</ds-flex-item>
<ds-flex-item class="ds-tab-nav-item">
<ds-space margin="small">
<ds-number
:count="author.commentsCount"
:label="$t('common.comment', null, author.commentsCount)"
/>
</ds-space>
</ds-flex-item>
</ds-flex>
<!--<ds-text
color="soft"
size="small">
<ds-icon name="map-marker" /> Hamburg, Deutschland
</ds-text>-->
<ds-flex
v-if="!itsMe"
gutter="x-small"
style="margin-bottom: 0;"
>
<ds-flex-item :width="{base: 3}">
<hc-follow-button
:follow-id="author.id"
@update="voted = true"
/>
</ds-flex-item>
<ds-flex-item :width="{base: 1}">
<ds-button full-width>
<ds-icon name="user-times" />
</ds-button>
</ds-flex-item>
</ds-flex>
<!--<ds-space margin-bottom="x-small" />-->
</div>
</template>
</dropdown>
</template>
<script>
import HcFollowButton from '~/components/FollowButton.vue'
import HcBadges from '~/components/Badges.vue'
let mouseEnterTimer = null
let mouseLeaveTimer = null
import Dropdown from '~/components/Dropdown'
export default {
name: 'HcAuthor',
components: {
HcFollowButton,
HcBadges
HcBadges,
Dropdown
},
props: {
post: { type: Object, default: null },
@ -130,7 +130,6 @@ export default {
},
data() {
return {
isPopoverOpen: false,
voted: false
}
},
@ -156,30 +155,6 @@ export default {
hasAuthor() {
return Boolean(this.post && this.post.author)
}
},
beforeDestroy() {
clearTimeout(mouseEnterTimer)
clearTimeout(mouseLeaveTimer)
},
methods: {
popoverMouseEnter() {
clearTimeout(mouseEnterTimer)
clearTimeout(mouseLeaveTimer)
if (!this.isPopoverOpen) {
mouseEnterTimer = setTimeout(() => {
this.isPopoverOpen = true
}, 500)
}
},
popoveMouseLeave() {
clearTimeout(mouseEnterTimer)
clearTimeout(mouseLeaveTimer)
if (this.isPopoverOpen) {
mouseLeaveTimer = setTimeout(() => {
this.isPopoverOpen = false
}, 300)
}
}
}
}
</script>
@ -191,4 +166,15 @@ export default {
margin-top: -45px;
border: #fff 5px solid;
}
.author {
white-space: nowrap;
position: relative;
display: flex;
align-items: center;
&:hover,
&.active {
z-index: 999;
}
}
</style>

View File

@ -3,10 +3,16 @@
:open.sync="isPopoverOpen"
:open-group="Math.random().toString()"
:placement="placement"
:disabled="disabled"
trigger="manual"
:offset="offset"
>
<slot :toggleMenu="toggleMenu" />
<slot
:toggleMenu="toggleMenu"
:openMenu="openMenu"
:closeMenu="closeMenu"
:isOpen="isOpen"
/>
<div
slot="popover"
@mouseover="popoverMouseEnter"
@ -15,6 +21,9 @@
<slot
name="popover"
:toggleMenu="toggleMenu"
:openMenu="openMenu"
:closeMenu="closeMenu"
:isOpen="isOpen"
/>
</div>
</v-popover>
@ -29,6 +38,7 @@ let mouseLeaveTimer = null
export default {
props: {
placement: { type: String, default: 'bottom-end' },
disabled: { type: Boolean, default: false },
offset: { type: [String, Number], default: '16' }
},
data() {
@ -36,17 +46,68 @@ export default {
isPopoverOpen: false
}
},
computed: {
isOpen() {
return this.isPopoverOpen
}
},
watch: {
isPopoverOpen: {
immediate: true,
handler(isOpen) {
try {
if (isOpen) {
this.$nextTick(() => {
setTimeout(() => {
document
.getElementsByTagName('body')[0]
.classList.add('dropdown-open')
}, 20)
})
} else {
document
.getElementsByTagName('body')[0]
.classList.remove('dropdown-open')
}
} catch (err) {}
}
}
},
beforeDestroy() {
clearTimeout(mouseEnterTimer)
clearTimeout(mouseLeaveTimer)
},
methods: {
toggleMenu() {
this.isPopoverOpen = !this.isPopoverOpen
this.isPopoverOpen ? this.closeMenu(false) : this.openMenu(false)
},
openMenu(useTimeout) {
if (this.disabled) {
return
}
this.clearTimeouts()
if (useTimeout === true) {
this.popoverMouseEnter()
} else {
this.isPopoverOpen = true
}
},
closeMenu(useTimeout) {
if (this.disabled) {
return
}
this.clearTimeouts()
if (useTimeout === true) {
this.popoveMouseLeave()
} else {
this.isPopoverOpen = false
}
},
popoverMouseEnter() {
clearTimeout(mouseEnterTimer)
clearTimeout(mouseLeaveTimer)
if (this.disabled) {
return
}
this.clearTimeouts()
if (!this.isPopoverOpen) {
mouseEnterTimer = setTimeout(() => {
this.isPopoverOpen = true
@ -54,13 +115,19 @@ export default {
}
},
popoveMouseLeave() {
clearTimeout(mouseEnterTimer)
clearTimeout(mouseLeaveTimer)
if (this.disabled) {
return
}
this.clearTimeouts()
if (this.isPopoverOpen) {
mouseLeaveTimer = setTimeout(() => {
this.isPopoverOpen = false
}, 300)
}
},
clearTimeouts() {
clearTimeout(mouseEnterTimer)
clearTimeout(mouseLeaveTimer)
}
}
}

View File

@ -5,6 +5,7 @@
<nuxt />
</div>
</ds-container>
<div id="overlay" />
</div>
</template>

View File

@ -26,7 +26,7 @@
<a
class="avatar-menu-trigger"
:href="$router.resolve({name: 'profile-slug', params: {slug: user.slug}}).href"
@click.prevent="toggleMenu()"
@click.prevent="toggleMenu"
>
<ds-avatar
:image="user.avatar"
@ -37,7 +37,7 @@
</template>
<template
slot="popover"
slot-scope="{toggleMenu}"
slot-scope="{closeMenu}"
>
<div class="avatar-menu-popover">
{{ $t('login.hello') }} <b>{{ user.name }}</b>
@ -50,13 +50,16 @@
slot-scope="item"
:route="item.route"
:parents="item.parents"
@click.native="toggleMenu"
@click.native="closeMenu(false)"
>
<ds-icon :name="item.route.icon" /> {{ item.route.name }}
</ds-menu-item>
</ds-menu>
<ds-space margin="xx-small" />
<nuxt-link :to="{ name: 'logout'}">
<nuxt-link
:to="{ name: 'logout'}"
style="margin-left: 0"
>
<ds-icon name="sign-out" /> {{ $t('login.logout') }}
</nuxt-link>
</div>
@ -72,6 +75,7 @@
<nuxt />
</div>
</ds-container>
<div id="overlay" />
</div>
</template>
@ -121,6 +125,10 @@ export default {
},
methods: {
isExact(url) {
if (url.indexOf('/profile') === 0) {
// do only match own profile
this.$route.path === url
}
return this.$route.path.indexOf(url) === 0
}
}
@ -147,10 +155,14 @@ export default {
padding-bottom: 0.5rem;
nav {
margin-left: -15px;
margin-right: -15px;
margin-left: -16px;
margin-right: -10px;
padding-top: 1rem;
padding-bottom: 1rem;
a {
padding-left: 12px;
}
}
}
</style>

View File

@ -14,6 +14,10 @@
<component
v-if="route"
class="ds-menu-item-link"
:class="[
isExact && 'router-active-link',
isExact && 'router-link-exact-active'
]"
v-bind="bindings"
:exact="isExact"
:is="linkTag"