Set up UI
@ -154,6 +154,7 @@ const permissions = shield(
|
||||
User: or(noEmailFilter, isAdmin),
|
||||
isLoggedIn: allow,
|
||||
Badge: allow,
|
||||
postsEmotionsCountByEmotion: allow,
|
||||
},
|
||||
Mutation: {
|
||||
'*': deny,
|
||||
|
||||
@ -107,4 +107,22 @@ export default {
|
||||
return !emoted
|
||||
},
|
||||
},
|
||||
Query: {
|
||||
postsEmotionsCountByEmotion: async (object, params, context, resolveInfo) => {
|
||||
const session = context.driver.session()
|
||||
const { id, data } = params
|
||||
const transactionRes = await session.run(
|
||||
`MATCH (post:Post {id: $id})<-[emoted:EMOTED {emotion: $data.emotion}]-()
|
||||
RETURN COUNT(DISTINCT emoted) as emotionsCount
|
||||
`,
|
||||
{ id, data },
|
||||
)
|
||||
session.close()
|
||||
|
||||
const [emotionsCount] = transactionRes.records.map(record => {
|
||||
return record.get('emotionsCount').low
|
||||
})
|
||||
return emotionsCount
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -7,4 +7,4 @@ type EMOTED @relation(name: "EMOTED") {
|
||||
#updatedAt: DateTime
|
||||
createdAt: String
|
||||
updatedAt: String
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,3 +93,7 @@ type Mutation {
|
||||
): Post
|
||||
RemovePostEmotions(from: _UserInput!, to: _PostInput!, data: _EMOTEDInput!): Boolean!
|
||||
}
|
||||
|
||||
type Query {
|
||||
postsEmotionsCountByEmotion(id: ID!, data: _EMOTEDInput!): Int!
|
||||
}
|
||||
|
||||
126
webapp/components/EmotionsButtons/EmotionsButtons.vue
Normal file
@ -0,0 +1,126 @@
|
||||
<template>
|
||||
<ds-space margin="large" style="text-align: center">
|
||||
<ds-flex :gutter="{ lg: 'large' }" class="emotions-flex">
|
||||
<div v-for="emotion in emotionsList" :key="emotion">
|
||||
<ds-flex-item :width="{ lg: '100%' }">
|
||||
<ds-button
|
||||
:loading="loading"
|
||||
size="large"
|
||||
ghost
|
||||
@click="toggleEmotion(emotion)"
|
||||
class="emotions-buttons"
|
||||
>
|
||||
<img :src="iconPath(emotion)" alt width="53" />
|
||||
</ds-button>
|
||||
<ds-space margin-bottom="xx-small" />
|
||||
<div>
|
||||
<p class="emotions-label">{{ emotion }}</p>
|
||||
<p :key="postsEmotionsCountByEmotion[emotion.toLowerCase()]">
|
||||
{{ postsEmotionsCountByEmotion[emotion.toLowerCase()] }}
|
||||
</p>
|
||||
</div>
|
||||
</ds-flex-item>
|
||||
</div>
|
||||
</ds-flex>
|
||||
</ds-space>
|
||||
</template>
|
||||
<script>
|
||||
import gql from 'graphql-tag'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
post: { type: Object, default: () => {} },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
emotionsList: ['Funny', 'Happy', 'Surprised', 'Cry', 'Angry'],
|
||||
selectedEmotions: [],
|
||||
postsEmotionsCountByEmotion: {},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
currentUser: 'auth/user',
|
||||
}),
|
||||
},
|
||||
mounted() {
|
||||
this.emotionsList.map(emotion => {
|
||||
this.emotionsCount(emotion.toLowerCase())
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
iconPath(emotion) {
|
||||
if (this.isActive(emotion)) {
|
||||
return `/img/svg/emoji/${emotion.toLowerCase()}_color.svg`
|
||||
}
|
||||
return `/img/svg/emoji/${emotion.toLowerCase()}.svg`
|
||||
},
|
||||
toggleEmotion(emotion) {
|
||||
const index = this.selectedEmotions.indexOf(emotion)
|
||||
if (index > -1) {
|
||||
this.selectedEmotions.splice(index, 1)
|
||||
} else {
|
||||
this.selectedEmotions.push(emotion)
|
||||
}
|
||||
const addPostEmotionsMutation = gql`
|
||||
mutation($from: _UserInput!, $to: _PostInput!, $data: _EMOTEDInput!) {
|
||||
AddPostEmotions(from: $from, to: $to, data: $data) {
|
||||
emotion
|
||||
}
|
||||
}
|
||||
`
|
||||
const removePostEmotionsMutation = gql`
|
||||
mutation($from: _UserInput!, $to: _PostInput!, $data: _EMOTEDInput!) {
|
||||
RemovePostEmotions(from: $from, to: $to, data: $data)
|
||||
}
|
||||
`
|
||||
this.$apollo.mutate({
|
||||
mutation: this.isActive(emotion) ? addPostEmotionsMutation : removePostEmotionsMutation,
|
||||
variables: {
|
||||
from: { id: this.currentUser.id },
|
||||
to: { id: this.post.id },
|
||||
data: { emotion: emotion.toLowerCase() },
|
||||
},
|
||||
})
|
||||
},
|
||||
isActive(emotion) {
|
||||
const index = this.selectedEmotions.indexOf(emotion)
|
||||
if (index > -1) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
},
|
||||
emotionsCount(emotion) {
|
||||
this.$apollo
|
||||
.query({
|
||||
query: gql`
|
||||
query($id: ID!, $data: _EMOTEDInput!) {
|
||||
postsEmotionsCountByEmotion(id: $id, data: $data)
|
||||
}
|
||||
`,
|
||||
variables: { id: this.post.id, data: { emotion } },
|
||||
})
|
||||
.then(({ data: { postsEmotionsCountByEmotion } }) => {
|
||||
this.postsEmotionsCountByEmotion[emotion] = postsEmotionsCountByEmotion
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.emotions-flex {
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
.emotions-label {
|
||||
font-size: $font-size-small;
|
||||
}
|
||||
|
||||
.emotions-buttons {
|
||||
&:hover {
|
||||
background-color: $background-color-base;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -71,6 +71,7 @@ export default i18n => {
|
||||
}
|
||||
shoutedCount
|
||||
shoutedByCurrentUser
|
||||
emotionsCount
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
@ -43,14 +43,22 @@
|
||||
<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"
|
||||
/>
|
||||
<ds-flex :gutter="{ lg: 'small' }">
|
||||
<ds-flex-item :width="{ lg: '75%' }">
|
||||
<hc-emotions-buttons :post="post" />
|
||||
</ds-flex-item>
|
||||
<ds-flex-item :width="{ lg: '10%' }" />
|
||||
<!-- Shout Button -->
|
||||
<ds-flex-item :width="{ lg: '15%' }">
|
||||
<hc-shout-button
|
||||
v-if="post.author"
|
||||
:disabled="isAuthor(post.author.id)"
|
||||
:count="post.shoutedCount"
|
||||
:is-shouted="post.shoutedByCurrentUser"
|
||||
:post-id="post.id"
|
||||
/>
|
||||
</ds-flex-item>
|
||||
</ds-flex>
|
||||
<!-- Comments -->
|
||||
<ds-section slot="footer">
|
||||
<hc-comment-list :post="post" />
|
||||
@ -71,6 +79,7 @@ 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'
|
||||
import HcEmotionsButtons from '~/components/EmotionsButtons/EmotionsButtons'
|
||||
|
||||
export default {
|
||||
name: 'PostSlug',
|
||||
@ -86,6 +95,7 @@ export default {
|
||||
ContentMenu,
|
||||
HcCommentForm,
|
||||
HcCommentList,
|
||||
HcEmotionsButtons,
|
||||
},
|
||||
head() {
|
||||
return {
|
||||
|
||||
1
webapp/static/img/svg/emoji/angry.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80"><circle data-name="<Pfad>" cx="40" cy="40.1" r="40" fill="#cac9c9"/><ellipse data-name="<Pfad>" cx="38.4" cy="38.8" rx="37.4" ry="37.6" fill="#d7d8d8"/><path d="M39.8 55.6c8.8 0 13.4 7.7 13.4 11.6a.8.8 0 0 1-1 1s-5-6-12.4-6-12.4 6-12.4 6a.8.8 0 0 1-1-1c0-4 4.6-11.6 13.4-11.6z" fill="#303030"/><ellipse cx="26.4" cy="40.3" rx="4" ry="7.7" fill="#303030"/><ellipse cx="50.4" cy="39.9" rx="4" ry="7.7" fill="#303030"/><path d="M14.5 27.2s14.7-2 18.6 10c.2.3 0 .5-.4 0a22.8 22.8 0 0 0-18-6.8v-3.2zm47.5 0s-14.5-2-18.4 10c0 .3 0 .5.4 0a22.8 22.8 0 0 1 18.2-6.8v-3.2z" fill="#303030"/></svg>
|
||||
|
After Width: | Height: | Size: 658 B |
1
webapp/static/img/svg/emoji/angry_color.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80"><defs><radialGradient id="a" cx="37.4" cy="38.6" r="37.5" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#ed6c70" stop-opacity=".7"/><stop offset=".3" stop-color="#ed6c70" stop-opacity=".5"/><stop offset=".8" stop-color="#ed6c70" stop-opacity=".1"/><stop offset="1" stop-color="#ed6c70" stop-opacity="0"/></radialGradient><radialGradient id="b" cx="37.4" cy="38.6" r="37.5" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#fcea1c" stop-opacity=".2"/><stop offset=".8" stop-color="#fcea1c" stop-opacity=".1"/><stop offset="1" stop-color="#fcea1c" stop-opacity="0"/></radialGradient></defs><circle data-name="<Pfad>" cx="40" cy="40" r="40" fill="#dedc03"/><ellipse data-name="<Pfad>" cx="38.4" cy="38.7" rx="37.4" ry="37.6" fill="#fcea1c"/><ellipse data-name="<Pfad>" cx="37.4" cy="38.6" rx="37.4" ry="37.6" fill="url(#a)"/><ellipse data-name="<Pfad>" cx="37.4" cy="38.6" rx="37.4" ry="37.6" fill="url(#b)"/><ellipse cx="26.4" cy="40.2" rx="4" ry="7.7" fill="#303030"/><ellipse cx="50.4" cy="39.8" rx="4" ry="7.7" fill="#303030"/><path d="M14.5 27S29.2 25.3 33 37c.2.4 0 .6-.4 0a22.8 22.8 0 0 0-18-6.7V27zM62 27s-14.5-1.8-18.4 10c0 .4 0 .6.4 0a22.8 22.8 0 0 1 18.2-6.7V27zM39.8 55.5c8.8 0 13.4 7.7 13.4 11.6a.8.8 0 0 1-1 1s-5-6-12.4-6-12.4 6-12.4 6a.8.8 0 0 1-1-1c0-3.8 4.6-11.5 13.4-11.5z" fill="#303030"/></svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
1
webapp/static/img/svg/emoji/cry.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80"><circle data-name="<Pfad>" cx="40" cy="40" r="40" fill="#cbc9c9"/><ellipse data-name="<Pfad>" cx="38.5" cy="38.1" rx="37.4" ry="37.6" fill="#d7d7d7"/><path d="M15.8 24.5v3.2s10 1.3 12-11c0 0-6 8.8-12 7.8zm48.4 0v3.2s-10 1-12-11c0 0 6 9 12 7.8zm-23.8 27c13 0 18.4 7.7 18.4 11.6a2 2 0 0 1-2 2c-1 0-9-6-16.4-6S25 65 24 65a2 2 0 0 1-2-2c0-3.8 5.4-11.5 18.4-11.5z" fill="#303030"/><path d="M40.5 55a7.5 7.5 0 0 1 7.6 5.7 21 21 0 0 0-7.6-1.7 21.5 21.5 0 0 0-7.5 1.7 7.4 7.4 0 0 1 7.5-5.8z" fill="#ed6b70"/><path d="M35.6 42.2s-4.2-3-11.4-3-11.4 3-11.4 3S14.6 35 24.2 35s11.4 7 11.4 7zm32.4 0s-4-3-11.3-3-11.4 3-11.4 3S47 35 56.7 35 68 42 68 42z" fill="#303030"/><path d="M13.8 42.5v35c0 3.4 6 3.4 6 0v-35c0-3.7-6-3.7-6-.4v.5zm47.2 0v35c0 3.4 6 3.4 6 0v-35c0-3.7-6-3.7-6-.4v.5z" fill="#71caeb"/></svg>
|
||||
|
After Width: | Height: | Size: 866 B |
1
webapp/static/img/svg/emoji/cry_color.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80"><circle data-name="<Pfad>" cx="40" cy="40" r="40" fill="#dedc03"/><ellipse data-name="<Pfad>" cx="38.5" cy="38.2" rx="37.4" ry="37.6" fill="#fcea1c"/><path d="M15.8 24.5v3.3s10 1.2 12-11c0 0-6 8.8-12 7.7zm48.4 0v3.3s-10 1-12-11c0 0 6 8.8 12 7.7zm-23.8 27c13 0 18.4 7.7 18.4 11.6a2 2 0 0 1-2 2c-1 0-9-6-16.4-6S25 65 24 65a2 2 0 0 1-2-2c0-3.8 5.4-11.5 18.4-11.5z" fill="#303030"/><path d="M40.5 55a7.5 7.5 0 0 1 7.6 5.8 21 21 0 0 0-7.6-1.7A21.5 21.5 0 0 0 33 61a7.4 7.4 0 0 1 7.5-5.8z" fill="#ed6c70"/><path d="M35.6 42.2s-4.2-3-11.4-3-11.4 3-11.4 3S14.6 35 24.2 35s11.4 7.2 11.4 7.2zm32.4 0s-4-3-11.3-3-11.4 3-11.4 3S47 35 56.7 35 68 42.2 68 42.2z" fill="#303030"/><path d="M13.8 42.5v35c0 3.4 6 3.4 6 0v-35c0-3.6-6-3.6-6-.3v.3zm47.2 0v35c0 3.4 6 3.4 6 0v-35c0-3.6-6-3.6-6-.3v.3z" fill="#71caeb"/></svg>
|
||||
|
After Width: | Height: | Size: 874 B |
1
webapp/static/img/svg/emoji/funny.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80"><circle data-name="<Pfad>" cx="40.1" cy="40" r="40" fill="#cbc9c9"/><ellipse data-name="<Pfad>" cx="38.4" cy="38.6" rx="37.4" ry="37.6" fill="#d7d7d7"/><path d="M17.6 50h45.6s-3.7 19.6-22.8 19.6S17.6 50 17.6 50z" fill="#303030"/><path d="M40.4 59.8c8 0 9.8 7.8 9.8 7.8a22.6 22.6 0 0 1-9.8 2 22.7 22.7 0 0 1-9.7-2s1.5-7.8 9.7-7.8z" fill="#ed6b70"/><path d="M14.2 33.3s15-2.6 21.5 7.4A83.5 83.5 0 0 0 14.2 42c-10.3 2 4.6-4 14-3 0 0-.8-4-14-5.7zm51.6 0s-15-2.6-21.5 7.4A83.5 83.5 0 0 1 65.8 42c10.3 2-4.6-4-14-3 0 0 1-4 14-5.7z" fill="#303030"/></svg>
|
||||
|
After Width: | Height: | Size: 620 B |
1
webapp/static/img/svg/emoji/funny_color.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80"><circle data-name="<Pfad>" cx="40.1" cy="40" r="40" fill="#dedc03"/><ellipse data-name="<Pfad>" cx="38.4" cy="38.7" rx="37.4" ry="37.6" fill="#fcea1c"/><path d="M17.6 50h45.6s-3.7 19.7-22.8 19.7S17.6 50 17.6 50z" fill="#303030"/><path d="M40.4 60c8 0 9.8 7.6 9.8 7.6a22.6 22.6 0 0 1-9.8 2 22.7 22.7 0 0 1-9.7-2s1.5-7.7 9.7-7.7z" fill="#ed6b70"/><path d="M14.2 33.4s15-2.6 21.5 7.3A83.5 83.5 0 0 0 14.2 42c-10.3 2 4.6-4 14-3 0 0-.8-4-14-5.6zm51.6 0s-15-2.6-21.5 7.3A83.5 83.5 0 0 1 65.8 42c10.3 2-4.6-4-14-3 0 0 1-4 14-5.6z" fill="#303030"/></svg>
|
||||
|
After Width: | Height: | Size: 618 B |
1
webapp/static/img/svg/emoji/happy.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80"><circle data-name="<Pfad>" cx="40" cy="40" r="40" fill="#cbc9c9"/><ellipse data-name="<Pfad>" cx="38.4" cy="38.6" rx="37.4" ry="37.6" fill="#d7d7d7"/><ellipse cx="55.8" cy="39" rx="4" ry="7.7" fill="#303030"/><ellipse cx="24.1" cy="39" rx="4" ry="7.7" fill="#303030"/><ellipse cx="24.1" cy="45.9" rx="5.7" ry=".8" fill="#303030"/><ellipse cx="55.8" cy="45.9" rx="5.7" ry=".8" fill="#303030"/><path d="M17.5 55s8.3 4 22.8 4S63 55 63 55s-3.6 14.6-22.7 14.6S17.5 55 17.5 55z" fill="#303030"/><path d="M40.3 62.8c8 0 9.4 5.4 9.2 5.5a28.8 28.8 0 0 1-9.2 1.3 28.8 28.8 0 0 1-9.2-1.3s1-5.5 9.3-5.5z" fill="#ed6b70"/></svg>
|
||||
|
After Width: | Height: | Size: 687 B |
1
webapp/static/img/svg/emoji/happy_color.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80"><circle data-name="<Pfad>" cx="40" cy="40" r="40" fill="#dedc03"/><ellipse data-name="<Pfad>" cx="38.4" cy="38.7" rx="37.4" ry="37.6" fill="#fcea1c"/><ellipse cx="55.8" cy="39" rx="4" ry="7.7" fill="#303030"/><ellipse cx="24.1" cy="39" rx="4" ry="7.7" fill="#303030"/><ellipse cx="24.1" cy="45.9" rx="5.7" ry=".8" fill="#303030"/><ellipse cx="55.8" cy="45.9" rx="5.7" ry=".8" fill="#303030"/><path d="M17.5 55s8.3 4 22.8 4S63 55 63 55s-3.6 14.7-22.7 14.7S17.5 55 17.5 55z" fill="#303030"/><path d="M40.3 63c8 0 9.4 5.3 9.2 5.3a28.8 28.8 0 0 1-9.2 1.4 28.8 28.8 0 0 1-9.2-1.4s1-5.4 9.3-5.4z" fill="#ed6b70"/></svg>
|
||||
|
After Width: | Height: | Size: 685 B |
1
webapp/static/img/svg/emoji/surprised.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg id="new" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80"><style></style><circle id="XMLID_40_" cx="40" cy="40" r="40" fill="#cac9c9"/><ellipse id="XMLID_39_" cx="38.4" cy="38.7" rx="37.4" ry="37.6" fill="#d7d8d8"/><ellipse id="Oval" fill="#303030" cx="55.8" cy="39" rx="4" ry="7.7"/><ellipse id="Oval" fill="#303030" cx="24.1" cy="39" rx="4" ry="7.7"/><path d="M45 61.4c0-2.3-1.2-4.4-6-4.4-5 0-6 2.2-6 4.4 0 2.3 1 6.6 6 6.6 4.8 0 6-4.4 6-6.6zM51.1 19L50 16s8.9-4.6 15 6c0 0-8.6-6.1-13.9-3zM26.4 18.4l.6-3.1S17 12.6 13 24c0 0 7.5-7.6 13.4-5.6z" id="Path" fill="#303030"/></svg>
|
||||
|
After Width: | Height: | Size: 588 B |
1
webapp/static/img/svg/emoji/surprised_color.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg id="new" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 80 80"><style></style><circle id="XMLID_40_" cx="40" cy="40" r="40" fill="#dedc03"/><ellipse id="XMLID_39_" cx="38.4" cy="38.7" rx="37.4" ry="37.6" fill="#fcea1c"/><ellipse id="Oval" fill="#303030" cx="55.8" cy="39" rx="4" ry="7.7"/><ellipse id="Oval" fill="#303030" cx="24.1" cy="39" rx="4" ry="7.7"/><path d="M45 61.4c0-2.3-1.2-4.4-6-4.4-5 0-6 2.2-6 4.4 0 2.3 1 6.6 6 6.6 4.8 0 6-4.4 6-6.6zM51.1 19L50 16s8.9-4.6 15 6c0 0-8.6-6.1-13.9-3zM26.4 18.4l.6-3.1S17 12.6 13 24c0 0 7.5-7.6 13.4-5.6z" id="Path" fill="#303030"/></svg>
|
||||
|
After Width: | Height: | Size: 588 B |