From d4ce1ef80baac3e91f7e3864e5b920f812909c85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Fri, 12 Apr 2019 16:00:44 +0200 Subject: [PATCH 01/66] Localized HC link on Login page --- webapp/locales/de.json | 1 + webapp/locales/en.json | 1 + webapp/pages/login.vue | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/webapp/locales/de.json b/webapp/locales/de.json index 6e47d7122..ef9600c0e 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -6,6 +6,7 @@ "email": "Deine E-Mail", "password": "Dein Passwort", "moreInfo": "Was ist Human Connection?", + "moreInfoHint": "zur Präsentationsseite", "hello": "Hallo" }, "profile": { diff --git a/webapp/locales/en.json b/webapp/locales/en.json index 62c8f3e19..7c0b747c8 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -6,6 +6,7 @@ "email": "Your Email", "password": "Your Password", "moreInfo": "What is Human Connection?", + "moreInfoHint": "to the presentation page", "hello": "Hello" }, "profile": { diff --git a/webapp/pages/login.vue b/webapp/pages/login.vue index 846191c40..be2215fab 100644 --- a/webapp/pages/login.vue +++ b/webapp/pages/login.vue @@ -80,7 +80,7 @@ {{ $t('login.moreInfo') }} From 26be224464771b835fe062f9e3eddc0119d82f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Fri, 12 Apr 2019 16:08:39 +0200 Subject: [PATCH 02/66] Localised HC URL on Login page --- webapp/locales/de.json | 1 + webapp/locales/en.json | 1 + webapp/pages/login.vue | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/webapp/locales/de.json b/webapp/locales/de.json index ef9600c0e..43885ea17 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -6,6 +6,7 @@ "email": "Deine E-Mail", "password": "Dein Passwort", "moreInfo": "Was ist Human Connection?", + "moreInfoURL": "https://human-connection.org", "moreInfoHint": "zur Präsentationsseite", "hello": "Hallo" }, diff --git a/webapp/locales/en.json b/webapp/locales/en.json index 7c0b747c8..9ea58225f 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -6,6 +6,7 @@ "email": "Your Email", "password": "Your Password", "moreInfo": "What is Human Connection?", + "moreInfoURL": "https://human-connection.org/en/", "moreInfoHint": "to the presentation page", "hello": "Hello" }, diff --git a/webapp/pages/login.vue b/webapp/pages/login.vue index be2215fab..92269143b 100644 --- a/webapp/pages/login.vue +++ b/webapp/pages/login.vue @@ -79,7 +79,7 @@ From 674cdddfc3365fa91a6ced93f030be1840a9b2c8 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Tue, 16 Apr 2019 13:45:07 -0300 Subject: [PATCH 03/66] Add Editor, cancel/submit buttons for comments - to PagesPost_id_slugIndex.vue - handle simple comment creation using auto-generated resolver Co-authored-by: Joseph "Kachulio" Ngugi --- webapp/locales/en.json | 3 +- webapp/pages/post/_id/_slug/index.vue | 105 +++++++++++++++++++------- 2 files changed, 79 insertions(+), 29 deletions(-) diff --git a/webapp/locales/en.json b/webapp/locales/en.json index 40cc766d0..a6ceae9c9 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -106,7 +106,8 @@ }, "takeAction": { "name": "Take action" - } + }, + "submitComment": "Submit Comment" }, "quotes": { "african": { diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue index b72faa850..8af07bc26 100644 --- a/webapp/pages/post/_id/_slug/index.vue +++ b/webapp/pages/post/_id/_slug/index.vue @@ -96,34 +96,67 @@ -

- - - {{ post.commentsCount }}  Comments - -

- -
- + +

+ + + {{ post.commentsCount }}  Comments + +

+
+ + + + + + + + {{ $t('actions.cancel') }} + + + + + {{ $t('post.submitComment') }} + + + + + +
+ +
+ -
- +
@@ -139,6 +172,7 @@ import HcUser from '~/components/User' import HcShoutButton from '~/components/ShoutButton.vue' import HcEmpty from '~/components/Empty.vue' import Comment from '~/components/Comment.vue' +import HcEditor from '~/components/Editor/Editor.vue' export default { transition: { @@ -152,7 +186,8 @@ export default { HcShoutButton, HcEmpty, Comment, - ContentMenu + ContentMenu, + HcEditor }, head() { return { @@ -278,6 +313,20 @@ export default { methods: { isAuthor(id) { return this.$store.getters['auth/user'].id === id + }, + handleSubmit() { + this.$apollo.mutate({ + mutation: gql` + mutation($content: String!) { + CreateComment(content: $content) { + content + } + } + `, + variables: { + content: this.value + } + }) } } } From dfef4fe05fa74bad1ea8e2c91ffb1681538c3e42 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Tue, 16 Apr 2019 19:48:59 -0300 Subject: [PATCH 04/66] Add custom resolver, update factories --- backend/src/graphql-schema.js | 4 +++- backend/src/resolvers/comments.js | 28 ++++++++++++++++++++++++++ backend/src/resolvers/socialMedia.js | 2 +- backend/src/schema.graphql | 1 + backend/src/seed/factories/comments.js | 12 +++++------ 5 files changed, 38 insertions(+), 9 deletions(-) create mode 100644 backend/src/resolvers/comments.js diff --git a/backend/src/graphql-schema.js b/backend/src/graphql-schema.js index 1e13c95f4..7befd0507 100644 --- a/backend/src/graphql-schema.js +++ b/backend/src/graphql-schema.js @@ -9,6 +9,7 @@ import moderation from './resolvers/moderation.js' import rewards from './resolvers/rewards.js' import socialMedia from './resolvers/socialMedia.js' import notifications from './resolvers/notifications' +import comments from './resolvers/comments' export const typeDefs = fs .readFileSync( @@ -29,6 +30,7 @@ export const resolvers = { ...moderation.Mutation, ...rewards.Mutation, ...socialMedia.Mutation, - ...notifications.Mutation + ...notifications.Mutation, + ...comments.Mutation } } diff --git a/backend/src/resolvers/comments.js b/backend/src/resolvers/comments.js new file mode 100644 index 000000000..74454322d --- /dev/null +++ b/backend/src/resolvers/comments.js @@ -0,0 +1,28 @@ +import { neo4jgraphql } from 'neo4j-graphql-js' + +export default { + Mutation: { + CreateComment: async (object, params, context, resolveInfo) => { + const { postId } = params + + const result = await neo4jgraphql(object, params, context, resolveInfo, true) + + const session = context.driver.session() + const transactionRes = await session.run(` + MATCH (post:Post {id: $postId}), (comment:Comment {id: $commentId}) + MERGE (post)<-[:COMMENTS]-(comment) + RETURN comment {.id, .content}`, { + postId, + commentId: result.id + } + ) + const [comment] = transactionRes.records.map(record => { + return record.get('comment') + }) + + session.close() + + return comment + } + } +} diff --git a/backend/src/resolvers/socialMedia.js b/backend/src/resolvers/socialMedia.js index 3adf0e2d0..310375820 100644 --- a/backend/src/resolvers/socialMedia.js +++ b/backend/src/resolvers/socialMedia.js @@ -3,7 +3,7 @@ import { neo4jgraphql } from 'neo4j-graphql-js' export default { Mutation: { CreateSocialMedia: async (object, params, context, resolveInfo) => { - const socialMedia = await neo4jgraphql(object, params, context, resolveInfo, true) + const socialMedia = await neo4jgraphql(object, params, context, resolveInfo, false) const session = context.driver.session() await session.run( `MATCH (owner:User {id: $userId}), (socialMedia:SocialMedia {id: $socialMediaId}) diff --git a/backend/src/schema.graphql b/backend/src/schema.graphql index 94e28d0d7..6c35e082d 100644 --- a/backend/src/schema.graphql +++ b/backend/src/schema.graphql @@ -27,6 +27,7 @@ type Mutation { enable(id: ID!): ID reward(fromBadgeId: ID!, toUserId: ID!): ID unreward(fromBadgeId: ID!, toUserId: ID!): ID + CreateComment(id: ID!, postId: ID!, content: String!) : Comment "Shout the given Type and ID" shout(id: ID!, type: ShoutTypeEnum): Boolean! @cypher(statement: """ MATCH (n {id: $id})<-[:WROTE]-(wu:User), (u:User {id: $cypherParams.currentUserId}) diff --git a/backend/src/seed/factories/comments.js b/backend/src/seed/factories/comments.js index 92dca5b14..29d0722b7 100644 --- a/backend/src/seed/factories/comments.js +++ b/backend/src/seed/factories/comments.js @@ -4,22 +4,20 @@ import uuid from 'uuid/v4' export default function (params) { const { id = uuid(), + postId = uuid(), content = [ faker.lorem.sentence(), faker.lorem.sentence() - ].join('. '), - disabled = false, - deleted = false + ].join('. ') } = params return ` mutation { CreateComment( id: "${id}", - content: "${content}", - disabled: ${disabled}, - deleted: ${deleted} - ) { id } + postId: "${postId}", + content: "${content}" + ) { id, content } } ` } From 9bc0c0f92cb95b6b0b7a86eac090ba98d76c1c31 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Tue, 16 Apr 2019 20:31:34 -0300 Subject: [PATCH 05/66] Add tests, create comments only when authenticated --- .../src/middleware/permissionsMiddleware.js | 3 +- backend/src/resolvers/comments.js | 7 +- backend/src/resolvers/comments.spec.js | 64 +++++++++++++++++++ 3 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 backend/src/resolvers/comments.spec.js diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index 3ac43a6e2..3688aec16 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -86,7 +86,8 @@ const permissions = shield({ unshout: isAuthenticated, changePassword: isAuthenticated, enable: isModerator, - disable: isModerator + disable: isModerator, + CreateComment: isAuthenticated // CreateUser: allow, }, User: { diff --git a/backend/src/resolvers/comments.js b/backend/src/resolvers/comments.js index 74454322d..5ab20cf46 100644 --- a/backend/src/resolvers/comments.js +++ b/backend/src/resolvers/comments.js @@ -5,7 +5,7 @@ export default { CreateComment: async (object, params, context, resolveInfo) => { const { postId } = params - const result = await neo4jgraphql(object, params, context, resolveInfo, true) + const comment = await neo4jgraphql(object, params, context, resolveInfo, true) const session = context.driver.session() const transactionRes = await session.run(` @@ -13,12 +13,9 @@ export default { MERGE (post)<-[:COMMENTS]-(comment) RETURN comment {.id, .content}`, { postId, - commentId: result.id + commentId: comment.id } ) - const [comment] = transactionRes.records.map(record => { - return record.get('comment') - }) session.close() diff --git a/backend/src/resolvers/comments.spec.js b/backend/src/resolvers/comments.spec.js new file mode 100644 index 000000000..e17f94ec9 --- /dev/null +++ b/backend/src/resolvers/comments.spec.js @@ -0,0 +1,64 @@ +import Factory from '../seed/factories' +import { GraphQLClient } from 'graphql-request' +import { host, login } from '../jest/helpers' + +const factory = Factory() +let client +let variables + +beforeEach(async () => { + await factory.create('User', { + email: 'test@example.org', + password: '1234' + }) +}) + +afterEach(async () => { + await factory.cleanDatabase() +}) + +describe('CreateComment', () => { + const mutation = ` + mutation($id: ID!, $postId: ID!, $content: String!) { + CreateComment(id: $id, postId: $postId, content: $content) { + id + content + } + } + ` + describe('unauthenticated', () => { + it('throws authorization error', async () => { + variables = { + id: 'c1', + postId: 'p1', + content: "I'm not authorised to comment" + } + client = new GraphQLClient(host) + await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised') + }) + }) + + describe('authenticated', () => { + let headers + beforeEach(async () => { + headers = await login({ email: 'test@example.org', password: '1234' }) + client = new GraphQLClient(host, { headers }) + }) + + it('creates a post', async () => { + variables = { + id: 'c1', + postId: 'p1', + content: "I'm authorised to comment" + } + const expected = { + CreateComment: { + id: 'c1', + content: "I'm authorised to comment" + } + } + + await expect(client.request(mutation, variables)).resolves.toMatchObject(expected) + }) + }) +}) \ No newline at end of file From dd9383ef40fab2b4b616cde39e5e5bca4c1c72d0 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Tue, 16 Apr 2019 23:02:57 -0300 Subject: [PATCH 06/66] Create two custom resolvers, get working with front end - Had difficulty adding a relationship with one custom resolver, if id for comment was not passed in, the comment was not created, hard coding it in also wasn't a good solution --- backend/src/resolvers/comments.js | 23 ++----- backend/src/resolvers/comments.spec.js | 12 ++-- backend/src/schema.graphql | 1 - backend/src/seed/factories/comments.js | 2 - webapp/graphql/AddPostComments.js | 18 ++++++ webapp/pages/post/_id/_slug/index.vue | 90 +++++++++++++++++--------- 6 files changed, 89 insertions(+), 57 deletions(-) create mode 100644 webapp/graphql/AddPostComments.js diff --git a/backend/src/resolvers/comments.js b/backend/src/resolvers/comments.js index 5ab20cf46..4542c075a 100644 --- a/backend/src/resolvers/comments.js +++ b/backend/src/resolvers/comments.js @@ -2,24 +2,11 @@ import { neo4jgraphql } from 'neo4j-graphql-js' export default { Mutation: { - CreateComment: async (object, params, context, resolveInfo) => { - const { postId } = params - - const comment = await neo4jgraphql(object, params, context, resolveInfo, true) - - const session = context.driver.session() - const transactionRes = await session.run(` - MATCH (post:Post {id: $postId}), (comment:Comment {id: $commentId}) - MERGE (post)<-[:COMMENTS]-(comment) - RETURN comment {.id, .content}`, { - postId, - commentId: comment.id - } - ) - - session.close() - - return comment + CreateComment: (object, params, context, resolveInfo) => { + return neo4jgraphql(object, params, context, resolveInfo, false) + }, + AddPostComments: (object, params, context, resolveInfo) => { + return neo4jgraphql(object, params, context, resolveInfo, false) } } } diff --git a/backend/src/resolvers/comments.spec.js b/backend/src/resolvers/comments.spec.js index e17f94ec9..2fcd7245f 100644 --- a/backend/src/resolvers/comments.spec.js +++ b/backend/src/resolvers/comments.spec.js @@ -19,8 +19,8 @@ afterEach(async () => { describe('CreateComment', () => { const mutation = ` - mutation($id: ID!, $postId: ID!, $content: String!) { - CreateComment(id: $id, postId: $postId, content: $content) { + mutation($id: ID!, $content: String!) { + CreateComment(id: $id, content: $content) { id content } @@ -29,8 +29,7 @@ describe('CreateComment', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { variables = { - id: 'c1', - postId: 'p1', + id: 'c1', content: "I'm not authorised to comment" } client = new GraphQLClient(host) @@ -46,9 +45,8 @@ describe('CreateComment', () => { }) it('creates a post', async () => { - variables = { - id: 'c1', - postId: 'p1', + variables = { + id: 'c1', content: "I'm authorised to comment" } const expected = { diff --git a/backend/src/schema.graphql b/backend/src/schema.graphql index 6c35e082d..94e28d0d7 100644 --- a/backend/src/schema.graphql +++ b/backend/src/schema.graphql @@ -27,7 +27,6 @@ type Mutation { enable(id: ID!): ID reward(fromBadgeId: ID!, toUserId: ID!): ID unreward(fromBadgeId: ID!, toUserId: ID!): ID - CreateComment(id: ID!, postId: ID!, content: String!) : Comment "Shout the given Type and ID" shout(id: ID!, type: ShoutTypeEnum): Boolean! @cypher(statement: """ MATCH (n {id: $id})<-[:WROTE]-(wu:User), (u:User {id: $cypherParams.currentUserId}) diff --git a/backend/src/seed/factories/comments.js b/backend/src/seed/factories/comments.js index 29d0722b7..b6ada7ac9 100644 --- a/backend/src/seed/factories/comments.js +++ b/backend/src/seed/factories/comments.js @@ -4,7 +4,6 @@ import uuid from 'uuid/v4' export default function (params) { const { id = uuid(), - postId = uuid(), content = [ faker.lorem.sentence(), faker.lorem.sentence() @@ -15,7 +14,6 @@ export default function (params) { mutation { CreateComment( id: "${id}", - postId: "${postId}", content: "${content}" ) { id, content } } diff --git a/webapp/graphql/AddPostComments.js b/webapp/graphql/AddPostComments.js new file mode 100644 index 000000000..ab9ef8ca5 --- /dev/null +++ b/webapp/graphql/AddPostComments.js @@ -0,0 +1,18 @@ +import gql from 'graphql-tag' + +export default app => { + return { + AddPostComments: gql(` + mutation($from: _CommentInput!, $to: _PostInput!) { + AddPostComments(from: $from, to: $to) { + from { + id + } + to { + id + } + } + } + `) + } +} diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue index 8af07bc26..ef1121031 100644 --- a/webapp/pages/post/_id/_slug/index.vue +++ b/webapp/pages/post/_id/_slug/index.vue @@ -117,11 +117,11 @@ v-model="value" /> + - + {{ $t('actions.cancel') }} @@ -140,23 +140,23 @@ - -
- -
- + +
+ +
+ @@ -198,7 +198,9 @@ export default { return { post: null, ready: false, - title: 'loading' + title: 'loading', + loading: false, + disabled: false } }, watch: { @@ -315,18 +317,48 @@ export default { return this.$store.getters['auth/user'].id === id }, handleSubmit() { - this.$apollo.mutate({ - mutation: gql` - mutation($content: String!) { - CreateComment(content: $content) { - content + this.loading = true + this.$apollo + .mutate({ + mutation: gql` + mutation($content: String!) { + CreateComment(content: $content) { + id + content + } } + `, + variables: { + content: this.value } - `, - variables: { - content: this.value - } - }) + }) + .then(res => { + this.disabled = true + this.loading = false + const { id } = res.data.CreateComment + const commentId = { id: id } + const postId = { id: this.post.id } + const AddPostComments = require('~/graphql/AddPostComments.js').default( + this + ) + + this.$apollo + .mutate({ + mutation: AddPostComments.AddPostComments, + variables: { + from: commentId, + to: postId + } + }) + .then(res => { + this.$toast.success('Saved!') + }) + }) + .catch(err => { + this.$toast.error(err.message) + this.loading = false + this.disabled = false + }) } } } From c519bff74340e3381f017dfc20ff638e5e3aabe5 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Tue, 16 Apr 2019 23:37:11 -0300 Subject: [PATCH 07/66] Fix lint --- backend/src/resolvers/comments.spec.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/src/resolvers/comments.spec.js b/backend/src/resolvers/comments.spec.js index 2fcd7245f..a70dfd974 100644 --- a/backend/src/resolvers/comments.spec.js +++ b/backend/src/resolvers/comments.spec.js @@ -28,9 +28,9 @@ describe('CreateComment', () => { ` describe('unauthenticated', () => { it('throws authorization error', async () => { - variables = { + variables = { id: 'c1', - content: "I'm not authorised to comment" + content: 'I\'m not authorised to comment' } client = new GraphQLClient(host) await expect(client.request(mutation, variables)).rejects.toThrow('Not Authorised') @@ -47,16 +47,16 @@ describe('CreateComment', () => { it('creates a post', async () => { variables = { id: 'c1', - content: "I'm authorised to comment" + content: 'I\'m authorised to comment' } const expected = { CreateComment: { id: 'c1', - content: "I'm authorised to comment" + content: 'I\'m authorised to comment' } } - + await expect(client.request(mutation, variables)).resolves.toMatchObject(expected) }) }) -}) \ No newline at end of file +}) From f46e5ee58c69095a8421ac3e8eb803715b6cd58d Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Wed, 17 Apr 2019 10:18:39 -0300 Subject: [PATCH 08/66] Use custom resolver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - add postId to type Comment - remove it from params to create node without postId - fix tests Co-authored-by: Robert Schäfer Co-Authored-By: Tirokk Co-Authored-By: Mike Aono --- backend/src/resolvers/comments.js | 23 ++++++++++++++++++----- backend/src/resolvers/comments.spec.js | 9 ++++----- backend/src/schema.graphql | 1 + 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/backend/src/resolvers/comments.js b/backend/src/resolvers/comments.js index 4542c075a..5709b52e1 100644 --- a/backend/src/resolvers/comments.js +++ b/backend/src/resolvers/comments.js @@ -2,11 +2,24 @@ import { neo4jgraphql } from 'neo4j-graphql-js' export default { Mutation: { - CreateComment: (object, params, context, resolveInfo) => { - return neo4jgraphql(object, params, context, resolveInfo, false) - }, - AddPostComments: (object, params, context, resolveInfo) => { - return neo4jgraphql(object, params, context, resolveInfo, false) + CreateComment: async (object, params, context, resolveInfo) => { + const { postId } = params + delete params.postId + const comment = await neo4jgraphql(object, params, context, resolveInfo, true) + + const session = context.driver.session() + + const transactionRes = await session.run(` + MATCH (post:Post {id: $postId}), (comment:Comment {id: $commentId}) + MERGE (post)<-[:COMMENTS]-(comment) + RETURN comment {.id, .content}`, { + postId, + commentId: comment.id + } + ) + session.close() + + return comment } } } diff --git a/backend/src/resolvers/comments.spec.js b/backend/src/resolvers/comments.spec.js index a70dfd974..9918038a7 100644 --- a/backend/src/resolvers/comments.spec.js +++ b/backend/src/resolvers/comments.spec.js @@ -19,8 +19,8 @@ afterEach(async () => { describe('CreateComment', () => { const mutation = ` - mutation($id: ID!, $content: String!) { - CreateComment(id: $id, content: $content) { + mutation($postId: ID, $content: String!) { + CreateComment(postId: $postId, content: $content) { id content } @@ -29,7 +29,7 @@ describe('CreateComment', () => { describe('unauthenticated', () => { it('throws authorization error', async () => { variables = { - id: 'c1', + postId: 'p1', content: 'I\'m not authorised to comment' } client = new GraphQLClient(host) @@ -46,12 +46,11 @@ describe('CreateComment', () => { it('creates a post', async () => { variables = { - id: 'c1', + postId: 'p1', content: 'I\'m authorised to comment' } const expected = { CreateComment: { - id: 'c1', content: 'I\'m authorised to comment' } } diff --git a/backend/src/schema.graphql b/backend/src/schema.graphql index ff8b04dfc..99bcd4533 100644 --- a/backend/src/schema.graphql +++ b/backend/src/schema.graphql @@ -210,6 +210,7 @@ type Post { type Comment { id: ID! activityId: String + postId: ID author: User @relation(name: "WROTE", direction: "IN") content: String! contentExcerpt: String From 4dc39a97a87d09bc3f3a26f5d464f692bb82e172 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Wed, 17 Apr 2019 12:51:30 -0300 Subject: [PATCH 09/66] Fix seeds --- backend/src/seed/factories/comments.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/seed/factories/comments.js b/backend/src/seed/factories/comments.js index b6ada7ac9..2a131d0d9 100644 --- a/backend/src/seed/factories/comments.js +++ b/backend/src/seed/factories/comments.js @@ -3,7 +3,7 @@ import uuid from 'uuid/v4' export default function (params) { const { - id = uuid(), + postId = 'p6', content = [ faker.lorem.sentence(), faker.lorem.sentence() @@ -13,7 +13,7 @@ export default function (params) { return ` mutation { CreateComment( - id: "${id}", + postId: "${postId}", content: "${content}" ) { id, content } } From 86d075292c332e383d171236ebe3050746eab625 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Wed, 17 Apr 2019 12:51:50 -0300 Subject: [PATCH 10/66] Update frontend - to work with new backend implementation --- webapp/graphql/AddPostComments.js | 18 ------------------ webapp/pages/post/_id/_slug/index.vue | 24 ++++-------------------- 2 files changed, 4 insertions(+), 38 deletions(-) delete mode 100644 webapp/graphql/AddPostComments.js diff --git a/webapp/graphql/AddPostComments.js b/webapp/graphql/AddPostComments.js deleted file mode 100644 index ab9ef8ca5..000000000 --- a/webapp/graphql/AddPostComments.js +++ /dev/null @@ -1,18 +0,0 @@ -import gql from 'graphql-tag' - -export default app => { - return { - AddPostComments: gql(` - mutation($from: _CommentInput!, $to: _PostInput!) { - AddPostComments(from: $from, to: $to) { - from { - id - } - to { - id - } - } - } - `) - } -} diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue index ef1121031..95295d6bf 100644 --- a/webapp/pages/post/_id/_slug/index.vue +++ b/webapp/pages/post/_id/_slug/index.vue @@ -321,38 +321,22 @@ export default { this.$apollo .mutate({ mutation: gql` - mutation($content: String!) { - CreateComment(content: $content) { + mutation($postId: ID, $content: String!) { + CreateComment(postId: $postId, content: $content) { id content } } `, variables: { + postId: this.post.id, content: this.value } }) .then(res => { this.disabled = true this.loading = false - const { id } = res.data.CreateComment - const commentId = { id: id } - const postId = { id: this.post.id } - const AddPostComments = require('~/graphql/AddPostComments.js').default( - this - ) - - this.$apollo - .mutate({ - mutation: AddPostComments.AddPostComments, - variables: { - from: commentId, - to: postId - } - }) - .then(res => { - this.$toast.success('Saved!') - }) + this.$toast.success('Saved!') }) .catch(err => { this.$toast.error(err.message) From f4744fa513e1137418bf3190903a6822e988c547 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Wed, 17 Apr 2019 18:37:44 -0300 Subject: [PATCH 11/66] Remove unused import, variables, set debug to false --- backend/src/resolvers/comments.js | 16 ++++++++-------- backend/src/seed/factories/comments.js | 1 - 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/backend/src/resolvers/comments.js b/backend/src/resolvers/comments.js index 5709b52e1..5446278d1 100644 --- a/backend/src/resolvers/comments.js +++ b/backend/src/resolvers/comments.js @@ -5,20 +5,20 @@ export default { CreateComment: async (object, params, context, resolveInfo) => { const { postId } = params delete params.postId - const comment = await neo4jgraphql(object, params, context, resolveInfo, true) - + const comment = await neo4jgraphql(object, params, context, resolveInfo, false) + const session = context.driver.session() - const transactionRes = await session.run(` + await session.run(` MATCH (post:Post {id: $postId}), (comment:Comment {id: $commentId}) MERGE (post)<-[:COMMENTS]-(comment) RETURN comment {.id, .content}`, { - postId, - commentId: comment.id - } + postId, + commentId: comment.id + } ) - session.close() - + session.close() + return comment } } diff --git a/backend/src/seed/factories/comments.js b/backend/src/seed/factories/comments.js index 2a131d0d9..3c042f0b2 100644 --- a/backend/src/seed/factories/comments.js +++ b/backend/src/seed/factories/comments.js @@ -1,5 +1,4 @@ import faker from 'faker' -import uuid from 'uuid/v4' export default function (params) { const { From 0149f30f5fa466291fba95e3059919732e6ebbff Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Wed, 17 Apr 2019 20:27:35 -0300 Subject: [PATCH 12/66] Fix failing tests, refactor - due to changes made to comments factories, which caused failures - to use new custom CreateComment resolver syntax to relate a comment to post by passing in the postId --- .../middleware/softDeleteMiddleware.spec.js | 10 ++--- backend/src/resolvers/moderation.spec.js | 9 ++--- backend/src/seed/factories/comments.js | 3 ++ backend/src/seed/seed-db.js | 38 +++++++------------ 4 files changed, 24 insertions(+), 36 deletions(-) diff --git a/backend/src/middleware/softDeleteMiddleware.spec.js b/backend/src/middleware/softDeleteMiddleware.spec.js index 46005a4ff..f007888ed 100644 --- a/backend/src/middleware/softDeleteMiddleware.spec.js +++ b/backend/src/middleware/softDeleteMiddleware.spec.js @@ -23,21 +23,19 @@ beforeAll(async () => { ]) await Promise.all([ - factory.create('Comment', { id: 'c2', content: 'Enabled comment on public post' }) + factory.create('Comment', { id: 'c2', postId: 'p3', content: 'Enabled comment on public post' }) ]) await Promise.all([ - factory.relate('Comment', 'Author', { from: 'u1', to: 'c2' }), - factory.relate('Comment', 'Post', { from: 'c2', to: 'p3' }) + factory.relate('Comment', 'Author', { from: 'u1', to: 'c2' }) ]) const asTroll = Factory() await asTroll.authenticateAs({ email: 'troll@example.org', password: '1234' }) await asTroll.create('Post', { id: 'p2', title: 'Disabled post', content: 'This is an offensive post content', image: '/some/offensive/image.jpg', deleted: false }) - await asTroll.create('Comment', { id: 'c1', content: 'Disabled comment' }) + await asTroll.create('Comment', { id: 'c1', postId: 'p3', content: 'Disabled comment' }) await Promise.all([ - asTroll.relate('Comment', 'Author', { from: 'u2', to: 'c1' }), - asTroll.relate('Comment', 'Post', { from: 'c1', to: 'p3' }) + asTroll.relate('Comment', 'Author', { from: 'u2', to: 'c1' }) ]) const asModerator = Factory() diff --git a/backend/src/resolvers/moderation.spec.js b/backend/src/resolvers/moderation.spec.js index dfbcac80f..f8aa6e10b 100644 --- a/backend/src/resolvers/moderation.spec.js +++ b/backend/src/resolvers/moderation.spec.js @@ -109,11 +109,11 @@ describe('disable', () => { await factory.authenticateAs({ email: 'commenter@example.org', password: '1234' }) await Promise.all([ factory.create('Post', { id: 'p3' }), - factory.create('Comment', { id: 'c47' }) + factory.create('Comment', { id: 'c47', postId: 'p3', content: 'this comment was created for this post' }) ]) + await Promise.all([ - factory.relate('Comment', 'Author', { from: 'u45', to: 'c47' }), - factory.relate('Comment', 'Post', { from: 'c47', to: 'p3' }) + factory.relate('Comment', 'Author', { from: 'u45', to: 'c47' }) ]) } }) @@ -286,8 +286,7 @@ describe('enable', () => { factory.create('Comment', { id: 'c456' }) ]) await Promise.all([ - factory.relate('Comment', 'Author', { from: 'u123', to: 'c456' }), - factory.relate('Comment', 'Post', { from: 'c456', to: 'p9' }) + factory.relate('Comment', 'Author', { from: 'u123', to: 'c456' }) ]) const disableMutation = ` diff --git a/backend/src/seed/factories/comments.js b/backend/src/seed/factories/comments.js index 3c042f0b2..66f2338b5 100644 --- a/backend/src/seed/factories/comments.js +++ b/backend/src/seed/factories/comments.js @@ -1,7 +1,9 @@ import faker from 'faker' +import uuid from 'uuid/v4' export default function (params) { const { + id = uuid(), postId = 'p6', content = [ faker.lorem.sentence(), @@ -12,6 +14,7 @@ export default function (params) { return ` mutation { CreateComment( + id: "${id}" postId: "${postId}", content: "${content}" ) { id, content } diff --git a/backend/src/seed/seed-db.js b/backend/src/seed/seed-db.js index 3de70e643..ec0184b9c 100644 --- a/backend/src/seed/seed-db.js +++ b/backend/src/seed/seed-db.js @@ -185,45 +185,33 @@ import Factory from './factories' ]) await Promise.all([ - f.create('Comment', { id: 'c1' }), - f.create('Comment', { id: 'c2' }), - f.create('Comment', { id: 'c3' }), - f.create('Comment', { id: 'c4' }), - f.create('Comment', { id: 'c5' }), - f.create('Comment', { id: 'c6' }), - f.create('Comment', { id: 'c7' }), - f.create('Comment', { id: 'c8' }), - f.create('Comment', { id: 'c9' }), - f.create('Comment', { id: 'c10' }), - f.create('Comment', { id: 'c11' }), - f.create('Comment', { id: 'c12' }) + f.create('Comment', { id: 'c1', postId: 'p1' }), + f.create('Comment', { id: 'c2', postId: 'p1' }), + f.create('Comment', { id: 'c3', postId: 'p3' }), + f.create('Comment', { id: 'c4', postId: 'p2' }), + f.create('Comment', { id: 'c5', postId: 'p3' }), + f.create('Comment', { id: 'c6', postId: 'p4' }), + f.create('Comment', { id: 'c7', postId: 'p2' }), + f.create('Comment', { id: 'c8', postId: 'p15' }), + f.create('Comment', { id: 'c9', postId: 'p15' }), + f.create('Comment', { id: 'c10', postId: 'p15' }), + f.create('Comment', { id: 'c11', postId: 'p15' }), + f.create('Comment', { id: 'c12', postId: 'p15' }) ]) await Promise.all([ f.relate('Comment', 'Author', { from: 'u3', to: 'c1' }), - f.relate('Comment', 'Post', { from: 'c1', to: 'p1' }), f.relate('Comment', 'Author', { from: 'u1', to: 'c2' }), - f.relate('Comment', 'Post', { from: 'c2', to: 'p1' }), f.relate('Comment', 'Author', { from: 'u1', to: 'c3' }), - f.relate('Comment', 'Post', { from: 'c3', to: 'p3' }), f.relate('Comment', 'Author', { from: 'u4', to: 'c4' }), - f.relate('Comment', 'Post', { from: 'c4', to: 'p2' }), f.relate('Comment', 'Author', { from: 'u4', to: 'c5' }), - f.relate('Comment', 'Post', { from: 'c5', to: 'p3' }), f.relate('Comment', 'Author', { from: 'u3', to: 'c6' }), - f.relate('Comment', 'Post', { from: 'c6', to: 'p4' }), f.relate('Comment', 'Author', { from: 'u2', to: 'c7' }), - f.relate('Comment', 'Post', { from: 'c7', to: 'p2' }), f.relate('Comment', 'Author', { from: 'u5', to: 'c8' }), - f.relate('Comment', 'Post', { from: 'c8', to: 'p15' }), f.relate('Comment', 'Author', { from: 'u6', to: 'c9' }), - f.relate('Comment', 'Post', { from: 'c9', to: 'p15' }), f.relate('Comment', 'Author', { from: 'u7', to: 'c10' }), - f.relate('Comment', 'Post', { from: 'c10', to: 'p15' }), f.relate('Comment', 'Author', { from: 'u5', to: 'c11' }), - f.relate('Comment', 'Post', { from: 'c11', to: 'p15' }), - f.relate('Comment', 'Author', { from: 'u6', to: 'c12' }), - f.relate('Comment', 'Post', { from: 'c12', to: 'p15' }) + f.relate('Comment', 'Author', { from: 'u6', to: 'c12' }) ]) const disableMutation = 'mutation($id: ID!) { disable(id: $id) }' From 4f7d5ee24fb49b285d5b0813d8b4cd7d97b34a49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=A4fer?= Date: Thu, 18 Apr 2019 19:05:36 +0200 Subject: [PATCH 13/66] Fix? flaky cypress by waiting for content Content menu is a client-side rendered component. Maybe an extra assertion will wait for it? That's how you can flix flaky cucumbers if you use capybara. --- cypress/integration/common/report.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cypress/integration/common/report.js b/cypress/integration/common/report.js index 78abf5378..a6c13c3e6 100644 --- a/cypress/integration/common/report.js +++ b/cypress/integration/common/report.js @@ -52,10 +52,11 @@ When('I click on "Report Post" from the content menu of the post', () => { When( 'I click on "Report User" from the content menu in the user info box', () => { - cy.contains('.ds-card', davidIrvingName) - .find('.content-menu-trigger') - .first() - .click({force: true}) + // wait client-side-rendered content + cy.get('.ds-card-content .content-menu button').should('exist') + + cy.contains('.ds-card-content', davidIrvingName) + .find('.content-menu button').click() cy.get('.popover .ds-menu-item-link') .contains('Report User') From 3d2a982d3fe47e26e2a2e9706d6b3be9a2e14446 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Thu, 18 Apr 2019 22:14:23 -0300 Subject: [PATCH 14/66] Attempt to updated comments - by pushing to the post.comments array, which updates the array, but doesn't rerender the comments component - by updating the apollo store as seen here https://akryum.github.io/vue-apollo/guide/apollo/mutations.html#server-side-example and https://github.com/Akryum/vue-apollo-todos --- backend/src/seed/factories/comments.js | 2 +- webapp/graphql/PostQuery.gql | 66 ++++++++++++++++++++++++++ webapp/pages/post/_id/_slug/index.vue | 39 +++++++++++++-- 3 files changed, 101 insertions(+), 6 deletions(-) create mode 100644 webapp/graphql/PostQuery.gql diff --git a/backend/src/seed/factories/comments.js b/backend/src/seed/factories/comments.js index b30cede36..ba3a85840 100644 --- a/backend/src/seed/factories/comments.js +++ b/backend/src/seed/factories/comments.js @@ -19,6 +19,6 @@ export default function (params) { } } `, - variables: { id, content } + variables: { id, postId, content } } } diff --git a/webapp/graphql/PostQuery.gql b/webapp/graphql/PostQuery.gql new file mode 100644 index 000000000..87021b7ee --- /dev/null +++ b/webapp/graphql/PostQuery.gql @@ -0,0 +1,66 @@ +query Post($slug: String!) { + Post(slug: $slug) { + id + title + content + createdAt + disabled + deleted + slug + image + author { + id + slug + name + avatar + disabled + deleted + shoutedCount + contributionsCount + commentsCount + followedByCount + followedByCurrentUser + badges { + id + key + icon + } + } + tags { + name + } + commentsCount + comments(orderBy: createdAt_desc) { + id + contentExcerpt + createdAt + disabled + deleted + author { + id + slug + name + avatar + disabled + deleted + shoutedCount + contributionsCount + commentsCount + followedByCount + followedByCurrentUser + badges { + id + key + icon + } + } + } + categories { + id + name + icon + } + shoutedCount + shoutedByCurrentUser + } +} diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue index 95295d6bf..fc0056e0b 100644 --- a/webapp/pages/post/_id/_slug/index.vue +++ b/webapp/pages/post/_id/_slug/index.vue @@ -131,7 +131,7 @@ @@ -172,7 +172,8 @@ import HcUser from '~/components/User' import HcShoutButton from '~/components/ShoutButton.vue' import HcEmpty from '~/components/Empty.vue' import Comment from '~/components/Comment.vue' -import HcEditor from '~/components/Editor/Editor.vue' +import HcEditor from '~/components/Editor' +import POST_INFO from '~/graphql/PostQuery.gql' export default { transition: { @@ -316,7 +317,12 @@ export default { isAuthor(id) { return this.$store.getters['auth/user'].id === id }, + addComment(comment) { + this.post.comments.push(comment) + }, handleSubmit() { + const value = this.value + this.value = '' this.loading = true this.$apollo .mutate({ @@ -330,10 +336,33 @@ export default { `, variables: { postId: this.post.id, - content: this.value - } - }) + content: value + }, + update: (store, { data: { CreateComment } }) => { + const data = store.readQuery({ query: POST_INFO }) + // data.Post.push(CreateComment) + // store.writeQuery({ query: POST_INFO, data }) + // // Add to Todo tasks list + // const todoQuery = { + // query: POST_INFO, + // variables: { filter: { done: false } }, + // } + // const todoData = store.readQuery(todoQuery) + // todoData.allTasks.push(createTask) + // store.writeQuery({ ...todoQuery, data: todoData }) + }, + optimisticResponse: { + __typename: 'Mutation', + CreateComment: { + __typename: 'Comment', + id: null, + content: value + }, + }, + }) .then(res => { + console.log(res.data.CreateComment) + this.addComment(res.data.CreateComment) this.disabled = true this.loading = false this.$toast.success('Saved!') From 9ff194f3d67f35b19cff69e0c499128b6270bad7 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Fri, 19 Apr 2019 09:46:46 -0300 Subject: [PATCH 15/66] Refetch the post to update the comments - I'm not happy with this as it is expensive, but seems to be used in other places in the code base, where I found the idea, @appinteractive left a comment suggesting a better approach would be to use subscriptions, but I haven't had time to research/try this option Co-authored-by: Mike Aono Co-authored-by: Joseph Ngugi --- webapp/pages/post/_id/_slug/index.vue | 42 +++++++++++---------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue index fc0056e0b..1803541d4 100644 --- a/webapp/pages/post/_id/_slug/index.vue +++ b/webapp/pages/post/_id/_slug/index.vue @@ -318,7 +318,8 @@ export default { return this.$store.getters['auth/user'].id === id }, addComment(comment) { - this.post.comments.push(comment) + this.$apollo.queries.Post.refetch() + // this.post = { ...this.post, comments: [...this.post.comments, comment] } }, handleSubmit() { const value = this.value @@ -337,31 +338,9 @@ export default { variables: { postId: this.post.id, content: value - }, - update: (store, { data: { CreateComment } }) => { - const data = store.readQuery({ query: POST_INFO }) - // data.Post.push(CreateComment) - // store.writeQuery({ query: POST_INFO, data }) - // // Add to Todo tasks list - // const todoQuery = { - // query: POST_INFO, - // variables: { filter: { done: false } }, - // } - // const todoData = store.readQuery(todoQuery) - // todoData.allTasks.push(createTask) - // store.writeQuery({ ...todoQuery, data: todoData }) - }, - optimisticResponse: { - __typename: 'Mutation', - CreateComment: { - __typename: 'Comment', - id: null, - content: value - }, - }, - }) + } + }) .then(res => { - console.log(res.data.CreateComment) this.addComment(res.data.CreateComment) this.disabled = true this.loading = false @@ -373,6 +352,19 @@ export default { this.disabled = false }) } + }, + apollo: { + Post: { + query() { + return require('~/graphql/PostQuery.gql') + }, + variables() { + return { + slug: this.$route.params.slug + } + }, + fetchPolicy: 'cache-and-network' + } } } From 4d8148297e125abe01259a0603049c79755b65bf Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Fri, 19 Apr 2019 12:53:59 -0300 Subject: [PATCH 16/66] Fix styling of hc-editor, localize toast message - validations are not working for hc-editor, neither in this PR nor in ContributionForm --- webapp/locales/en.json | 3 +- webapp/pages/post/_id/_slug/index.vue | 90 +++++++++++++++++---------- 2 files changed, 58 insertions(+), 35 deletions(-) diff --git a/webapp/locales/en.json b/webapp/locales/en.json index af4e50c11..c74cbed52 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -112,7 +112,8 @@ "takeAction": { "name": "Take action" }, - "submitComment": "Submit Comment" + "submitComment": "Submit Comment", + "commentSubmitted": "Comment Submitted" }, "quotes": { "african": { diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue index 1803541d4..60ed15c20 100644 --- a/webapp/pages/post/_id/_slug/index.vue +++ b/webapp/pages/post/_id/_slug/index.vue @@ -112,33 +112,46 @@ - - - - - - - - {{ $t('actions.cancel') }} - - - - - {{ $t('post.submitComment') }} - - - + + + @@ -201,7 +214,13 @@ export default { ready: false, title: 'loading', loading: false, - disabled: false + disabled: false, + form: { + content: '' + }, + formSchema: { + content: { required: true, min: 3 } + } } }, watch: { @@ -317,14 +336,17 @@ export default { isAuthor(id) { return this.$store.getters['auth/user'].id === id }, + updateEditorContent(value) { + // this.form.content = value + this.$refs.contributionForm.update('content', value) + }, addComment(comment) { this.$apollo.queries.Post.refetch() // this.post = { ...this.post, comments: [...this.post.comments, comment] } }, handleSubmit() { - const value = this.value - this.value = '' - this.loading = true + const content = this.form.content + this.form.content = '' this.$apollo .mutate({ mutation: gql` @@ -337,14 +359,14 @@ export default { `, variables: { postId: this.post.id, - content: value + content: content } }) .then(res => { this.addComment(res.data.CreateComment) - this.disabled = true this.loading = false - this.$toast.success('Saved!') + this.disabled = false + this.$toast.success(this.$t('post.commentSubmitted')) }) .catch(err => { this.$toast.error(err.message) From 49c03c92c8695205cb76e14fc6086eb40a01833b Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Sat, 20 Apr 2019 10:49:02 -0300 Subject: [PATCH 17/66] Extract PostQuery/convert to js, try to get clear working Co-authored-by: Mike Aono --- webapp/graphql/PostQuery.gql | 66 --------------- webapp/graphql/PostQuery.js | 79 ++++++++++++++++++ webapp/pages/post/_id/_slug/index.vue | 113 +++----------------------- 3 files changed, 89 insertions(+), 169 deletions(-) delete mode 100644 webapp/graphql/PostQuery.gql create mode 100644 webapp/graphql/PostQuery.js diff --git a/webapp/graphql/PostQuery.gql b/webapp/graphql/PostQuery.gql deleted file mode 100644 index 87021b7ee..000000000 --- a/webapp/graphql/PostQuery.gql +++ /dev/null @@ -1,66 +0,0 @@ -query Post($slug: String!) { - Post(slug: $slug) { - id - title - content - createdAt - disabled - deleted - slug - image - author { - id - slug - name - avatar - disabled - deleted - shoutedCount - contributionsCount - commentsCount - followedByCount - followedByCurrentUser - badges { - id - key - icon - } - } - tags { - name - } - commentsCount - comments(orderBy: createdAt_desc) { - id - contentExcerpt - createdAt - disabled - deleted - author { - id - slug - name - avatar - disabled - deleted - shoutedCount - contributionsCount - commentsCount - followedByCount - followedByCurrentUser - badges { - id - key - icon - } - } - } - categories { - id - name - icon - } - shoutedCount - shoutedByCurrentUser - } -} diff --git a/webapp/graphql/PostQuery.js b/webapp/graphql/PostQuery.js new file mode 100644 index 000000000..d45624616 --- /dev/null +++ b/webapp/graphql/PostQuery.js @@ -0,0 +1,79 @@ +import gql from 'graphql-tag' + +export default app => { + const lang = app.$i18n.locale().toUpperCase() + return gql(` + query Post($slug: String!) { + Post(slug: $slug) { + id + title + content + createdAt + disabled + deleted + slug + image + author { + id + slug + name + avatar + disabled + deleted + shoutedCount + contributionsCount + commentsCount + followedByCount + followedByCurrentUser + location { + name: name${lang} + } + badges { + id + key + icon + } + } + tags { + name + } + commentsCount + comments(orderBy: createdAt_desc) { + id + contentExcerpt + createdAt + disabled + deleted + author { + id + slug + name + avatar + disabled + deleted + shoutedCount + contributionsCount + commentsCount + followedByCount + followedByCurrentUser + location { + name: name${lang} + } + badges { + id + key + icon + } + } + } + categories { + id + name + icon + } + shoutedCount + shoutedByCurrentUser + } + } + `) +} diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue index 60ed15c20..58f254273 100644 --- a/webapp/pages/post/_id/_slug/index.vue +++ b/webapp/pages/post/_id/_slug/index.vue @@ -113,7 +113,7 @@ - @@ -133,7 +134,7 @@ {{ $t('actions.cancel') }} @@ -186,7 +187,6 @@ import HcShoutButton from '~/components/ShoutButton.vue' import HcEmpty from '~/components/Empty.vue' import Comment from '~/components/Comment.vue' import HcEditor from '~/components/Editor' -import POST_INFO from '~/graphql/PostQuery.gql' export default { transition: { @@ -229,102 +229,6 @@ export default { this.title = this.post.title } }, - async asyncData(context) { - const { - params, - error, - app: { apolloProvider, $i18n } - } = context - const client = apolloProvider.defaultClient - const query = gql(` - query Post($slug: String!) { - Post(slug: $slug) { - id - title - content - createdAt - disabled - deleted - slug - image - author { - id - slug - name - avatar - disabled - deleted - shoutedCount - contributionsCount - commentsCount - followedByCount - followedByCurrentUser - location { - name: name${$i18n.locale().toUpperCase()} - } - badges { - id - key - icon - } - } - tags { - name - } - commentsCount - comments(orderBy: createdAt_desc) { - id - contentExcerpt - createdAt - disabled - deleted - author { - id - slug - name - avatar - disabled - deleted - shoutedCount - contributionsCount - commentsCount - followedByCount - followedByCurrentUser - location { - name: name${$i18n.locale().toUpperCase()} - } - badges { - id - key - icon - } - } - } - categories { - id - name - icon - } - shoutedCount - shoutedByCurrentUser - } - } - `) - 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 @@ -337,8 +241,11 @@ export default { return this.$store.getters['auth/user'].id === id }, updateEditorContent(value) { - // this.form.content = value - this.$refs.contributionForm.update('content', value) + this.$refs.commentForm.update('content', value) + }, + clearEditor() { + this.$emit('clear') + this.$refs.commentForm.update('content', '') }, addComment(comment) { this.$apollo.queries.Post.refetch() @@ -378,7 +285,7 @@ export default { apollo: { Post: { query() { - return require('~/graphql/PostQuery.gql') + return require('~/graphql/PostQuery.js').default(this) }, variables() { return { From 52e82d277e3e943debb9e6f7dbcbdb3392faf479 Mon Sep 17 00:00:00 2001 From: aonomike Date: Sat, 20 Apr 2019 16:59:47 +0300 Subject: [PATCH 18/66] Add Post Comment feature file --- cypress/integration/post/Comment.feature | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 cypress/integration/post/Comment.feature diff --git a/cypress/integration/post/Comment.feature b/cypress/integration/post/Comment.feature new file mode 100644 index 000000000..e82b7ee86 --- /dev/null +++ b/cypress/integration/post/Comment.feature @@ -0,0 +1,15 @@ +Feature: Post Comment + As a user + I want to comment on contributions of others + To be able to express my thoughts and emotions about these, discuss and add give further information. + + Background: + Given we have the following posts in our database: + | id | title | slug | + | bWBjpkTKZp | 101 Essays that will change the way you think | 101-essays | + And I have a user account + And I am logged in + + Scenario: + Given I get to the post page of "101-essays" + Then I should be able to post a comment to the post "101-essays" \ No newline at end of file From c6b11319fef76e455c3ccce7c8c6263624d05e46 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Mon, 22 Apr 2019 11:51:29 -0300 Subject: [PATCH 19/66] Clear editor, write cypress test - the editor only clears once, also there are some other bugs associated with clearing it this way - according to https://github.com/scrumpy/tiptap/issues/21 there should be a clearContent(), but haven't been able to get it to work - cypress test for some reason is with a weird bug where I need to submit the form, then click on the submit button, otherwise it doesn't call the handleSubmit method --- cypress/integration/common/post.js | 18 ++++++++++++++++++ cypress/integration/post/Comment.feature | 7 ++++--- webapp/pages/post/_id/_slug/index.vue | 18 +++++++++--------- 3 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 cypress/integration/common/post.js diff --git a/cypress/integration/common/post.js b/cypress/integration/common/post.js new file mode 100644 index 000000000..fc03b20b3 --- /dev/null +++ b/cypress/integration/common/post.js @@ -0,0 +1,18 @@ +import { When, Then } from 'cypress-cucumber-preprocessor/steps' + +When('I should be able to post a comment', () => { + cy.get('.ProseMirror') + .type('This is a comment') + .get('.ds-form') + .submit() + .get('button') + .contains('Submit Comment') + .click() + .get('.iziToast-message') + .contains('Comment Submitted') + }) + +Then('I should see my comment', () => { + cy.get('div.comment p') + .should('contain', 'This is a comment') +}) diff --git a/cypress/integration/post/Comment.feature b/cypress/integration/post/Comment.feature index e82b7ee86..164c13bd6 100644 --- a/cypress/integration/post/Comment.feature +++ b/cypress/integration/post/Comment.feature @@ -1,7 +1,7 @@ Feature: Post Comment As a user I want to comment on contributions of others - To be able to express my thoughts and emotions about these, discuss and add give further information. + To be able to express my thoughts and emotions about these, discuss, and add give further information. Background: Given we have the following posts in our database: @@ -11,5 +11,6 @@ Feature: Post Comment And I am logged in Scenario: - Given I get to the post page of "101-essays" - Then I should be able to post a comment to the post "101-essays" \ No newline at end of file + Given I visit "post/bWBjpkTKZp/101-essays" + Then I should be able to post a comment + And I should see my comment \ No newline at end of file diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue index 58f254273..27b552608 100644 --- a/webapp/pages/post/_id/_slug/index.vue +++ b/webapp/pages/post/_id/_slug/index.vue @@ -97,7 +97,7 @@ - +

@@ -111,7 +111,7 @@

- + - + {{ $t('actions.cancel') }} @@ -244,8 +243,9 @@ export default { this.$refs.commentForm.update('content', value) }, clearEditor() { - this.$emit('clear') - this.$refs.commentForm.update('content', '') + this.loading = false + this.disabled = false + this.form.content = ' ' }, addComment(comment) { this.$apollo.queries.Post.refetch() @@ -253,7 +253,7 @@ export default { }, handleSubmit() { const content = this.form.content - this.form.content = '' + this.form.content = ' ' this.$apollo .mutate({ mutation: gql` @@ -266,7 +266,7 @@ export default { `, variables: { postId: this.post.id, - content: content + content } }) .then(res => { From 43d6254f3ebebbbebfc98f509c87bd2342b3178b Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Tue, 23 Apr 2019 12:23:21 -0300 Subject: [PATCH 20/66] Add custom CommentByPost query --- backend/src/graphql-schema.js | 3 ++- backend/src/resolvers/comments.js | 20 ++++++++++++++++++++ backend/src/schema.graphql | 1 + 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/backend/src/graphql-schema.js b/backend/src/graphql-schema.js index aff10729f..bad277721 100644 --- a/backend/src/graphql-schema.js +++ b/backend/src/graphql-schema.js @@ -23,7 +23,8 @@ export const resolvers = { Query: { ...statistics.Query, ...userManagement.Query, - ...notifications.Query + ...notifications.Query, + ...comments.Query }, Mutation: { ...userManagement.Mutation, diff --git a/backend/src/resolvers/comments.js b/backend/src/resolvers/comments.js index 5446278d1..b3350ec8e 100644 --- a/backend/src/resolvers/comments.js +++ b/backend/src/resolvers/comments.js @@ -1,6 +1,26 @@ import { neo4jgraphql } from 'neo4j-graphql-js' export default { + Query: { + CommentByPost: async (object, params, context, resolveInfo) => { + const { postId } = params + + const session = context.driver.session() + const transactionRes = await session.run(` + MATCH (comment:Comment)-[:COMMENTS]->(post:Post {id: $postId}) + RETURN comment {.id, .contentExcerpt, .createdAt}`, { + postId + }) + + session.close() + let comments = [] + transactionRes.records.map(record => { + comments.push(record.get('comment')) + }) + + return comments + } + }, Mutation: { CreateComment: async (object, params, context, resolveInfo) => { const { postId } = params diff --git a/backend/src/schema.graphql b/backend/src/schema.graphql index 99bcd4533..4638fbd0d 100644 --- a/backend/src/schema.graphql +++ b/backend/src/schema.graphql @@ -16,6 +16,7 @@ type Query { LIMIT $limit """ ) + CommentByPost(postId: ID!): [Comment]! } type Mutation { # Get a JWT Token for the given Email and password From 20112bdd9b9e79247bacc8687948a4b99c00af47 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Tue, 23 Apr 2019 12:24:27 -0300 Subject: [PATCH 21/66] Add back asyncData, use CommentByPost query --- webapp/graphql/CommentQuery.js | 13 +++ webapp/pages/post/_id/_slug/index.vue | 116 ++++++++++++++++++++++++-- 2 files changed, 121 insertions(+), 8 deletions(-) create mode 100644 webapp/graphql/CommentQuery.js diff --git a/webapp/graphql/CommentQuery.js b/webapp/graphql/CommentQuery.js new file mode 100644 index 000000000..1c3f9be20 --- /dev/null +++ b/webapp/graphql/CommentQuery.js @@ -0,0 +1,13 @@ +import gql from 'graphql-tag' + +export default app => { + return gql(` + query CommentByPost($postId: ID!) { + CommentByPost(postId: $postId, orderBy: createdAt_desc) { + id + contentExcerpt + createdAt + } + } + `) +} diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue index 27b552608..0ecd98c4e 100644 --- a/webapp/pages/post/_id/_slug/index.vue +++ b/webapp/pages/post/_id/_slug/index.vue @@ -102,7 +102,7 @@ - +
@@ -210,6 +210,7 @@ export default { data() { return { post: null, + comments: null, ready: false, title: 'loading', loading: false, @@ -226,6 +227,105 @@ export default { Post(post) { this.post = post[0] || {} this.title = this.post.title + }, + CommentByPost(comments) { + this.comments = comments || [] + } + }, + async asyncData(context) { + const { + params, + error, + app: { apolloProvider, $i18n } + } = context + const client = apolloProvider.defaultClient + const query = gql(` + query Post($slug: String!) { + Post(slug: $slug) { + id + title + content + createdAt + disabled + deleted + slug + image + author { + id + slug + name + avatar + disabled + deleted + shoutedCount + contributionsCount + commentsCount + followedByCount + followedByCurrentUser + location { + name: name${$i18n.locale().toUpperCase()} + } + badges { + id + key + icon + } + } + tags { + name + } + commentsCount + comments(orderBy: createdAt_desc) { + id + contentExcerpt + createdAt + disabled + deleted + author { + id + slug + name + avatar + disabled + deleted + shoutedCount + contributionsCount + commentsCount + followedByCount + followedByCurrentUser + location { + name: name${$i18n.locale().toUpperCase()} + } + badges { + id + key + icon + } + } + } + categories { + id + name + icon + } + shoutedCount + shoutedByCurrentUser + } + } + `) + 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() { @@ -248,7 +348,7 @@ export default { this.form.content = ' ' }, addComment(comment) { - this.$apollo.queries.Post.refetch() + this.$apollo.queries.CommentByPost.refetch() // this.post = { ...this.post, comments: [...this.post.comments, comment] } }, handleSubmit() { @@ -283,13 +383,13 @@ export default { } }, apollo: { - Post: { + CommentByPost: { query() { - return require('~/graphql/PostQuery.js').default(this) + return require('~/graphql/CommentQuery.js').default(this) }, variables() { return { - slug: this.$route.params.slug + postId: this.post.id } }, fetchPolicy: 'cache-and-network' From 3b00a3419978fce9fc0803a65bb5eaf65a849ec3 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Tue, 23 Apr 2019 18:19:11 -0300 Subject: [PATCH 22/66] Add cypress step to check the editor is cleared --- cypress/integration/common/post.js | 7 ++++++- cypress/integration/post/Comment.feature | 5 +++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/cypress/integration/common/post.js b/cypress/integration/common/post.js index fc03b20b3..01601437c 100644 --- a/cypress/integration/common/post.js +++ b/cypress/integration/common/post.js @@ -15,4 +15,9 @@ When('I should be able to post a comment', () => { Then('I should see my comment', () => { cy.get('div.comment p') .should('contain', 'This is a comment') -}) +}) + +Then('the editor should be cleared', () => { + cy.get('.ProseMirror p') + .should('have.class', 'is-empty') +}) diff --git a/cypress/integration/post/Comment.feature b/cypress/integration/post/Comment.feature index 164c13bd6..9290d7e21 100644 --- a/cypress/integration/post/Comment.feature +++ b/cypress/integration/post/Comment.feature @@ -10,7 +10,8 @@ Feature: Post Comment And I have a user account And I am logged in - Scenario: + Scenario: Comment creation Given I visit "post/bWBjpkTKZp/101-essays" Then I should be able to post a comment - And I should see my comment \ No newline at end of file + And I should see my comment + And the editor should be cleared From 11a1f7991e0c020ecd295340b8e03ce4bcb15fc4 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Tue, 23 Apr 2019 18:19:48 -0300 Subject: [PATCH 23/66] Remove PostQuery.js - to be added in a separate ticket(?) --- webapp/graphql/PostQuery.js | 79 ------------------------------------- 1 file changed, 79 deletions(-) delete mode 100644 webapp/graphql/PostQuery.js diff --git a/webapp/graphql/PostQuery.js b/webapp/graphql/PostQuery.js deleted file mode 100644 index d45624616..000000000 --- a/webapp/graphql/PostQuery.js +++ /dev/null @@ -1,79 +0,0 @@ -import gql from 'graphql-tag' - -export default app => { - const lang = app.$i18n.locale().toUpperCase() - return gql(` - query Post($slug: String!) { - Post(slug: $slug) { - id - title - content - createdAt - disabled - deleted - slug - image - author { - id - slug - name - avatar - disabled - deleted - shoutedCount - contributionsCount - commentsCount - followedByCount - followedByCurrentUser - location { - name: name${lang} - } - badges { - id - key - icon - } - } - tags { - name - } - commentsCount - comments(orderBy: createdAt_desc) { - id - contentExcerpt - createdAt - disabled - deleted - author { - id - slug - name - avatar - disabled - deleted - shoutedCount - contributionsCount - commentsCount - followedByCount - followedByCurrentUser - location { - name: name${lang} - } - badges { - id - key - icon - } - } - } - categories { - id - name - icon - } - shoutedCount - shoutedByCurrentUser - } - } - `) -} From 0078b743fe5ae3bcd401c628e53e14ad7a191eb3 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Wed, 24 Apr 2019 09:11:33 -0300 Subject: [PATCH 24/66] Validate comments length, presence/test - Co-authored-by: Wolfgang Huss - Co-authored-by: Mike Aono --- backend/src/resolvers/comments.js | 7 +++++++ backend/src/resolvers/comments.spec.js | 22 +++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/backend/src/resolvers/comments.js b/backend/src/resolvers/comments.js index b3350ec8e..60ecbcc8e 100644 --- a/backend/src/resolvers/comments.js +++ b/backend/src/resolvers/comments.js @@ -1,5 +1,7 @@ import { neo4jgraphql } from 'neo4j-graphql-js' +import { UserInputError } from 'apollo-server' +const COMMENT_MIN_LENGTH = 3 export default { Query: { CommentByPost: async (object, params, context, resolveInfo) => { @@ -23,6 +25,11 @@ export default { }, Mutation: { CreateComment: async (object, params, context, resolveInfo) => { + const content = params.content.replace(/<(?:.|\n)*?>/gm, '').trim() + + if (!params.content || content.length < COMMENT_MIN_LENGTH) { + throw new UserInputError(`Comment must be at least ${COMMENT_MIN_LENGTH} characters long!`) + } const { postId } = params delete params.postId const comment = await neo4jgraphql(object, params, context, resolveInfo, false) diff --git a/backend/src/resolvers/comments.spec.js b/backend/src/resolvers/comments.spec.js index 9918038a7..eb4e39633 100644 --- a/backend/src/resolvers/comments.spec.js +++ b/backend/src/resolvers/comments.spec.js @@ -44,7 +44,7 @@ describe('CreateComment', () => { client = new GraphQLClient(host, { headers }) }) - it('creates a post', async () => { + it('creates a comment', async () => { variables = { postId: 'p1', content: 'I\'m authorised to comment' @@ -57,5 +57,25 @@ describe('CreateComment', () => { await expect(client.request(mutation, variables)).resolves.toMatchObject(expected) }) + + it('throw an error if an empty string is sent as content', async () => { + variables = { + postId: 'p1', + content: '

' + } + + await expect(client.request(mutation, variables)) + .rejects.toThrow('Comment must be at least 3 characters long!') + }) + + it('throws an error if a comment is less than 3 characters', async () => { + variables = { + postId: 'p1', + content: '

ab

' + } + + await expect(client.request(mutation, variables)) + .rejects.toThrow('Comment must be at least 3 characters long!') + }) }) }) From 546e2c99adb1c96ca4128aa0e929ff385ebdf84c Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Wed, 24 Apr 2019 09:15:41 -0300 Subject: [PATCH 25/66] Localise text, remove frontend validations - validations are not working for the editor, they only work for our ds-input --- webapp/components/Editor/index.vue | 2 +- webapp/locales/de.json | 3 +++ webapp/locales/en.json | 3 +++ webapp/pages/post/_id/_slug/index.vue | 5 ----- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/webapp/components/Editor/index.vue b/webapp/components/Editor/index.vue index 5636c3714..57998fcbc 100644 --- a/webapp/components/Editor/index.vue +++ b/webapp/components/Editor/index.vue @@ -224,7 +224,7 @@ export default { new ListItem(), new Placeholder({ emptyNodeClass: 'is-empty', - emptyNodeText: 'Schreib etwas inspirerendes…' + emptyNodeText: this.$t('editor.placeholder') }), new History(), new Mention({ diff --git a/webapp/locales/de.json b/webapp/locales/de.json index 04a14f2a7..3fac0310d 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -8,6 +8,9 @@ "moreInfo": "Was ist Human Connection?", "hello": "Hallo" }, + "editor": { + "placeholder": "Schreib etwas inspirerendes…" + }, "profile": { "name": "Mein Profil", "memberSince": "Mitglied seit", diff --git a/webapp/locales/en.json b/webapp/locales/en.json index c74cbed52..83e8c4eda 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -8,6 +8,9 @@ "moreInfo": "What is Human Connection?", "hello": "Hello" }, + "editor": { + "placeholder": "Leave your inspirational thoughts…" + }, "profile": { "name": "My Profile", "memberSince": "Member since", diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue index 0ecd98c4e..29ad646f1 100644 --- a/webapp/pages/post/_id/_slug/index.vue +++ b/webapp/pages/post/_id/_slug/index.vue @@ -115,7 +115,6 @@ @@ -445,6 +448,9 @@ export default { // remove link command({ href: null }) } + }, + clear() { + this.editor.clearContent(true) } } } diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue index fb3f8e5f9..459c9696d 100644 --- a/webapp/pages/post/_id/_slug/index.vue +++ b/webapp/pages/post/_id/_slug/index.vue @@ -107,7 +107,7 @@ color="primary" size="small" round - >{{ post.commentsCount }}  Comments + >{{ comments.length }}  Comments @@ -121,6 +121,7 @@ {{ $t('actions.cancel') }} @@ -346,15 +347,13 @@ export default { } this.$refs.commentForm.update('content', value) }, - clearEditor() { - this.form.content = ' ' + clear() { + this.$refs.editor.clear() }, addComment(comment) { this.$apollo.queries.CommentByPost.refetch() }, handleSubmit() { - const content = this.form.content - this.form.content = ' ' this.$apollo .mutate({ mutation: gql` @@ -367,11 +366,12 @@ export default { `, variables: { postId: this.post.id, - content + content: this.form.content } }) .then(res => { this.addComment(res.data.CreateComment) + this.$refs.editor.clear() this.loading = false this.disabled = false this.$toast.success(this.$t('post.comment.submitted')) @@ -395,7 +395,7 @@ export default { }, fetchPolicy: 'cache-and-network' }, - User: { + User: { query() { return gql(`{ User(orderBy: slug_asc) { From bc35ab835f09220899ddec08695d569fe09e83d7 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Wed, 24 Apr 2019 20:56:57 -0300 Subject: [PATCH 31/66] Modify cypress tests, attempt to get them to work - they are still not triggering a change in form.content, therefore sending an empty string and either failing the back end validations, or if removed creating a comment with an empty string --- cypress/integration/common/post.js | 17 +++++------------ cypress/integration/post/Comment.feature | 7 ++++++- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/cypress/integration/common/post.js b/cypress/integration/common/post.js index 63df8459b..23a7d5764 100644 --- a/cypress/integration/common/post.js +++ b/cypress/integration/common/post.js @@ -1,20 +1,13 @@ import { When, Then } from 'cypress-cucumber-preprocessor/steps' -When('I should be able to post a comment', () => { - cy.get('[contenteditable]') - .type('This is a comment') - // .get('.ds-form') - // .submit() - .get('button') - .contains('Submit Comment') - .click() - .get('.iziToast-message') +Then('my comment should be successfully created', () => { + cy.get('.iziToast-message') .contains('Comment Submitted') - }) - +}) + Then('I should see my comment', () => { cy.get('div.comment p') - .should('contain', 'This is a comment') + .should('contain', 'Human Connection rocks') }) Then('the editor should be cleared', () => { diff --git a/cypress/integration/post/Comment.feature b/cypress/integration/post/Comment.feature index 9290d7e21..8370bcfd4 100644 --- a/cypress/integration/post/Comment.feature +++ b/cypress/integration/post/Comment.feature @@ -12,6 +12,11 @@ Feature: Post Comment Scenario: Comment creation Given I visit "post/bWBjpkTKZp/101-essays" - Then I should be able to post a comment + And I type in the following text: + """ + Human Connection rocks + """ + And I click on "Submit Comment" + Then my comment should be successfully created And I should see my comment And the editor should be cleared From 18458d23f5cfa9a3f2c27f0a31a8903c5b23b74a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Thu, 25 Apr 2019 10:36:03 +0200 Subject: [PATCH 32/66] Localisations corrected Had some old failures and some criss-cross with German and English. --- webapp/locales/de.json | 6 +++--- webapp/locales/en.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/webapp/locales/de.json b/webapp/locales/de.json index 90a2cf997..5831d5e61 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -9,7 +9,7 @@ "hello": "Hallo" }, "editor": { - "placeholder": "Schreib etwas inspirerendes…" + "placeholder": "Schreib etwas Inspirierendes …" }, "profile": { "name": "Mein Profil", @@ -116,8 +116,8 @@ "name": "Aktiv werden" }, "comment": { - "submit": "Commentar Senden", - "submitted": "Commentar Gesendet" + "submit": "Kommentar Senden", + "submitted": "Kommentar Gesendet" } }, "quotes": { diff --git a/webapp/locales/en.json b/webapp/locales/en.json index e909bbbf8..e92b2a190 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -9,7 +9,7 @@ "hello": "Hello" }, "editor": { - "placeholder": "Leave your inspirational thoughts…" + "placeholder": "Leave your inspirational thoughts …" }, "profile": { "name": "My Profile", From 092dcd71227bc1dc95c8844ee95f6a75cda48f23 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Thu, 25 Apr 2019 10:10:08 -0300 Subject: [PATCH 33/66] Get cypress test passing in a hacky way --- cypress/integration/common/post.js | 2 ++ webapp/components/Editor/index.vue | 3 +++ webapp/pages/post/_id/_slug/index.vue | 14 +++++++------- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/cypress/integration/common/post.js b/cypress/integration/common/post.js index 23a7d5764..e3a922139 100644 --- a/cypress/integration/common/post.js +++ b/cypress/integration/common/post.js @@ -1,6 +1,8 @@ import { When, Then } from 'cypress-cucumber-preprocessor/steps' Then('my comment should be successfully created', () => { + cy.get('.ds-form') + .submit() cy.get('.iziToast-message') .contains('Comment Submitted') }) diff --git a/webapp/components/Editor/index.vue b/webapp/components/Editor/index.vue index 5b542b3ce..7596e75e4 100644 --- a/webapp/components/Editor/index.vue +++ b/webapp/components/Editor/index.vue @@ -415,6 +415,9 @@ export default { this.$emit('input', content) } }, + update(value) { + this.editor.setContent(value) + }, showLinkMenu(attrs) { this.linkUrl = attrs.href this.linkMenuIsActive = true diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue index 459c9696d..c99e4e5be 100644 --- a/webapp/pages/post/_id/_slug/index.vue +++ b/webapp/pages/post/_id/_slug/index.vue @@ -339,13 +339,16 @@ export default { return this.$store.getters['auth/user'].id === id }, updateEditorContent(value) { - const content = value.replace(/<(?:.|\n)*?>/gm, '').trim().length - if (content < 3) { + const content = value.replace(/<(?:.|\n)*?>/gm, '').trim() + if (content.length < 3) { this.disabled = true } else { this.disabled = false } - this.$refs.commentForm.update('content', value) + console.log(value) + this.form.content = value + // this.$refs.commentForm.update('content', value) + // this.$refs.editor.update(value) }, clear() { this.$refs.editor.clear() @@ -354,6 +357,7 @@ export default { this.$apollo.queries.CommentByPost.refetch() }, handleSubmit() { + console.log('content', this.form.content) this.$apollo .mutate({ mutation: gql` @@ -372,14 +376,10 @@ export default { .then(res => { this.addComment(res.data.CreateComment) this.$refs.editor.clear() - this.loading = false - this.disabled = false this.$toast.success(this.$t('post.comment.submitted')) }) .catch(err => { this.$toast.error(err.message) - this.loading = false - this.disabled = false }) } }, From c387760046bb2bd4c4170dbafb9283edf0b4e1d9 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Thu, 25 Apr 2019 14:20:00 -0300 Subject: [PATCH 34/66] Extract CommentForm component - Cypress test is now passing as a result Co-authored-by: Tirokk --- cypress/integration/common/post.js | 2 - webapp/components/CommentForm/index.vue | 123 ++++++++++++++++++++++++ webapp/pages/post/_id/_slug/index.vue | 110 +-------------------- 3 files changed, 127 insertions(+), 108 deletions(-) create mode 100644 webapp/components/CommentForm/index.vue diff --git a/cypress/integration/common/post.js b/cypress/integration/common/post.js index e3a922139..23a7d5764 100644 --- a/cypress/integration/common/post.js +++ b/cypress/integration/common/post.js @@ -1,8 +1,6 @@ import { When, Then } from 'cypress-cucumber-preprocessor/steps' Then('my comment should be successfully created', () => { - cy.get('.ds-form') - .submit() cy.get('.iziToast-message') .contains('Comment Submitted') }) diff --git a/webapp/components/CommentForm/index.vue b/webapp/components/CommentForm/index.vue new file mode 100644 index 000000000..f13ce6927 --- /dev/null +++ b/webapp/components/CommentForm/index.vue @@ -0,0 +1,123 @@ + + + diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue index c99e4e5be..82de14481 100644 --- a/webapp/pages/post/_id/_slug/index.vue +++ b/webapp/pages/post/_id/_slug/index.vue @@ -111,49 +111,7 @@ - - - - - +
/gm, '').trim() - if (content.length < 3) { - this.disabled = true - } else { - this.disabled = false - } - console.log(value) - this.form.content = value - // this.$refs.commentForm.update('content', value) - // this.$refs.editor.update(value) - }, - clear() { - this.$refs.editor.clear() - }, addComment(comment) { this.$apollo.queries.CommentByPost.refetch() - }, - handleSubmit() { - console.log('content', this.form.content) - this.$apollo - .mutate({ - mutation: gql` - mutation($postId: ID, $content: String!) { - CreateComment(postId: $postId, content: $content) { - id - content - } - } - `, - variables: { - postId: this.post.id, - content: this.form.content - } - }) - .then(res => { - this.addComment(res.data.CreateComment) - this.$refs.editor.clear() - this.$toast.success(this.$t('post.comment.submitted')) - }) - .catch(err => { - this.$toast.error(err.message) - }) } }, apollo: { @@ -394,19 +305,6 @@ export default { } }, fetchPolicy: 'cache-and-network' - }, - User: { - query() { - return gql(`{ - User(orderBy: slug_asc) { - id - slug - } - }`) - }, - result(result) { - this.users = result.data.User - } } } } From 05ad8ccc302279ac7507b91abe64fe03dd2e29bb Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Thu, 25 Apr 2019 16:36:59 -0300 Subject: [PATCH 35/66] Remove unused variable/method --- webapp/components/CommentForm/index.vue | 4 +--- webapp/components/Editor/index.vue | 3 --- webapp/locales/de.json | 2 +- webapp/locales/en.json | 2 +- 4 files changed, 3 insertions(+), 8 deletions(-) diff --git a/webapp/components/CommentForm/index.vue b/webapp/components/CommentForm/index.vue index f13ce6927..bb71af1f7 100644 --- a/webapp/components/CommentForm/index.vue +++ b/webapp/components/CommentForm/index.vue @@ -19,7 +19,7 @@ @@ -29,7 +29,6 @@ @@ -57,7 +56,6 @@ export default { }, data() { return { - loading: false, disabled: true, form: { content: '' diff --git a/webapp/components/Editor/index.vue b/webapp/components/Editor/index.vue index 7596e75e4..5b542b3ce 100644 --- a/webapp/components/Editor/index.vue +++ b/webapp/components/Editor/index.vue @@ -415,9 +415,6 @@ export default { this.$emit('input', content) } }, - update(value) { - this.editor.setContent(value) - }, showLinkMenu(attrs) { this.linkUrl = attrs.href this.linkMenuIsActive = true diff --git a/webapp/locales/de.json b/webapp/locales/de.json index 5831d5e61..f920498bf 100644 --- a/webapp/locales/de.json +++ b/webapp/locales/de.json @@ -9,7 +9,7 @@ "hello": "Hallo" }, "editor": { - "placeholder": "Schreib etwas Inspirierendes …" + "placeholder": "Schreib etwas Inspirierendes..." }, "profile": { "name": "Mein Profil", diff --git a/webapp/locales/en.json b/webapp/locales/en.json index e92b2a190..6fd664425 100644 --- a/webapp/locales/en.json +++ b/webapp/locales/en.json @@ -9,7 +9,7 @@ "hello": "Hello" }, "editor": { - "placeholder": "Leave your inspirational thoughts …" + "placeholder": "Leave your inspirational thoughts..." }, "profile": { "name": "My Profile", From 7b1be0cb7d6b4c17d6c330b5537f98bd9e8d0a51 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Thu, 25 Apr 2019 17:17:12 -0300 Subject: [PATCH 36/66] Add test coverage --- .gitignore | 1 + backend/package.json | 2 ++ package.json | 4 ++- webapp/package.json | 2 ++ yarn.lock | 70 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 07094a43b..07623b965 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ cypress/screenshots/ cypress.env.json !.gitkeep +**/coverage diff --git a/backend/package.json b/backend/package.json index a258b1f27..b9660315b 100644 --- a/backend/package.json +++ b/backend/package.json @@ -26,6 +26,8 @@ "license": "MIT", "jest": { "verbose": true, + "collectCoverage": true, + "coverageReporters": ["text", "lcov"], "testMatch": [ "**/src/**/?(*.)+(spec|test).js?(x)" ] diff --git a/package.json b/package.json index 703997ee1..ec511da35 100644 --- a/package.json +++ b/package.json @@ -15,9 +15,11 @@ "cypress:webapp": "cd webapp && cross-env GRAPHQL_URI=http://localhost:4123 yarn run dev", "cypress:setup": "run-p cypress:backend:* cypress:webapp", "cypress:run": "cypress run --browser chromium", - "cypress:open": "cypress open --browser chromium" + "cypress:open": "cypress open --browser chromium", + "test:jest": "cd webapp && yarn test && cd ../backend && yarn test:jest && codecov" }, "devDependencies": { + "codecov": "^3.3.0", "cross-env": "^5.2.0", "cypress": "^3.2.0", "cypress-cucumber-preprocessor": "^1.11.0", diff --git a/webapp/package.json b/webapp/package.json index 80a0ff427..dd649c10e 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -17,6 +17,8 @@ }, "jest": { "verbose": true, + "collectCoverage": true, + "coverageReporters": ["text", "lcov"], "moduleFileExtensions": [ "js", "json", diff --git a/yarn.lock b/yarn.lock index 1d7745f03..a1f294474 100644 --- a/yarn.lock +++ b/yarn.lock @@ -762,6 +762,13 @@ acorn@^6.0.2: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.1.tgz#7d25ae05bb8ad1f9b699108e1094ecd7884adc1f" integrity sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA== +agent-base@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" + integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg== + dependencies: + es6-promisify "^5.0.0" + ajv@^6.5.5: version "6.10.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" @@ -840,6 +847,11 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +argv@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/argv/-/argv-0.0.2.tgz#ecbd16f8949b157183711b1bda334f37840185ab" + integrity sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas= + arr-diff@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" @@ -1491,6 +1503,17 @@ code-point-at@^1.0.0: resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= +codecov@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/codecov/-/codecov-3.3.0.tgz#7bf337b3f7b0474606b5c31c56dd9e44e395e15d" + integrity sha512-S70c3Eg9SixumOvxaKE/yKUxb9ihu/uebD9iPO2IR73IdP4i6ZzjXEULj3d0HeyWPr0DqBfDkjNBWxURjVO5hw== + dependencies: + argv "^0.0.2" + ignore-walk "^3.0.1" + js-yaml "^3.12.0" + teeny-request "^3.7.0" + urlgrey "^0.4.4" + coffee-react-transform@^3.1.0: version "3.3.0" resolved "https://registry.yarnpkg.com/coffee-react-transform/-/coffee-react-transform-3.3.0.tgz#f1f90fa22de8d767fca2793e3b70f0f7d7a2e467" @@ -2103,6 +2126,18 @@ es6-iterator@~2.0.3: es5-ext "^0.10.35" es6-symbol "^3.1.1" +es6-promise@^4.0.3: + version "4.2.6" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.6.tgz#b685edd8258886365ea62b57d30de28fadcd974f" + integrity sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q== + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= + dependencies: + es6-promise "^4.0.3" + es6-symbol@^3.1.1, es6-symbol@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" @@ -2632,6 +2667,14 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= +https-proxy-agent@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" + integrity sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ== + dependencies: + agent-base "^4.1.0" + debug "^3.1.0" + iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -3007,6 +3050,14 @@ js-levenshtein@^1.1.3: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-yaml@^3.12.0: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@^3.9.0: version "3.13.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.0.tgz#38ee7178ac0eea2c97ff6d96fff4b18c7d8cf98e" @@ -3509,6 +3560,11 @@ node-fetch@2.1.2: resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5" integrity sha1-q4hOjn5X44qUR1POxwb3iNF2i7U= +node-fetch@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.3.0.tgz#1a1d940bbfb916a1d3e0219f037e89e71f8c5fa5" + integrity sha512-MOd8pV3fxENbryESLgVIeaGKrdl+uaYhCSSVkjeOb/31/njTpcis5aWfdqgNlHIrKOLRbMnfPINPOML2CIFeXA== + node-pre-gyp@^0.10.0: version "0.10.3" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" @@ -4621,6 +4677,15 @@ tar@^4: safe-buffer "^5.1.2" yallist "^3.0.2" +teeny-request@^3.7.0: + version "3.11.3" + resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-3.11.3.tgz#335c629f7645e5d6599362df2f3230c4cbc23a55" + integrity sha512-CKncqSF7sH6p4rzCgkb/z/Pcos5efl0DmolzvlqRQUNcpRIruOhY9+T1FsIlyEbfWd7MsFpodROOwHYh2BaXzw== + dependencies: + https-proxy-agent "^2.2.1" + node-fetch "^2.2.0" + uuid "^3.3.2" + text-encoding@^0.6.4: version "0.6.4" resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" @@ -4847,6 +4912,11 @@ url@0.11.0, url@~0.11.0: punycode "1.3.2" querystring "0.2.0" +urlgrey@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/urlgrey/-/urlgrey-0.4.4.tgz#892fe95960805e85519f1cd4389f2cb4cbb7652f" + integrity sha1-iS/pWWCAXoVRnxzUOJ8stMu3ZS8= + use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" From 06650de30f62e813e1b5ab6e2f6aa7be7caf918e Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Thu, 25 Apr 2019 18:05:49 -0300 Subject: [PATCH 37/66] Update travis to run codecov --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index cd43b771f..9e983ec76 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,6 +31,7 @@ script: - yarn run cypress:run after_success: + - codecov --token=$CODECOV_TOKEN - wget https://raw.githubusercontent.com/DiscordHooks/travis-ci-discord-webhook/master/send.sh - chmod +x send.sh - ./send.sh success $WEBHOOK_URL From f72a6e8a42dc69a6fa5f95839dc4151b54a41b78 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Thu, 25 Apr 2019 18:37:03 -0300 Subject: [PATCH 38/66] Add codecov globally in travis.yml, add badge --- .travis.yml | 1 + README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 9e983ec76..7f1f8ccfc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ addons: before_install: - yarn global add wait-on + - yarn global add codecov - yarn install - cp cypress.env.template.json cypress.env.json diff --git a/README.md b/README.md index 3f92be96d..ac7d2a024 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # Human-Connection [![Build Status](https://travis-ci.com/Human-Connection/Human-Connection.svg?branch=master)](https://travis-ci.com/Human-Connection/Human-Connection) +[![Codecov Coverage](https://img.shields.io/codecov/c/github/Human-Connection/Human-Connection/master.svg?style=flat-square)](https://codecov.io/gh/Human-Connection/Human-Connection/) [![MIT License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/Human-Connection/Nitro-Backend/blob/backend/LICENSE.md) [![Discord Channel](https://img.shields.io/discord/489522408076738561.svg)](https://discord.gg/6ub73U3) From 341e4b9c9f29be3fd0c217d9b46a88b5ee3c3e3c Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Thu, 25 Apr 2019 19:09:31 -0300 Subject: [PATCH 39/66] Remove codecov from .travis.yml - errored out when running the latest, but was adding coverage previously --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7f1f8ccfc..cd43b771f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,6 @@ addons: before_install: - yarn global add wait-on - - yarn global add codecov - yarn install - cp cypress.env.template.json cypress.env.json @@ -32,7 +31,6 @@ script: - yarn run cypress:run after_success: - - codecov --token=$CODECOV_TOKEN - wget https://raw.githubusercontent.com/DiscordHooks/travis-ci-discord-webhook/master/send.sh - chmod +x send.sh - ./send.sh success $WEBHOOK_URL From d7102d48a1730cc3b9c8faa2610aa172a01ce518 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Fri, 26 Apr 2019 04:49:58 +0000 Subject: [PATCH 40/66] Bump eslint-plugin-jest from 22.5.0 to 22.5.1 in /backend Bumps [eslint-plugin-jest](https://github.com/jest-community/eslint-plugin-jest) from 22.5.0 to 22.5.1. - [Release notes](https://github.com/jest-community/eslint-plugin-jest/releases) - [Changelog](https://github.com/jest-community/eslint-plugin-jest/blob/master/CHANGELOG.md) - [Commits](https://github.com/jest-community/eslint-plugin-jest/compare/v22.5.0...v22.5.1) Signed-off-by: dependabot[bot] --- backend/package.json | 2 +- backend/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/package.json b/backend/package.json index a258b1f27..e9b5b9b0f 100644 --- a/backend/package.json +++ b/backend/package.json @@ -85,7 +85,7 @@ "eslint": "~5.16.0", "eslint-config-standard": "~12.0.0", "eslint-plugin-import": "~2.17.2", - "eslint-plugin-jest": "~22.5.0", + "eslint-plugin-jest": "~22.5.1", "eslint-plugin-node": "~8.0.1", "eslint-plugin-promise": "~4.1.1", "eslint-plugin-standard": "~4.0.0", diff --git a/backend/yarn.lock b/backend/yarn.lock index e66d93297..009207eca 100644 --- a/backend/yarn.lock +++ b/backend/yarn.lock @@ -3030,10 +3030,10 @@ eslint-plugin-import@~2.17.2: read-pkg-up "^2.0.0" resolve "^1.10.0" -eslint-plugin-jest@~22.5.0: - version "22.5.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.5.0.tgz#3a02527a5b08f7232f7bb0a52da98407bf84cdd0" - integrity sha512-YLeCRAuU3qP9lRZMul1/IbxXGg1THVpWFPBEa+VUQkcqEtO3W9GDKZ84MxYxzKTwMChTjj1l2vuNKva8HYtGPg== +eslint-plugin-jest@~22.5.1: + version "22.5.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.5.1.tgz#a31dfe9f9513c6af7c17ece4c65535a1370f060b" + integrity sha512-c3WjZR/HBoi4GedJRwo2OGHa8Pzo1EbSVwQ2HFzJ+4t2OoYM7Alx646EH/aaxZ+9eGcPiq0FT0UGkRuFFx2FHg== eslint-plugin-node@~8.0.1: version "8.0.1" From 589112966271cda7eaa53b7791da39109c4f14a1 Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Fri, 26 Apr 2019 08:57:29 -0300 Subject: [PATCH 41/66] Ordered comments like alpha, move HcCommentForm, mobile responsive - in the first instance, we will be importing posts/comments from the alpha, so to maintain consistency, we've ordered them alike. In the future, we could support user choice of order. - Gives more space for HcCommentForm, user can see comments added to list, helps with mobile responsiveness Co-authored-by: Tirokk Co-authored-by: Mike Aono --- backend/src/resolvers/comments.js | 2 +- webapp/components/CommentForm/index.vue | 80 ++++++++++++------------- webapp/graphql/CommentQuery.js | 4 +- webapp/locales/de.json | 2 +- webapp/locales/en.json | 2 +- webapp/pages/post/_id/_slug/index.vue | 31 +++++----- 6 files changed, 58 insertions(+), 63 deletions(-) diff --git a/backend/src/resolvers/comments.js b/backend/src/resolvers/comments.js index 60ecbcc8e..899338644 100644 --- a/backend/src/resolvers/comments.js +++ b/backend/src/resolvers/comments.js @@ -10,7 +10,7 @@ export default { const session = context.driver.session() const transactionRes = await session.run(` MATCH (comment:Comment)-[:COMMENTS]->(post:Post {id: $postId}) - RETURN comment {.id, .contentExcerpt, .createdAt}`, { + RETURN comment {.id, .contentExcerpt, .createdAt} ORDER BY comment.createdAt ASC`, { postId }) diff --git a/webapp/components/CommentForm/index.vue b/webapp/components/CommentForm/index.vue index bb71af1f7..b1f3ddf80 100644 --- a/webapp/components/CommentForm/index.vue +++ b/webapp/components/CommentForm/index.vue @@ -1,45 +1,43 @@