refactor backend and add UI

This commit is contained in:
ALau2088 2019-05-24 08:03:39 -07:00
parent c76e18fae3
commit 8a8ed5131e
6 changed files with 170 additions and 83 deletions

View File

@ -22,10 +22,29 @@ const validateUrl = async (resolve, root, args, context, info) => {
}
}
const validateComment = async (resolve, root, args, context, info) => {
const COMMENT_MIN_LENGTH = 1
const content = args.content.replace(/<(?:.|\n)*?>/gm, '').trim()
if (!args.content || content.length < COMMENT_MIN_LENGTH) {
throw new UserInputError(
`Comment must be at least ${COMMENT_MIN_LENGTH} character long!`
)
}
const NO_POST_ERR_MESSAGE = 'Comment cannot be created without a post!'
const { postId } = args
if (!postId) {
throw new UserInputError(NO_POST_ERR_MESSAGE)
}
return await resolve(root, args, context, info)
}
export default {
Mutation: {
CreateUser: validateUsername,
UpdateUser: validateUsername,
CreateSocialMedia: validateUrl
CreateSocialMedia: validateUrl,
CreateComment: validateComment,
UpdateComment: validateComment
}
}

View File

@ -1,13 +1,9 @@
import { neo4jgraphql } from 'neo4j-graphql-js'
import { UserInputError } from 'apollo-server'
const COMMENT_MIN_LENGTH = 1
const NO_POST_ERR_MESSAGE = 'Comment cannot be created without a post!'
export default {
Mutation: {
CreateComment: async (object, params, context, resolveInfo) => {
const content = params.content.replace(/<(?:.|\n)*?>/gm, '').trim()
const { postId } = params
// Adding relationship from comment to post by passing in the postId,
// but we do not want to create the comment with postId as an attribute
@ -15,15 +11,6 @@ export default {
// before comment creation.
delete params.postId
if (!params.content || content.length < COMMENT_MIN_LENGTH) {
throw new UserInputError(
`Comment must be at least ${COMMENT_MIN_LENGTH} character long!`
)
}
if (!postId.trim()) {
throw new UserInputError(NO_POST_ERR_MESSAGE)
}
const session = context.driver.session()
const postQueryRes = await session.run(
`
@ -65,38 +52,6 @@ export default {
return comment
},
UpdateComment: async (object, params, context, resolveInfo) => {
// Strip element tags and remove leading/trailing white spaces from content
const content = params.content.replace(/<(?:.|\n)*?>/gm, '').trim()
const { id } = params
// Check length of content
if (!params.content || content.length < COMMENT_MIN_LENGTH) {
throw new UserInputError(
`Comment must be at least ${COMMENT_MIN_LENGTH} character long!`
)
}
// Check if comment exists
const session = context.driver.session()
const commentQueryRes = await session.run(
`
MATCH (comment: Comment { id:$id})
RETURN comment`,
{
id
}
)
// Destructure content from session results array
const [comment] = commentQueryRes.records.map(record => {
return record.get('comment')
})
// Send error message if cannot find a matching comment.
if (!comment) {
throw new UserInputError(NO_COMMENT_ERR_MESSAGE)
}
// Update comment.
const commentRev = await neo4jgraphql(
object,
params,
@ -104,20 +59,6 @@ export default {
resolveInfo,
false
)
await session.run(
`
MATCH (comment: Comment { id:$id})
SET comment.content = $content
`,
{
id,
content
}
)
session.close()
return commentRev
}
}
}

View File

@ -22,15 +22,20 @@
:resource="comment"
style="float-right"
:is-owner="isAuthor(author.id)"
v-on:showEditCommentMenu="editCommentMenu"
/>
</no-ssr>
<!-- eslint-disable vue/no-v-html -->
<!-- TODO: replace editor content with tiptap render view -->
<ds-space margin-bottom="small" />
<div
style="padding-left: 40px;"
v-html="comment.contentExcerpt"
/>
<ds-space margin-bottom="small"/>
<div v-if="openEditCommentMenu">
<hc-edit-comment-form
v-bind:comment="comment"
v-bind:post="post"
v-on:showEditCommentMenu="editCommentMenu"
/>
</div>
<div v-else style="padding-left: 40px;" v-html="comment.contentExcerpt"/>
<!-- eslint-enable vue/no-v-html -->
</div>
</template>
@ -39,13 +44,22 @@
import { mapGetters } from 'vuex'
import HcUser from '~/components/User'
import ContentMenu from '~/components/ContentMenu'
import HcEditCommentForm from '~/components/comments/EditCommentForm'
import gql from 'graphql-tag'
export default {
components: {
HcUser,
ContentMenu
ContentMenu,
HcEditCommentForm
},
data() {
return {
openEditCommentMenu: false
}
},
props: {
post: { type: Object, default: () => {} },
comment: {
type: Object,
default() {
@ -69,6 +83,9 @@ export default {
methods: {
isAuthor(id) {
return this.user.id === id
},
editCommentMenu(showMenu) {
this.openEditCommentMenu = showMenu
}
}
}

View File

@ -90,7 +90,7 @@ export default {
name: this.$t(`comment.edit`),
callback: () => {
/* eslint-disable-next-line no-console */
console.log('EDIT COMMENT')
this.$emit('showEditCommentMenu', true)
},
icon: 'edit'
})

View File

@ -12,23 +12,11 @@
>{{ comments.length }}</ds-tag>&nbsp; Comments
</span>
</h3>
<ds-space margin-bottom="large" />
<div
v-if="comments && comments.length"
id="comments"
class="comments"
>
<comment
v-for="comment in comments"
:key="comment.id"
:comment="comment"
/>
<ds-space margin-bottom="large"/>
<div v-if="comments && comments.length" id="comments" class="comments">
<comment v-for="comment in comments" :key="comment.id" :comment="comment" :post="post"/>
</div>
<hc-empty
v-else
name="empty"
icon="messages"
/>
<hc-empty v-else name="empty" icon="messages"/>
</div>
</template>
<script>

View File

@ -0,0 +1,122 @@
<template>
<ds-form v-model="form" @submit="handleSubmit">
<template slot-scope="{ errors }">
<ds-card>
<!-- <no-ssr> -->
<hc-editor ref="editor" :users="users" :value="form.content" @input="updateEditorContent"/>
<!-- </no-ssr> -->
<ds-space/>
<ds-flex :gutter="{ base: 'small', md: 'small', sm: 'x-large', xs: 'x-large' }">
<ds-flex-item :width="{ base: '0%', md: '50%', sm: '0%', xs: '0%' }"/>
<ds-flex-item :width="{ base: '40%', md: '20%', sm: '30%', xs: '30%' }">
<ds-button
:disabled="disabled"
ghost
class="cancelBtn"
@click.prevent="closeEditWindow"
>{{ $t('actions.cancel') }}</ds-button>
</ds-flex-item>
<ds-flex-item :width="{ base: '40%', md: '20%', sm: '40%', xs: '40%' }">
<ds-button
type="submit"
:loading="loading"
:disabled="disabled || errors"
primary
>{{ $t('post.comment.submit') }}</ds-button>
</ds-flex-item>
</ds-flex>
</ds-card>
</template>
</ds-form>
</template>
<script>
import gql from 'graphql-tag'
import HcEditor from '~/components/Editor'
export default {
components: {
HcEditor
},
props: {
post: { type: Object, default: () => {} },
comments: { type: Array, default: () => [] },
comment: {
type: Object,
default() {
return {}
}
}
},
data() {
return {
disabled: false,
loading: false,
form: {
content: this.comment.contentExcerpt
},
users: []
}
},
methods: {
updateEditorContent(value) {
const content = value.replace(/<(?:.|\n)*?>/gm, '').trim()
if (content.length < 1) {
this.disabled = true
} else {
this.disabled = false
}
this.form.content = value
},
closeEditWindow() {
this.$emit('showEditCommentMenu', false)
},
handleSubmit() {
this.loading = true
this.disabled = true
this.$apollo
.mutate({
mutation: gql`
mutation($postId: ID, $content: String!, $id: ID!) {
UpdateComment(postId: $postId, content: $content, id: $id) {
id
content
}
}
`,
variables: {
postId: this.post.id,
content: this.form.content,
id: this.comment.id
}
})
.then(res => {
this.loading = false
this.$root.$emit('refetchPostComments')
this.$toast.success(this.$t('post.comment.submitted'))
this.disabled = false
this.$emit('showEditCommentMenu', false)
})
//@Todo close edit comment window
.catch(err => {
this.$toast.error(err.message)
})
}
},
apollo: {
User: {
query() {
return gql(`{
User(orderBy: slug_asc) {
id
slug
}
}`)
},
result(result) {
this.users = result.data.User
}
}
}
}
</script>