Robert Schäfer 72edf78889 Meld a chaotic commit history into one commit
Some important commit messages:

```
    Fix youtu.be not being embedded

    And also try to maintain the old behaviour matching
    `provider.provider_url`.
```

```
    Remove confusing code comments and obsolete code

    I discovered that the behaviour of no duplicate notifications being send
    out is caused by the frontend: When the editor reads html from the
    backend, it will parse hashtags and mentions as ordinary links, not as
    their respective nodes during editing. Also, we don't have to worry
    about duplicate ids being found: The cypher statement will implicitly
    suppress duplicate notification nodes for the same user.

    So let's remove the code to avoid confusing the next developer.
```

```
    Test editor.getHTML()

    I do this because I'm not able to test the content of `this.editor` from
    a wrapper of `vue-test-utils`. If I call `this.editor.getHTML` directly
    and use it as a computed property `renderedContent` to populate a `<div
    v-html="renderedContent" />` this will not work for the embeds. So, my
    current best bet is to test the editor object isolated from a real
    component. ;(
```

```
    Add core-js as explicit dependency

    Because of build errors on Travis.

    See: https://stackoverflow.com/a/55313456

    Remove as soon as this issue is resolved:
    https://github.com/storybookjs/storybook/issues/7591

```

```
    Refactor: Keep Runtime-only builds

    See: https://vuejs.org/v2/guide/installation.html#Runtime-Compiler-vs-Runtime-only
```
2019-08-01 00:28:22 +02:00

202 lines
5.1 KiB
Vue

<template>
<transition name="fade" appear>
<ds-card
v-if="post && ready"
:image="post.image | proxyApiUrl"
:class="{ 'post-card': true, 'disabled-content': post.disabled }"
>
<ds-space margin-bottom="small" />
<hc-user :user="post.author" :date-time="post.createdAt" />
<!-- Content Menu (can open Modals) -->
<no-ssr>
<content-menu
placement="bottom-end"
resource-type="contribution"
:resource="post"
:modalsData="menuModalsData"
:is-owner="isAuthor(post.author ? post.author.id : null)"
/>
</no-ssr>
<ds-space margin-bottom="small" />
<ds-heading tag="h3" no-margin>{{ post.title }}</ds-heading>
<ds-space margin-bottom="small" />
<content-viewer class="content" :content="post.content" />
<!-- eslint-enable vue/no-v-html -->
<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
v-if="post.author"
:disabled="isAuthor(post.author.id)"
:count="post.shoutedCount"
:is-shouted="post.shoutedByCurrentUser"
:post-id="post.id"
/>
<!-- Comments -->
<ds-section slot="footer">
<hc-comment-list :post="post" />
<ds-space margin-bottom="large" />
<hc-comment-form :post="post" />
</ds-section>
</ds-card>
</transition>
</template>
<script>
import ContentViewer from '~/components/Editor/ContentViewer'
import HcCategory from '~/components/Category'
import HcTag from '~/components/Tag'
import ContentMenu from '~/components/ContentMenu'
import HcUser from '~/components/User'
import HcShoutButton from '~/components/ShoutButton.vue'
import HcCommentForm from '~/components/comments/CommentForm'
import HcCommentList from '~/components/comments/CommentList'
import { postMenuModalsData, deletePostMutation } from '~/components/utils/PostHelpers'
import PostQuery from '~/graphql/PostQuery.js'
export default {
name: 'PostSlug',
transition: {
name: 'slide-up',
mode: 'out-in',
},
components: {
HcTag,
HcCategory,
HcUser,
HcShoutButton,
ContentMenu,
HcCommentForm,
HcCommentList,
ContentViewer,
},
head() {
return {
title: this.title,
}
},
data() {
return {
post: null,
ready: false,
title: 'loading',
}
},
watch: {
Post(post) {
this.post = post[0] || {}
this.title = this.post.title
},
},
async asyncData(context) {
const {
params,
error,
app: { apolloProvider, $i18n },
} = context
const client = apolloProvider.defaultClient
const query = PostQuery($i18n)
const variables = { slug: params.slug }
const {
data: { Post },
} = await client.query({ query, variables })
if (Post.length <= 0) {
// TODO: custom 404 error page with translations
const message = 'This post could not be found'
return error({ statusCode: 404, message })
}
const [post] = Post
return {
post,
title: post.title,
}
},
mounted() {
setTimeout(() => {
// NOTE: quick fix for jumping flexbox implementation
// will be fixed in a future update of the styleguide
this.ready = true
}, 50)
},
computed: {
menuModalsData() {
return postMenuModalsData(
// "this.post" may not always be defined at the beginning …
this.post ? this.$filters.truncate(this.post.title, 30) : '',
this.deletePostCallback,
)
},
},
methods: {
isAuthor(id) {
return this.$store.getters['auth/user'].id === id
},
async deletePostCallback() {
try {
await this.$apollo.mutate(deletePostMutation(this.post.id))
this.$toast.success(this.$t('delete.contribution.success'))
this.$router.history.push('/') // Redirect to index (main) page
} catch (err) {
this.$toast.error(err.message)
}
},
},
}
</script>
<style lang="scss">
.page-name-post-id-slug {
.content-menu {
float: right;
margin-right: -$space-x-small;
margin-top: -$space-large;
}
.post-card {
// max-width: 800px;
margin: auto;
.comments {
margin-top: $space-small;
.comment {
margin-top: $space-small;
position: relative;
}
}
.ds-card-image {
img {
max-height: 300px;
object-fit: cover;
object-position: center;
}
}
.ds-card-footer {
padding: 0;
.ds-section {
padding: $space-base;
}
}
}
}
</style>