Merge branch '2019/kw15/design_differences_post' of https://github.com/Human-Connection/Human-Connection into 2019/kw15/design_differences_post

This commit is contained in:
Wolfgang Huß 2019-04-10 16:23:58 +02:00
commit 12fff83f27
9 changed files with 199 additions and 49 deletions

View File

@ -0,0 +1,19 @@
<template>
<ds-tag>
<ds-icon
size="large"
:name="icon"
/>
{{ name }}
</ds-tag>
</template>
<script>
export default {
name: 'HcCategory',
props: {
icon: { type: String, required: true },
name: { type: String, required: true }
}
}
</script>

View File

@ -0,0 +1,7 @@
### Example
Relative time from 08.03.2017
```
<hc-relative-date-time dateTime="03.08.2017" />
```

View File

@ -0,0 +1,15 @@
import { shallowMount } from '@vue/test-utils'
import RelativeDateTime from './index.vue'
describe('RelativeDateTime', () => {
let wrapper
beforeEach(() => {
wrapper = shallowMount(RelativeDateTime, {})
})
it('renders', () => {
console.log(wrapper.html())
expect(wrapper.is('div')).toBe(true)
})
})

View File

@ -0,0 +1,69 @@
<template>
<span :title="absoluteTime">{{ relativeDateTime }}</span>
</template>
<script>
export default {
name: 'HcRelativeDateTime',
props: {
dateTime: {
type: [Date, String],
required: true
}
},
data() {
return {
relativeDateTime: null,
interval: 15000,
timeout: null,
absoluteTime: null
}
},
watch: {
locale() {
this.calcRelativeDateTime()
},
dateTime(dateTime) {
this.calcRelativeDateTime()
}
},
created() {
this.calcRelativeDateTime()
},
mounted() {
this.calcRelativeDateTime()
},
destroyed() {
clearTimeout(this.timeout)
},
methods: {
calcRelativeDateTime() {
// Reset Timer
clearTimeout(this.timeout)
// Calculate Relative Date
this.relativeDateTime = this.$filters.relativeDateTime(this.dateTime)
if (!process.browser) {
return
}
// TODO It is unclear what exactly this does and how to archive it
/*if (
this.relativeDateTime ===
t
.add(this.interval, 'milliseconds')
.utc()
.fromNow()
) {
this.interval += 15000
}*/
// Recalculate Timer
this.timeout = setTimeout(() => {
this.calcRelativeDateTime()
}, this.interval)
}
}
}
</script>

15
webapp/components/Tag.vue Normal file
View File

@ -0,0 +1,15 @@
<template>
<ds-tag>
<ds-icon name="tag" />
{{ name }}
</ds-tag>
</template>
<script>
export default {
name: 'HcTag',
props: {
name: { type: String, required: true }
}
}
</script>

View File

@ -1,6 +1,8 @@
<template> <template>
<div v-if="!user || ((user.disabled || user.deleted) && !isModerator)"> <div v-if="!user || ((user.disabled || user.deleted) && !isModerator)">
<div style="display: inline-block; float: left; margin-right: 4px; height: 100%; vertical-align: middle;"> <div
style="display: inline-block; float: left; margin-right: 4px; height: 100%; vertical-align: middle;"
>
<ds-avatar <ds-avatar
style="display: inline-block; vertical-align: middle;" style="display: inline-block; vertical-align: middle;"
size="32px" size="32px"
@ -10,9 +12,7 @@
<b <b
class="username" class="username"
style="vertical-align: middle;" style="vertical-align: middle;"
> >Anonymus</b>
Anonymus
</b>
</div> </div>
</div> </div>
<dropdown <dropdown
@ -33,7 +33,9 @@
@mouseover="openMenu(true)" @mouseover="openMenu(true)"
@mouseleave="closeMenu(true)" @mouseleave="closeMenu(true)"
> >
<div style="display: inline-block; float: left; margin-right: 4px; height: 100%; vertical-align: middle;"> <div
style="display: inline-block; float: left; margin-right: 4px; height: 100%; vertical-align: middle;"
>
<ds-avatar <ds-avatar
:image="user.avatar" :image="user.avatar"
:name="user.name" :name="user.name"
@ -45,16 +47,26 @@
<b <b
class="username" class="username"
style="vertical-align: middle;" style="vertical-align: middle;"
>{{ user.name | truncate(trunc, 18) }}</b>
</div>
<!-- Time -->
<div
v-if="dateTime"
style="display: inline;"
> >
{{ user.name | truncate(trunc, 18) }} <ds-text
</b> align="right"
size="small"
color="soft"
>
<ds-icon name="clock" />
<hc-relative-date-time :date-time="dateTime" />
</ds-text>
</div> </div>
</div> </div>
</nuxt-link> </nuxt-link>
</template> </template>
<template <template slot="popover">
slot="popover"
>
<div style="min-width: 250px"> <div style="min-width: 250px">
<hc-badges <hc-badges
v-if="user.badges && user.badges.length" v-if="user.badges && user.badges.length"
@ -68,11 +80,10 @@
style="margin-top: 5px" style="margin-top: 5px"
bold bold
> >
<ds-icon name="map-marker" /> {{ user.location.name }} <ds-icon name="map-marker" />
{{ user.location.name }}
</ds-text> </ds-text>
<ds-flex <ds-flex style="margin-top: -10px">
style="margin-top: -10px"
>
<ds-flex-item class="ds-tab-nav-item"> <ds-flex-item class="ds-tab-nav-item">
<ds-space margin="small"> <ds-space margin="small">
<ds-number <ds-number
@ -125,21 +136,25 @@
</template> </template>
<script> <script>
import { mapGetters } from 'vuex'
import HcRelativeDateTime from '~/components/RelativeDateTime'
import HcFollowButton from '~/components/FollowButton.vue' import HcFollowButton from '~/components/FollowButton.vue'
import HcBadges from '~/components/Badges.vue' import HcBadges from '~/components/Badges.vue'
import Dropdown from '~/components/Dropdown' import Dropdown from '~/components/Dropdown'
import { mapGetters } from 'vuex'
export default { export default {
name: 'HcUser', name: 'HcUser',
components: { components: {
HcRelativeDateTime,
HcFollowButton, HcFollowButton,
HcBadges, HcBadges,
Dropdown Dropdown
}, },
props: { props: {
user: { type: Object, default: null }, user: { type: Object, default: null },
trunc: { type: Number, default: null } trunc: { type: Number, default: null },
dateTime: { type: [Date, String], default: null }
}, },
computed: { computed: {
...mapGetters({ ...mapGetters({

View File

@ -6,10 +6,13 @@
<ds-card <ds-card
v-if="post && ready" v-if="post && ready"
:image="post.image" :image="post.image"
:header="post.title"
:class="{'post-card': true, 'disabled-content': post.disabled}" :class="{'post-card': true, 'disabled-content': post.disabled}"
> >
<hc-user :user="post.author" /> <ds-space margin-bottom="small" />
<hc-user
:user="post.author"
:date-time="post.createdAt"
/>
<no-ssr> <no-ssr>
<content-menu <content-menu
placement="bottom-end" placement="bottom-end"
@ -19,6 +22,13 @@
/> />
</no-ssr> </no-ssr>
<ds-space margin-bottom="small" /> <ds-space margin-bottom="small" />
<ds-heading
tag="h3"
no-margin
>
{{ post.title }}
</ds-heading>
<ds-space margin-bottom="small" />
<!-- Content --> <!-- Content -->
<!-- eslint-disable vue/no-v-html --> <!-- eslint-disable vue/no-v-html -->
<!-- TODO: replace editor content with tiptap render view --> <!-- TODO: replace editor content with tiptap render view -->
@ -26,19 +36,33 @@
class="content hc-editor-content" class="content hc-editor-content"
v-html="post.content" v-html="post.content"
/> />
<ds-space>
<ds-text
v-if="post.createdAt"
align="right"
size="small"
color="soft"
>
{{ post.createdAt | dateTime('dd. MMMM yyyy HH:mm') }}
</ds-text>
</ds-space>
<!-- eslint-enable vue/no-v-html --> <!-- eslint-enable vue/no-v-html -->
<!-- Shout Button -->
<ds-space margin="xx-large" /> <ds-space margin="xx-large" />
<!-- Categories -->
<div class="categories">
<ds-space margin="xx-small" />
<hc-category
v-for="category in post.categories"
:key="category.id"
v-tooltip="{content: category.name, placement: 'top-start', delay: { show: 300 }}"
:icon="category.icon"
:name="category.name"
/>
</div>
<ds-space margin-bottom="small" />
<!-- Tags -->
<div
v-if="post.tags && post.tags.length"
class="tags"
>
<ds-space margin="xx-small" />
<hc-tag
v-for="tag in post.tags"
:key="tag.id"
:name="tag.name"
/>
</div>
<!-- Shout Button -->
<hc-shout-button <hc-shout-button
v-if="post.author" v-if="post.author"
:disabled="isAuthor(post.author.id)" :disabled="isAuthor(post.author.id)"
@ -115,6 +139,9 @@
<script> <script>
import gql from 'graphql-tag' import gql from 'graphql-tag'
import HcCategory from '~/components/Category.vue'
import HcTag from '~/components/Tag.vue'
import ContentMenu from '~/components/ContentMenu' import ContentMenu from '~/components/ContentMenu'
import HcUser from '~/components/User.vue' import HcUser from '~/components/User.vue'
import HcShoutButton from '~/components/ShoutButton.vue' import HcShoutButton from '~/components/ShoutButton.vue'
@ -127,6 +154,8 @@ export default {
mode: 'out-in' mode: 'out-in'
}, },
components: { components: {
HcTag,
HcCategory,
HcUser, HcUser,
HcShoutButton, HcShoutButton,
HcEmpty, HcEmpty,

View File

@ -1368,11 +1368,6 @@
"@types/express-serve-static-core" "*" "@types/express-serve-static-core" "*"
"@types/mime" "*" "@types/mime" "*"
"@types/stack-utils@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw==
"@types/strip-bom@^3.0.0": "@types/strip-bom@^3.0.0":
version "3.0.0" version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/strip-bom/-/strip-bom-3.0.0.tgz#14a8ec3956c2e81edb7520790aecf21c290aebd2" resolved "https://registry.yarnpkg.com/@types/strip-bom/-/strip-bom-3.0.0.tgz#14a8ec3956c2e81edb7520790aecf21c290aebd2"
@ -6121,15 +6116,6 @@ jest-message-util@^24.7.1:
version "24.7.1" version "24.7.1"
resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.7.1.tgz#f1dc3a6c195647096a99d0f1dadbc447ae547018" resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.7.1.tgz#f1dc3a6c195647096a99d0f1dadbc447ae547018"
integrity sha512-dk0gqVtyqezCHbcbk60CdIf+8UHgD+lmRHifeH3JRcnAqh4nEyPytSc9/L1+cQyxC+ceaeP696N4ATe7L+omcg== integrity sha512-dk0gqVtyqezCHbcbk60CdIf+8UHgD+lmRHifeH3JRcnAqh4nEyPytSc9/L1+cQyxC+ceaeP696N4ATe7L+omcg==
dependencies:
"@babel/code-frame" "^7.0.0"
"@jest/test-result" "^24.7.1"
"@jest/types" "^24.7.0"
"@types/stack-utils" "^1.0.1"
chalk "^2.0.1"
micromatch "^3.1.10"
slash "^2.0.0"
stack-utils "^1.0.1"
jest-mock@^24.7.0: jest-mock@^24.7.0:
version "24.7.0" version "24.7.0"
@ -9810,11 +9796,6 @@ stack-trace@0.0.10:
resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=
stack-utils@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8"
integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==
stackframe@^1.0.4: stackframe@^1.0.4:
version "1.0.4" version "1.0.4"
resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.0.4.tgz#357b24a992f9427cba6b545d96a14ed2cbca187b" resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.0.4.tgz#357b24a992f9427cba6b545d96a14ed2cbca187b"