Merge branch 'master' into add-masonry-grid

This commit is contained in:
Alina Beck 2019-08-19 15:05:54 +01:00 committed by GitHub
commit b74c47a265
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
57 changed files with 273 additions and 398 deletions

View File

@ -42,7 +42,7 @@
] ]
}, },
"dependencies": { "dependencies": {
"@hapi/joi": "^15.1.0", "@hapi/joi": "^15.1.1",
"activitystrea.ms": "~2.1.3", "activitystrea.ms": "~2.1.3",
"apollo-cache-inmemory": "~1.6.3", "apollo-cache-inmemory": "~1.6.3",
"apollo-client": "~2.6.4", "apollo-client": "~2.6.4",

View File

@ -198,7 +198,6 @@ describe('Hashtags', () => {
Post(id: $id) { Post(id: $id) {
tags { tags {
id id
name
} }
} }
} }
@ -234,10 +233,7 @@ describe('Hashtags', () => {
}) })
it('both Hashtags are created with the "id" set to their "name"', async () => { it('both Hashtags are created with the "id" set to their "name"', async () => {
const expected = [ const expected = [{ id: 'Democracy' }, { id: 'Liberty' }]
{ id: 'Democracy', name: 'Democracy' },
{ id: 'Liberty', name: 'Liberty' },
]
await expect( await expect(
query({ query: postWithHastagsQuery, variables: postWithHastagsVariables }), query({ query: postWithHastagsQuery, variables: postWithHastagsVariables }),
).resolves.toEqual( ).resolves.toEqual(
@ -277,10 +273,7 @@ describe('Hashtags', () => {
}, },
}) })
const expected = [ const expected = [{ id: 'Elections' }, { id: 'Liberty' }]
{ id: 'Elections', name: 'Elections' },
{ id: 'Liberty', name: 'Liberty' },
]
await expect( await expect(
query({ query: postWithHastagsQuery, variables: postWithHastagsVariables }), query({ query: postWithHastagsQuery, variables: postWithHastagsVariables }),
).resolves.toEqual( ).resolves.toEqual(

View File

@ -151,7 +151,6 @@ export default {
friendsCount: '<-[:FRIENDS]->(related:User)', friendsCount: '<-[:FRIENDS]->(related:User)',
followingCount: '-[:FOLLOWS]->(related:User)', followingCount: '-[:FOLLOWS]->(related:User)',
followedByCount: '<-[:FOLLOWS]-(related:User)', followedByCount: '<-[:FOLLOWS]-(related:User)',
commentsCount: '-[:WROTE]->(r:Comment)',
commentedCount: '-[:WROTE]->(:Comment)-[:COMMENTS]->(related:Post)', commentedCount: '-[:WROTE]->(:Comment)-[:COMMENTS]->(related:Post)',
shoutedCount: '-[:SHOUTED]->(related:Post)', shoutedCount: '-[:SHOUTED]->(related:Post)',
badgesCount: '<-[:REWARDED]-(related:Badge)', badgesCount: '<-[:REWARDED]-(related:Badge)',

View File

@ -29,11 +29,6 @@ type Post {
categories: [Category]! @relation(name: "CATEGORIZED", direction: "OUT") categories: [Category]! @relation(name: "CATEGORIZED", direction: "OUT")
comments: [Comment]! @relation(name: "COMMENTS", direction: "IN") comments: [Comment]! @relation(name: "COMMENTS", direction: "IN")
commentsCount: Int!
@cypher(
statement: "MATCH (this)<-[:COMMENTS]-(r:Comment) WHERE NOT r.deleted = true AND NOT r.disabled = true RETURN COUNT(r)"
)
shoutedBy: [User]! @relation(name: "SHOUTED", direction: "IN") shoutedBy: [User]! @relation(name: "SHOUTED", direction: "IN")
shoutedCount: Int! shoutedCount: Int!
@cypher( @cypher(

View File

@ -1,6 +1,5 @@
type Tag { type Tag {
id: ID! id: ID!
name: String!
taggedPosts: [Post]! @relation(name: "TAGGED", direction: "IN") taggedPosts: [Post]! @relation(name: "TAGGED", direction: "IN")
taggedOrganizations: [Organization]! @relation(name: "TAGGED", direction: "IN") taggedOrganizations: [Organization]! @relation(name: "TAGGED", direction: "IN")
taggedCount: Int! @cypher(statement: "MATCH (this)<-[:TAGGED]-(p) RETURN COUNT(DISTINCT p)") taggedCount: Int! @cypher(statement: "MATCH (this)<-[:TAGGED]-(p) RETURN COUNT(DISTINCT p)")

View File

@ -64,7 +64,6 @@ type User {
) )
comments: [Comment]! @relation(name: "WROTE", direction: "OUT") comments: [Comment]! @relation(name: "WROTE", direction: "OUT")
commentsCount: Int! @cypher(statement: "MATCH (this)-[:WROTE]->(r:Comment) WHERE NOT r.deleted = true AND NOT r.disabled = true RETURN COUNT(r)")
commentedCount: Int! @cypher(statement: "MATCH (this)-[:WROTE]->(r:Comment)-[:COMMENTS]->(p:Post) WHERE NOT r.deleted = true AND NOT r.disabled = true AND NOT p.deleted = true AND NOT p.disabled = true RETURN COUNT(DISTINCT(p))") commentedCount: Int! @cypher(statement: "MATCH (this)-[:WROTE]->(r:Comment)-[:COMMENTS]->(p:Post) WHERE NOT r.deleted = true AND NOT r.disabled = true AND NOT p.deleted = true AND NOT p.disabled = true RETURN COUNT(DISTINCT(p))")
shouted: [Post]! @relation(name: "SHOUTED", direction: "OUT") shouted: [Post]! @relation(name: "SHOUTED", direction: "OUT")
@ -143,7 +142,6 @@ type Query {
followedByCount: Int followedByCount: Int
followedByCurrentUser: Boolean followedByCurrentUser: Boolean
contributionsCount: Int contributionsCount: Int
commentsCount: Int
commentedCount: Int commentedCount: Int
shoutedCount: Int shoutedCount: Int
badgesCount: Int badgesCount: Int

View File

@ -5,9 +5,9 @@ export default function(params) {
return { return {
mutation: ` mutation: `
mutation($id: ID!, $name: String!) { mutation($id: ID!) {
CreateTag(id: $id, name: $name) { CreateTag(id: $id) {
name id
} }
} }
`, `,

View File

@ -768,31 +768,26 @@
resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.0.0.tgz#9f05469c88cb2fd3dcd624776b54ee95c312126a" resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.0.0.tgz#9f05469c88cb2fd3dcd624776b54ee95c312126a"
integrity sha512-mV6T0IYqb0xL1UALPFplXYQmR0twnXG0M6jUswpquqT2sD12BOiCiLy3EvMp/Fy7s3DZElC4/aPjEjo2jeZpvw== integrity sha512-mV6T0IYqb0xL1UALPFplXYQmR0twnXG0M6jUswpquqT2sD12BOiCiLy3EvMp/Fy7s3DZElC4/aPjEjo2jeZpvw==
"@hapi/hoek@6.x.x": "@hapi/bourne@1.x.x":
version "6.2.4" version "1.3.2"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-6.2.4.tgz#4b95fbaccbfba90185690890bdf1a2fbbda10595" resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-1.3.2.tgz#0a7095adea067243ce3283e1b56b8a8f453b242a"
integrity sha512-HOJ20Kc93DkDVvjwHyHawPwPkX44sIrbXazAUDiUXaY2R9JwQGo2PhFfnQtdrsIe4igjG2fPgMra7NYw7qhy0A== integrity sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA==
"@hapi/hoek@8.x.x": "@hapi/hoek@8.x.x":
version "8.0.1" version "8.0.1"
resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.0.1.tgz#9712fa2ad124ac64668ab06ba847b1eaf83a03fd" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.0.1.tgz#9712fa2ad124ac64668ab06ba847b1eaf83a03fd"
integrity sha512-cctMYH5RLbElaUpZn3IJaUj9QNQD8iXDnl7xNY6KB1aFD2ciJrwpo3kvZowIT75uA+silJFDnSR2kGakALUymg== integrity sha512-cctMYH5RLbElaUpZn3IJaUj9QNQD8iXDnl7xNY6KB1aFD2ciJrwpo3kvZowIT75uA+silJFDnSR2kGakALUymg==
"@hapi/joi@^15.0.3", "@hapi/joi@^15.1.0": "@hapi/joi@^15.0.3", "@hapi/joi@^15.1.0", "@hapi/joi@^15.1.1":
version "15.1.0" version "15.1.1"
resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.1.0.tgz#940cb749b5c55c26ab3b34ce362e82b6162c8e7a" resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.1.1.tgz#c675b8a71296f02833f8d6d243b34c57b8ce19d7"
integrity sha512-n6kaRQO8S+kepUTbXL9O/UOL788Odqs38/VOfoCrATDtTvyfiO3fgjlSRaNkHabpTLgM7qru9ifqXlXbXk8SeQ== integrity sha512-entf8ZMOK8sc+8YfeOlM8pCfg3b5+WZIKBfUaaJT8UsjAAPjartzxIYm3TIbjvA4u+u++KbcXD38k682nVHDAQ==
dependencies: dependencies:
"@hapi/address" "2.x.x" "@hapi/address" "2.x.x"
"@hapi/hoek" "6.x.x" "@hapi/bourne" "1.x.x"
"@hapi/marker" "1.x.x" "@hapi/hoek" "8.x.x"
"@hapi/topo" "3.x.x" "@hapi/topo" "3.x.x"
"@hapi/marker@1.x.x":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@hapi/marker/-/marker-1.0.0.tgz#65b0b2b01d1be06304886ce9b4b77b1bfb21a769"
integrity sha512-JOfdekTXnJexfE8PyhZFyHvHjt81rBFSAbTIRAhF2vv/2Y1JzoKsGqxH/GpZJoF7aEfYok8JVcAHmSz1gkBieA==
"@hapi/topo@3.x.x": "@hapi/topo@3.x.x":
version "3.1.2" version "3.1.2"
resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-3.1.2.tgz#57cc1317be1a8c5f47c124f9b0e3c49cd78424d2" resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-3.1.2.tgz#57cc1317be1a8c5f47c124f9b0e3c49cd78424d2"

View File

@ -42,9 +42,9 @@ Given("we have a selection of tags and categories as well as posts", () => {
slug: "health-wellbeing", slug: "health-wellbeing",
icon: "medkit" icon: "medkit"
}) })
.create("Tag", { id: "t1", name: "Ecology" }) .create("Tag", { id: "Ecology" })
.create("Tag", { id: "t2", name: "Nature" }) .create("Tag", { id: "Nature" })
.create("Tag", { id: "t3", name: "Democracy" }); .create("Tag", { id: "Democracy" });
const someAuthor = { const someAuthor = {
id: "authorId", id: "authorId",
@ -71,14 +71,14 @@ Given("we have a selection of tags and categories as well as posts", () => {
.relate("Post", "Categories", { from: "p0", to: "cat1" }) .relate("Post", "Categories", { from: "p0", to: "cat1" })
.relate("Post", "Categories", { from: "p1", to: "cat2" }) .relate("Post", "Categories", { from: "p1", to: "cat2" })
.relate("Post", "Categories", { from: "p2", to: "cat1" }) .relate("Post", "Categories", { from: "p2", to: "cat1" })
.relate("Post", "Tags", { from: "p0", to: "t1" }) .relate("Post", "Tags", { from: "p0", to: "Ecology" })
.relate("Post", "Tags", { from: "p0", to: "t2" }) .relate("Post", "Tags", { from: "p0", to: "Nature" })
.relate("Post", "Tags", { from: "p0", to: "t3" }) .relate("Post", "Tags", { from: "p0", to: "Democracy" })
.relate("Post", "Tags", { from: "p1", to: "t2" }) .relate("Post", "Tags", { from: "p1", to: "Nature" })
.relate("Post", "Tags", { from: "p1", to: "t3" }) .relate("Post", "Tags", { from: "p1", to: "Democracy" })
.relate("Post", "Tags", { from: "p2", to: "t2" }) .relate("Post", "Tags", { from: "p2", to: "Nature" })
.relate("Post", "Tags", { from: "p2", to: "t3" }) .relate("Post", "Tags", { from: "p2", to: "Democracy" })
.relate("Post", "Tags", { from: "p3", to: "t3" }); .relate("Post", "Tags", { from: "p3", to: "Democracy" });
}); });
Given("we have the following user accounts:", table => { Given("we have the following user accounts:", table => {
@ -260,7 +260,7 @@ Then("the first post on the landing page has the title:", title => {
Then( Then(
"the page {string} returns a 404 error with a message:", "the page {string} returns a 404 error with a message:",
(route, message) => { (route, message) => {
// TODO: how can we check HTTP codes with cypress? cy.request({ url: route, failOnStatusCode: false }).its('status').should('eq', 404)
cy.visit(route, { failOnStatusCode: false }); cy.visit(route, { failOnStatusCode: false });
cy.get(".error").should("contain", message); cy.get(".error").should("contain", message);
} }

View File

@ -38,14 +38,12 @@ export_collection "emotions"
export_collection_query "follows" "{'foreignService': 'organizations'}" "organizations" export_collection_query "follows" "{'foreignService': 'organizations'}" "organizations"
export_collection_query "follows" "{'foreignService': 'users'}" "users" export_collection_query "follows" "{'foreignService': 'users'}" "users"
export_collection "invites" export_collection "invites"
export_collection "notifications"
export_collection "organizations" export_collection "organizations"
export_collection "pages" export_collection "pages"
export_collection "projects" export_collection "projects"
export_collection "settings" export_collection "settings"
export_collection "shouts" export_collection "shouts"
export_collection "status" export_collection "status"
export_collection "systemnotifications"
export_collection "users" export_collection "users"
export_collection "userscandos" export_collection "userscandos"
export_collection "usersettings" export_collection "usersettings"

View File

@ -148,6 +148,6 @@ MATCH (c:Category {id: categoryId})
MERGE (p)-[:CATEGORIZED]->(c) MERGE (p)-[:CATEGORIZED]->(c)
WITH p, post.tags AS tags WITH p, post.tags AS tags
UNWIND tags AS tag UNWIND tags AS tag
MERGE (t:Tag {id: tag, name: tag}) MERGE (t:Tag {id: apoc.text.clean(tag), disabled: false, deleted: false})
MERGE (p)-[:TAGGED]->(t) MERGE (p)-[:TAGGED]->(t)
; ;

View File

@ -1 +1,2 @@
MATCH (n:User) DETACH DELETE n; MATCH (n:User) DETACH DELETE n;
MATCH (e:EmailAddress) DETACH DELETE e;

View File

@ -94,12 +94,11 @@
} }
} }
*/ */
CALL apoc.load.json("file:${IMPORT_CHUNK_PATH_CQL_FILE}") YIELD value as user CALL apoc.load.json("file:${IMPORT_CHUNK_PATH_CQL_FILE}") YIELD value as user
MERGE(u:User {id: user._id["$oid"]}) MERGE(u:User {id: user._id["$oid"]})
ON CREATE SET ON CREATE SET
u.name = user.name, u.name = user.name,
u.slug = user.slug, u.slug = COALESCE(user.slug, apoc.text.random(20, "[A-Za-z]")),
u.email = user.email, u.email = user.email,
u.encryptedPassword = user.password, u.encryptedPassword = user.password,
u.avatar = replace(user.avatar, 'https://api-alpha.human-connection.org', ''), u.avatar = replace(user.avatar, 'https://api-alpha.human-connection.org', ''),

View File

@ -29,7 +29,6 @@ CREATE CONSTRAINT ON (u:User) ASSERT u.id IS UNIQUE;
CREATE CONSTRAINT ON (o:Organization) ASSERT o.id IS UNIQUE; CREATE CONSTRAINT ON (o:Organization) ASSERT o.id IS UNIQUE;
CREATE CONSTRAINT ON (t:Tag) ASSERT t.id IS UNIQUE; CREATE CONSTRAINT ON (t:Tag) ASSERT t.id IS UNIQUE;
CREATE CONSTRAINT ON (p:Post) ASSERT p.slug IS UNIQUE; CREATE CONSTRAINT ON (p:Post) ASSERT p.slug IS UNIQUE;
CREATE CONSTRAINT ON (c:Category) ASSERT c.slug IS UNIQUE; CREATE CONSTRAINT ON (c:Category) ASSERT c.slug IS UNIQUE;
CREATE CONSTRAINT ON (u:User) ASSERT u.slug IS UNIQUE; CREATE CONSTRAINT ON (u:User) ASSERT u.slug IS UNIQUE;

View File

@ -67,7 +67,7 @@ import { mapGetters, mapMutations } from 'vuex'
import HcUser from '~/components/User' import HcUser from '~/components/User'
import ContentMenu from '~/components/ContentMenu' import ContentMenu from '~/components/ContentMenu'
import ContentViewer from '~/components/Editor/ContentViewer' import ContentViewer from '~/components/Editor/ContentViewer'
import HcEditCommentForm from '~/components/comments/EditCommentForm/EditCommentForm' import HcEditCommentForm from '~/components/EditCommentForm/EditCommentForm'
export default { export default {
data: function() { data: function() {

View File

@ -1,5 +1,5 @@
import { mount, createLocalVue } from '@vue/test-utils' import { mount, createLocalVue } from '@vue/test-utils'
import CommentForm from './index.vue' import CommentForm from './CommentForm'
import Styleguide from '@human-connection/styleguide' import Styleguide from '@human-connection/styleguide'
import Vuex from 'vuex' import Vuex from 'vuex'
import MutationObserver from 'mutation-observer' import MutationObserver from 'mutation-observer'

View File

@ -24,10 +24,10 @@
<script> <script>
import gql from 'graphql-tag' import gql from 'graphql-tag'
import HcEditor from '~/components/Editor/Editor'
import PostCommentsQuery from '~/graphql/PostCommentsQuery.js'
import CommentMutations from '~/graphql/CommentMutations.js'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import HcEditor from '~/components/Editor/Editor'
import PostQuery from '~/graphql/PostQuery'
import CommentMutations from '~/graphql/CommentMutations'
export default { export default {
components: { components: {
@ -35,7 +35,6 @@ export default {
}, },
props: { props: {
post: { type: Object, default: () => {} }, post: { type: Object, default: () => {} },
comments: { type: Array, default: () => [] },
}, },
data() { data() {
return { return {
@ -70,18 +69,18 @@ export default {
this.disabled = true this.disabled = true
this.$apollo this.$apollo
.mutate({ .mutate({
mutation: CommentMutations().CreateComment, mutation: CommentMutations(this.$i18n).CreateComment,
variables: { variables: {
postId: this.post.id, postId: this.post.id,
content: this.form.content, content: this.form.content,
}, },
update: (store, { data: { CreateComment } }) => { update: (store, { data: { CreateComment } }) => {
const data = store.readQuery({ const data = store.readQuery({
query: PostCommentsQuery(this.$i18n), query: PostQuery(this.$i18n),
variables: { slug: this.post.slug }, variables: { slug: this.post.slug },
}) })
data.Post[0].comments.push(CreateComment) data.Post[0].comments.push(CreateComment)
store.writeQuery({ query: PostCommentsQuery(this.$i18n), data }) store.writeQuery({ query: PostQuery(this.$i18n), data })
}, },
}) })
.then(res => { .then(res => {
@ -98,14 +97,16 @@ export default {
apollo: { apollo: {
User: { User: {
query() { query() {
return gql(`{ return gql`
User(orderBy: slug_asc) { {
id User(orderBy: slug_asc) {
slug id
name slug
avatar name
avatar
}
} }
}`) `
}, },
result(result) { result(result) {
this.users = result.data.User this.users = result.data.User

View File

@ -1,5 +1,5 @@
import { config, mount, createLocalVue } from '@vue/test-utils' import { config, mount, createLocalVue } from '@vue/test-utils'
import CommentList from '.' import CommentList from './CommentList'
import Empty from '~/components/Empty' import Empty from '~/components/Empty'
import Vuex from 'vuex' import Vuex from 'vuex'
import Styleguide from '@human-connection/styleguide' import Styleguide from '@human-connection/styleguide'
@ -21,63 +21,52 @@ describe('CommentList.vue', () => {
let store let store
let wrapper let wrapper
let propsData let propsData
let data
propsData = {
post: {
id: 1,
},
}
store = new Vuex.Store({
getters: {
'auth/user': () => {
return {}
},
},
})
mocks = {
$t: jest.fn(),
$filters: {
truncate: a => a,
},
$apollo: {
queries: {
Post: {
refetch: jest.fn(),
},
},
},
}
data = () => {
return {
comments: [],
}
}
describe('shallowMount', () => { describe('shallowMount', () => {
beforeEach(() => {
propsData = {
post: {
id: 1,
comments: [{ id: 'comment134', contentExcerpt: 'this is a comment' }],
},
}
store = new Vuex.Store({
getters: {
'auth/user': () => {
return {}
},
},
})
mocks = {
$t: jest.fn(),
$filters: {
truncate: a => a,
},
$apollo: {
queries: {
Post: {
refetch: jest.fn(),
},
},
},
}
})
const Wrapper = () => { const Wrapper = () => {
return mount(CommentList, { return mount(CommentList, {
store, store,
mocks, mocks,
localVue, localVue,
propsData, propsData,
data,
}) })
} }
beforeEach(() => { beforeEach(() => {
wrapper = Wrapper() wrapper = Wrapper()
wrapper.setData({
comments: [
{
id: 'c1',
contentExcerpt: 'this is a comment',
},
],
})
}) })
it('displays a message icon when there are no comments to display', () => { it('displays a message icon when there are no comments to display', () => {
propsData.post.comments = []
expect(Wrapper().findAll(Empty)).toHaveLength(1) expect(Wrapper().findAll(Empty)).toHaveLength(1)
}) })

View File

@ -4,25 +4,25 @@
<span> <span>
<ds-icon name="comments" /> <ds-icon name="comments" />
<ds-tag <ds-tag
v-if="comments" v-if="post.comments.length"
style="margin-top: -4px; margin-left: -12px; position: absolute;" style="margin-top: -4px; margin-left: -12px; position: absolute;"
color="primary" color="primary"
size="small" size="small"
round round
> >
{{ comments.length }} {{ post.comments.length }}
</ds-tag> </ds-tag>
&nbsp; Comments &nbsp; Comments
</span> </span>
</h3> </h3>
<ds-space margin-bottom="large" /> <ds-space margin-bottom="large" />
<div v-if="comments && comments.length" id="comments" class="comments"> <div v-if="post.comments && post.comments.length" id="comments" class="comments">
<comment <comment
v-for="(comment, index) in comments" v-for="(comment, index) in post.comments"
:key="comment.id" :key="comment.id"
:comment="comment" :comment="comment"
:post="post" :post="post"
@deleteComment="comments.splice(index, 1)" @deleteComment="post.comments.splice(index, 1)"
/> />
</div> </div>
<hc-empty v-else name="empty" icon="messages" /> <hc-empty v-else name="empty" icon="messages" />
@ -31,7 +31,6 @@
<script> <script>
import Comment from '~/components/Comment.vue' import Comment from '~/components/Comment.vue'
import HcEmpty from '~/components/Empty.vue' import HcEmpty from '~/components/Empty.vue'
import PostCommentsQuery from '~/graphql/PostCommentsQuery.js'
export default { export default {
components: { components: {
@ -41,29 +40,5 @@ export default {
props: { props: {
post: { type: Object, default: () => {} }, post: { type: Object, default: () => {} },
}, },
data() {
return {
comments: [],
}
},
watch: {
Post(post) {
const [first] = post
this.comments = (first && first.comments) || []
},
},
apollo: {
Post: {
query() {
return PostCommentsQuery(this.$i18n)
},
variables() {
return {
slug: this.post.slug,
}
},
fetchPolicy: 'cache-and-network',
},
},
} }
</script> </script>

View File

@ -244,9 +244,8 @@ export default {
query() { query() {
return gql` return gql`
{ {
Tag(orderBy: name_asc) { Tag(orderBy: id_asc) {
id id
name
} }
} }
` `

View File

@ -2,7 +2,7 @@
<span> <span>
<no-ssr placeholder="0" tag="span"> <no-ssr placeholder="0" tag="span">
<count-to <count-to
:start-val="lastEndVal || startVal" :start-val="startVal"
:end-val="endVal" :end-val="endVal"
:duration="duration" :duration="duration"
:autoplay="autoplay" :autoplay="autoplay"
@ -20,28 +20,10 @@ export default {
}, },
props: { props: {
startVal: { type: Number, default: 0 }, startVal: { type: Number, default: 0 },
endVal: { type: Number, required: true }, endVal: { type: Number, default: 0 },
duration: { type: Number, default: 3000 }, duration: { type: Number, default: 3000 },
autoplay: { type: Boolean, default: true }, autoplay: { type: Boolean, default: true },
separator: { type: String, default: '.' }, separator: { type: String, default: '.' },
}, },
data() {
return {
lastEndVal: null,
isReady: false,
}
},
watch: {
endVal(endVal) {
if (this.isReady && this.startVal === 0 && !this.lastEndVal) {
this.lastEndVal = this.endVal
}
},
},
mounted() {
setTimeout(() => {
this.isReady = true
}, 500)
},
} }
</script> </script>

View File

@ -48,7 +48,7 @@ describe('DeleteData.vue', () => {
} }
getters = { getters = {
'auth/user': () => { 'auth/user': () => {
return { id: 'u343', name: deleteAccountName, contributionsCount: 2, commentsCount: 3 } return { id: 'u343', name: deleteAccountName, contributionsCount: 2, commentedCount: 3 }
}, },
} }
actions = { 'auth/logout': jest.fn() } actions = { 'auth/logout': jest.fn() }

View File

@ -30,12 +30,12 @@
}} }}
</label> </label>
<ds-space margin-bottom="small" /> <ds-space margin-bottom="small" />
<label v-if="currentUser.commentsCount" class="checkbox-container"> <label v-if="currentUser.commentedCount" class="checkbox-container">
<input type="checkbox" v-model="deleteComments" /> <input type="checkbox" v-model="deleteComments" />
<span class="checkmark"></span> <span class="checkmark"></span>
{{ {{
$t('settings.deleteUserAccount.commentsCount', { $t('settings.deleteUserAccount.commentedCount', {
count: currentUser.commentsCount, count: currentUser.commentedCount,
}) })
}} }}
</label> </label>

View File

@ -12,15 +12,13 @@
@click="selectItem(item)" @click="selectItem(item)"
> >
<div v-if="isMention">@{{ item.slug }}</div> <div v-if="isMention">@{{ item.slug }}</div>
<div v-if="isHashtag">#{{ item.name }}</div> <div v-if="isHashtag">#{{ item.id }}</div>
</div> </div>
<div v-if="isHashtag"> <div v-if="isHashtag">
<!-- if query is not empty and is find fully in the suggestions array ... --> <!-- if query is not empty and is find fully in the suggestions array ... -->
<div v-if="query && !filteredItems.find(el => el.name === query)"> <div v-if="query && !filteredItems.find(el => el.id === query)">
<div class="suggestion-list__item is-empty">{{ $t('editor.hashtag.addHashtag') }}</div> <div class="suggestion-list__item is-empty">{{ $t('editor.hashtag.addHashtag') }}</div>
<div class="suggestion-list__item" @click="selectItem({ name: query })"> <div class="suggestion-list__item" @click="selectItem({ id: query })">#{{ query }}</div>
#{{ query }}
</div>
</div> </div>
<!-- otherwise if sanitized query is empty advice the user to add a char --> <!-- otherwise if sanitized query is empty advice the user to add a char -->
<div v-else-if="!query"> <div v-else-if="!query">
@ -40,9 +38,7 @@
<!-- if "query" is not empty --> <!-- if "query" is not empty -->
<div v-else> <div v-else>
<div class="suggestion-list__item is-empty">{{ $t('editor.hashtag.addHashtag') }}</div> <div class="suggestion-list__item is-empty">{{ $t('editor.hashtag.addHashtag') }}</div>
<div class="suggestion-list__item" @click="selectItem({ name: query })"> <div class="suggestion-list__item" @click="selectItem({ id: query })">#{{ query }}</div>
#{{ query }}
</div>
</div> </div>
</div> </div>
</div> </div>
@ -455,7 +451,7 @@ export default {
// For hashtags handles pressing of space. // For hashtags handles pressing of space.
spaceHandler() { spaceHandler() {
if (this.suggestionType === this.hashtagSuggestionType && this.query !== '') { if (this.suggestionType === this.hashtagSuggestionType && this.query !== '') {
this.selectItem({ name: this.query }) this.selectItem({ id: this.query })
} }
}, },
// we have to replace our suggestion text with a mention // we have to replace our suggestion text with a mention
@ -467,8 +463,8 @@ export default {
label: item.slug, label: item.slug,
}, },
hashtag: { hashtag: {
id: item.name, id: item.id,
label: item.name, label: item.id,
}, },
} }
this.insertMentionOrHashtag({ this.insertMentionOrHashtag({

View File

@ -24,7 +24,7 @@ const post = {
deleted: false, deleted: false,
contributionsCount: 25, contributionsCount: 25,
shoutedCount: 5, shoutedCount: 5,
commentsCount: 39, commentedCount: 39,
followedByCount: 2, followedByCount: 2,
followedByCurrentUser: true, followedByCurrentUser: true,
location: null, location: null,
@ -38,7 +38,7 @@ const post = {
], ],
__typename: 'User', __typename: 'User',
}, },
commentsCount: 12, commentedCount: 12,
categories: [], categories: [],
shoutedCount: 421, shoutedCount: 421,
__typename: 'Post', __typename: 'Post',

View File

@ -44,25 +44,25 @@
</div> </div>
<no-ssr> <no-ssr>
<div style="display: inline-block; float: right"> <div style="display: inline-block; float: right">
<!-- Shouts Count --> <!-- Shouts Count -->
<span :style="{ opacity: post.shoutedCount ? 1 : 0.5 }"> <span :style="{ opacity: post.shoutedCount ? 1 : 0.5 }">
<ds-icon name="bullhorn" /> <ds-icon name="bullhorn" />
<small>{{ post.shoutedCount }}</small> <small>{{ post.shoutedCount }}</small>
</span> </span>
&nbsp; &nbsp;
<!-- Comments Count --> <!-- Comments Count -->
<span :style="{ opacity: post.commentsCount ? 1 : 0.5 }"> <span :style="{ opacity: post.commentedCount ? 1 : 0.5 }">
<ds-icon name="comments" /> <ds-icon name="comments" />
<small>{{ post.commentsCount }}</small> <small>{{ post.commentedCount }}</small>
</span> </span>
<!-- Menu --> <!-- Menu -->
<content-menu <content-menu
resource-type="contribution" resource-type="contribution"
:resource="post" :resource="post"
:modalsData="menuModalsData" :modalsData="menuModalsData"
:is-owner="isAuthor" :is-owner="isAuthor"
/> />
</div> </div>
</no-ssr> </no-ssr>
</template> </template>
</ds-card> </ds-card>

View File

@ -122,7 +122,7 @@ describe('SearchInput.vue', () => {
name: 'Trick', name: 'Trick',
slug: 'trick', slug: 'trick',
}, },
commentsCount: 0, commentedCount: 0,
createdAt: '2019-03-13T11:00:20.835Z', createdAt: '2019-03-13T11:00:20.835Z',
id: 'p10', id: 'p10',
label: 'Eos aut illo omnis quis eaque et iure aut.', label: 'Eos aut illo omnis quis eaque et iure aut.',

View File

@ -46,7 +46,7 @@
<ds-flex-item> <ds-flex-item>
<ds-text size="small" color="softer" class="search-meta"> <ds-text size="small" color="softer" class="search-meta">
<span style="text-align: right;"> <span style="text-align: right;">
<b>{{ option.commentsCount }}</b> <b>{{ option.commentedCount }}</b>
<ds-icon name="comments" /> <ds-icon name="comments" />
</span> </span>
<span style="width: 36px; display: inline-block; text-align: right;"> <span style="width: 36px; display: inline-block; text-align: right;">

View File

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

View File

@ -6,20 +6,20 @@ const localVue = createLocalVue()
localVue.use(Styleguide) localVue.use(Styleguide)
describe('Tag', () => { describe('Tag', () => {
let name let id
let Wrapper = () => { let Wrapper = () => {
return shallowMount(Tag, { return shallowMount(Tag, {
localVue, localVue,
propsData: { propsData: {
name, id,
}, },
}) })
} }
describe('given a String for Name', () => { describe('given a String for Name', () => {
beforeEach(() => { beforeEach(() => {
name = 'Liebe' id = 'Liebe'
}) })
it('shows Name', () => { it('shows Name', () => {

View File

@ -50,7 +50,11 @@
<ds-flex style="margin-top: -10px"> <ds-flex style="margin-top: -10px">
<ds-flex-item class="ds-tab-nav-item"> <ds-flex-item class="ds-tab-nav-item">
<ds-space margin="small"> <ds-space margin="small">
<ds-number :count="fanCount" :label="$t('profile.followers')" size="x-large" /> <ds-number
:count="user.followedByCount"
:label="$t('profile.followers')"
size="x-large"
/>
</ds-space> </ds-space>
</ds-flex-item> </ds-flex-item>
<ds-flex-item class="ds-tab-nav-item ds-tab-nav-item-active"> <ds-flex-item class="ds-tab-nav-item ds-tab-nav-item-active">
@ -64,8 +68,8 @@
<ds-flex-item class="ds-tab-nav-item"> <ds-flex-item class="ds-tab-nav-item">
<ds-space margin="small"> <ds-space margin="small">
<ds-number <ds-number
:count="user.commentsCount" :count="user.commentedCount"
:label="$t('common.comment', null, user.commentsCount)" :label="$t('common.comment', null, user.commentedCount)"
/> />
</ds-space> </ds-space>
</ds-flex-item> </ds-flex-item>
@ -121,10 +125,6 @@ export default {
itsMe() { itsMe() {
return this.user.slug === this.$store.getters['auth/user'].slug return this.user.slug === this.$store.getters['auth/user'].slug
}, },
fanCount() {
let count = Number(this.user.followedByCount) || 0
return count
},
userLink() { userLink() {
const { id, slug } = this.user const { id, slug } = this.user
if (!(id && slug)) return '' if (!(id && slug)) return ''

View File

@ -1,6 +1,6 @@
import gql from 'graphql-tag' import gql from 'graphql-tag'
export default () => { export default i18n => {
return { return {
CreateComment: gql` CreateComment: gql`
mutation($postId: ID!, $content: String!) { mutation($postId: ID!, $content: String!) {
@ -8,15 +8,26 @@ export default () => {
id id
contentExcerpt contentExcerpt
content content
createdAt
disabled
deleted
author { author {
id id
slug slug
name name
avatar avatar
disabled
deleted
shoutedCount
contributionsCount
commentedCount
followedByCount
followedByCurrentUser
badges {
id
icon
}
} }
createdAt
deleted
disabled
} }
} }
`, `,
@ -24,8 +35,19 @@ export default () => {
mutation($content: String!, $id: ID!) { mutation($content: String!, $id: ID!) {
UpdateComment(content: $content, id: $id) { UpdateComment(content: $content, id: $id) {
id id
content
contentExcerpt contentExcerpt
content
createdAt
disabled
deleted
author {
id
slug
name
avatar
disabled
deleted
}
} }
} }
`, `,

View File

@ -17,7 +17,7 @@ export default app => {
deleted deleted
shoutedCount shoutedCount
contributionsCount contributionsCount
commentsCount commentedCount
followedByCount followedByCount
followedByCurrentUser followedByCurrentUser
location { location {

View File

@ -1,39 +0,0 @@
import gql from 'graphql-tag'
export default i18n => {
const lang = i18n.locale().toUpperCase()
return gql(`
query Post($slug: String!) {
Post(slug: $slug) {
comments(orderBy: createdAt_asc) {
id
contentExcerpt
content
createdAt
disabled
deleted
author {
id
slug
name
avatar
disabled
deleted
shoutedCount
contributionsCount
commentsCount
followedByCount
followedByCurrentUser
location {
name: name${lang}
}
badges {
id
icon
}
}
}
}
}
`)
}

View File

@ -22,7 +22,7 @@ export default i18n => {
deleted deleted
shoutedCount shoutedCount
contributionsCount contributionsCount
commentsCount commentedCount
followedByCount followedByCount
followedByCurrentUser followedByCurrentUser
location { location {
@ -34,12 +34,12 @@ export default i18n => {
} }
} }
tags { tags {
name id
} }
commentsCount comments(orderBy: createdAt_asc) {
comments(orderBy: createdAt_desc) {
id id
contentExcerpt contentExcerpt
content
createdAt createdAt
disabled disabled
deleted deleted
@ -52,7 +52,7 @@ export default i18n => {
deleted deleted
shoutedCount shoutedCount
contributionsCount contributionsCount
commentsCount commentedCount
followedByCount followedByCount
followedByCurrentUser followedByCurrentUser
location { location {
@ -99,7 +99,7 @@ export const filterPosts = i18n => {
deleted deleted
contributionsCount contributionsCount
shoutedCount shoutedCount
commentsCount commentedCount
followedByCount followedByCount
followedByCurrentUser followedByCurrentUser
location { location {
@ -110,7 +110,6 @@ export const filterPosts = i18n => {
icon icon
} }
} }
commentsCount
categories { categories {
id id
name name

View File

@ -2,7 +2,7 @@ import gql from 'graphql-tag'
export default i18n => { export default i18n => {
const lang = i18n.locale().toUpperCase() const lang = i18n.locale().toUpperCase()
return gql(` return gql`
query User($id: ID!) { query User($id: ID!) {
User(id: $id) { User(id: $id) {
id id
@ -35,7 +35,7 @@ export default i18n => {
followedByCount followedByCount
followedByCurrentUser followedByCurrentUser
contributionsCount contributionsCount
commentsCount commentedCount
badges { badges {
id id
icon icon
@ -57,7 +57,7 @@ export default i18n => {
followedByCount followedByCount
followedByCurrentUser followedByCurrentUser
contributionsCount contributionsCount
commentsCount commentedCount
badges { badges {
id id
icon icon
@ -66,12 +66,11 @@ export default i18n => {
name: name${lang} name: name${lang}
} }
} }
contributionsCount
socialMedia { socialMedia {
id id
url url
} }
} }
} }
`) `
} }

View File

@ -1,38 +0,0 @@
import gql from 'graphql-tag'
export default i18n => {
const lang = i18n.locale().toUpperCase()
return gql(`
query Post($filter: _PostFilter, $first: Int, $offset: Int) {
Post(filter: $filter, first: $first, offset: $offset, orderBy: createdAt_desc) {
id
slug
title
contentExcerpt
shoutedCount
commentsCount
deleted
image
createdAt
disabled
deleted
categories {
id
name
icon
}
author {
id
slug
avatar
name
disabled
deleted
location {
name: name${lang}
}
}
}
}
`)
}

View File

@ -1,7 +1,7 @@
import gql from 'graphql-tag' import gql from 'graphql-tag'
export const BlockedUsers = () => { export const BlockedUsers = () => {
return gql(` return gql`
{ {
blockedUsers { blockedUsers {
id id
@ -13,27 +13,31 @@ export const BlockedUsers = () => {
deleted deleted
} }
} }
`) `
} }
export const Block = () => { export const Block = () => {
return gql(`mutation($id:ID!) { return gql`
block(id: $id) { mutation($id: ID!) {
id block(id: $id) {
name id
isBlocked name
followedByCurrentUser isBlocked
followedByCurrentUser
}
} }
}`) `
} }
export const Unblock = () => { export const Unblock = () => {
return gql(`mutation($id:ID!) { return gql`
unblock(id: $id) { mutation($id: ID!) {
id unblock(id: $id) {
name id
isBlocked name
followedByCurrentUser isBlocked
followedByCurrentUser
}
} }
}`) `
} }

View File

@ -171,7 +171,7 @@
"deleteUserAccount": { "deleteUserAccount": {
"name": "Daten löschen", "name": "Daten löschen",
"contributionsCount": "Meine {count} Beiträge löschen", "contributionsCount": "Meine {count} Beiträge löschen",
"commentsCount": "Meine {count} Kommentare löschen", "commentedCount": "Meine {count} Kommentare löschen",
"accountDescription": "Sei dir bewusst, dass deine Beiträge und Kommentare für unsere Community wichtig sind. Wenn du sie trotzdem löschen möchtest, musst du sie unten markieren.", "accountDescription": "Sei dir bewusst, dass deine Beiträge und Kommentare für unsere Community wichtig sind. Wenn du sie trotzdem löschen möchtest, musst du sie unten markieren.",
"accountWarning": "Dein Konto, deine Beiträge oder Kommentare kannst du nach dem Löschen <b>WEDER VERWALTEN NOCH WIEDERHERSTELLEN!</b>", "accountWarning": "Dein Konto, deine Beiträge oder Kommentare kannst du nach dem Löschen <b>WEDER VERWALTEN NOCH WIEDERHERSTELLEN!</b>",
"success": "Konto erfolgreich gelöscht!", "success": "Konto erfolgreich gelöscht!",

View File

@ -171,7 +171,7 @@
"deleteUserAccount": { "deleteUserAccount": {
"name": "Delete data", "name": "Delete data",
"contributionsCount": "Delete my {count} posts", "contributionsCount": "Delete my {count} posts",
"commentsCount": "Delete my {count} comments", "commentedCount": "Delete my {count} comments",
"accountDescription": "Be aware that your Post and Comments are important to our community. If you still choose to delete them, you have to mark them below.", "accountDescription": "Be aware that your Post and Comments are important to our community. If you still choose to delete them, you have to mark them below.",
"accountWarning": "You <b>CAN'T MANAGE</b> and <b>CAN'T RECOVER</b> your Account, Posts, or Comments after deleting your account!", "accountWarning": "You <b>CAN'T MANAGE</b> and <b>CAN'T RECOVER</b> your Account, Posts, or Comments after deleting your account!",
"success": "Account successfully deleted!", "success": "Account successfully deleted!",

View File

@ -121,7 +121,7 @@
"deleteUserAccount": { "deleteUserAccount": {
"name": "Usuń dane", "name": "Usuń dane",
"contributionsCount": "Usuń {count} moich postów", "contributionsCount": "Usuń {count} moich postów",
"commentsCount": "Usuń {count} moich komentarzy", "commentedCount": "Usuń {count} moich komentarzy",
"accountDescription": "Be aware that your Post and Comments are important to our community. If you still choose to delete them, you have to mark them below.", "accountDescription": "Be aware that your Post and Comments are important to our community. If you still choose to delete them, you have to mark them below.",
"accountWarning": "Po usunięcie Twojego konta, nie możesz <b>ZARZĄDZAĆ</b> ani <b>ODZYSKAĆ</b> danych, wpisów oraz komentarzy!", "accountWarning": "Po usunięcie Twojego konta, nie możesz <b>ZARZĄDZAĆ</b> ani <b>ODZYSKAĆ</b> danych, wpisów oraz komentarzy!",
"success": "Konto zostało usunięte", "success": "Konto zostało usunięte",

View File

@ -100,6 +100,7 @@ module.exports = {
{ src: '~/plugins/v-tooltip.js', ssr: false }, { src: '~/plugins/v-tooltip.js', ssr: false },
{ src: '~/plugins/izi-toast.js', ssr: false }, { src: '~/plugins/izi-toast.js', ssr: false },
{ src: '~/plugins/vue-filters.js' }, { src: '~/plugins/vue-filters.js' },
{ src: '~/plugins/vue-infinite-scroll.js', ssr: false },
], ],
router: { router: {

View File

@ -76,6 +76,7 @@
"tiptap-extensions": "~1.26.2", "tiptap-extensions": "~1.26.2",
"v-tooltip": "~2.0.2", "v-tooltip": "~2.0.2",
"vue-count-to": "~1.0.13", "vue-count-to": "~1.0.13",
"vue-infinite-scroll": "^2.0.2",
"vue-izitoast": "roschaefer/vue-izitoast#patch-1", "vue-izitoast": "roschaefer/vue-izitoast#patch-1",
"vuex-i18n": "~1.13.1", "vuex-i18n": "~1.13.1",
"vue-sweetalert-icons": "~4.2.0", "vue-sweetalert-icons": "~4.2.0",

View File

@ -7,7 +7,7 @@
<ds-space margin="small"> <ds-space margin="small">
<ds-number :count="0" :label="$t('admin.dashboard.users')" size="x-large" uppercase> <ds-number :count="0" :label="$t('admin.dashboard.users')" size="x-large" uppercase>
<no-ssr slot="count"> <no-ssr slot="count">
<hc-count-to :start-val="0" :end-val="statistics.countUsers || 0" /> <hc-count-to :end-val="statistics.countUsers" />
</no-ssr> </no-ssr>
</ds-number> </ds-number>
</ds-space> </ds-space>
@ -16,7 +16,7 @@
<ds-space margin="small"> <ds-space margin="small">
<ds-number :count="0" :label="$t('admin.dashboard.posts')" size="x-large" uppercase> <ds-number :count="0" :label="$t('admin.dashboard.posts')" size="x-large" uppercase>
<no-ssr slot="count"> <no-ssr slot="count">
<hc-count-to :start-val="0" :end-val="statistics.countPosts || 0" /> <hc-count-to :end-val="statistics.countPosts" />
</no-ssr> </no-ssr>
</ds-number> </ds-number>
</ds-space> </ds-space>
@ -30,7 +30,7 @@
uppercase uppercase
> >
<no-ssr slot="count"> <no-ssr slot="count">
<hc-count-to :start-val="0" :end-val="statistics.countComments || 0" /> <hc-count-to :end-val="statistics.countComments" />
</no-ssr> </no-ssr>
</ds-number> </ds-number>
</ds-space> </ds-space>
@ -44,7 +44,7 @@
uppercase uppercase
> >
<no-ssr slot="count"> <no-ssr slot="count">
<hc-count-to :start-val="0" :end-val="statistics.countNotifications || 0" /> <hc-count-to :end-val="statistics.countNotifications" />
</no-ssr> </no-ssr>
</ds-number> </ds-number>
</ds-space> </ds-space>
@ -58,7 +58,7 @@
uppercase uppercase
> >
<no-ssr slot="count"> <no-ssr slot="count">
<hc-count-to :start-val="0" :end-val="statistics.countOrganizations || 0" /> <hc-count-to :end-val="statistics.countOrganizations" />
</no-ssr> </no-ssr>
</ds-number> </ds-number>
</ds-space> </ds-space>
@ -72,7 +72,7 @@
uppercase uppercase
> >
<no-ssr slot="count"> <no-ssr slot="count">
<hc-count-to :start-val="0" :end-val="statistics.countProjects || 0" /> <hc-count-to :end-val="statistics.countProjects" />
</no-ssr> </no-ssr>
</ds-number> </ds-number>
</ds-space> </ds-space>
@ -81,7 +81,7 @@
<ds-space margin="small"> <ds-space margin="small">
<ds-number :count="0" :label="$t('admin.dashboard.invites')" size="x-large" uppercase> <ds-number :count="0" :label="$t('admin.dashboard.invites')" size="x-large" uppercase>
<no-ssr slot="count"> <no-ssr slot="count">
<hc-count-to :start-val="0" :end-val="statistics.countInvites || 0" /> <hc-count-to :end-val="statistics.countInvites" />
</no-ssr> </no-ssr>
</ds-number> </ds-number>
</ds-space> </ds-space>
@ -90,7 +90,7 @@
<ds-space margin="small"> <ds-space margin="small">
<ds-number :count="0" :label="$t('admin.dashboard.follows')" size="x-large" uppercase> <ds-number :count="0" :label="$t('admin.dashboard.follows')" size="x-large" uppercase>
<no-ssr slot="count"> <no-ssr slot="count">
<hc-count-to :start-val="0" :end-val="statistics.countFollows || 0" /> <hc-count-to :end-val="statistics.countFollows" />
</no-ssr> </no-ssr>
</ds-number> </ds-number>
</ds-space> </ds-space>
@ -99,7 +99,7 @@
<ds-space margin="small"> <ds-space margin="small">
<ds-number :count="0" :label="$t('admin.dashboard.shouts')" size="x-large" uppercase> <ds-number :count="0" :label="$t('admin.dashboard.shouts')" size="x-large" uppercase>
<no-ssr slot="count"> <no-ssr slot="count">
<hc-count-to :start-val="0" :end-val="statistics.countShouts || 0" /> <hc-count-to :end-val="statistics.countShouts" />
</no-ssr> </no-ssr>
</ds-number> </ds-number>
</ds-space> </ds-space>
@ -128,9 +128,6 @@ export default {
return process.client return process.client
}, },
}, },
mounted() {
this.$apollo.queries.statistics.startPolling(5000)
},
apollo: { apollo: {
statistics: { statistics: {
query: gql` query: gql`

View File

@ -1,12 +1,12 @@
<template> <template>
<ds-card :header="$t('admin.tags.name')"> <ds-card :header="$t('admin.tags.name')">
<ds-table :data="Tag" :fields="fields" condensed> <ds-table :data="Tag" :fields="fields" condensed>
<template slot="id" slot-scope="scope"> <template slot="index" slot-scope="scope">
{{ scope.index + 1 }}. {{ scope.index + 1 }}.
</template> </template>
<template slot="name" slot-scope="scope"> <template slot="id" slot-scope="scope">
<nuxt-link :to="{ path: '/', query: { hashtag: scope.row.id } }"> <nuxt-link :to="{ path: '/', query: { hashtag: scope.row.id } }">
<b>#{{ scope.row.name | truncate(20) }}</b> <b>#{{ scope.row.id | truncate(20) }}</b>
</nuxt-link> </nuxt-link>
</template> </template>
</ds-table> </ds-table>
@ -25,8 +25,8 @@ export default {
computed: { computed: {
fields() { fields() {
return { return {
id: this.$t('admin.tags.number'), index: this.$t('admin.tags.number'),
name: this.$t('admin.tags.name'), id: this.$t('admin.tags.name'),
taggedCountUnique: { taggedCountUnique: {
label: this.$t('admin.tags.tagCountUnique'), label: this.$t('admin.tags.tagCountUnique'),
align: 'right', align: 'right',
@ -44,7 +44,6 @@ export default {
query { query {
Tag(first: 20, orderBy: taggedCountUnique_desc) { Tag(first: 20, orderBy: taggedCountUnique_desc) {
id id
name
taggedCount taggedCount
taggedCountUnique taggedCountUnique
} }

View File

@ -5,6 +5,7 @@ import Styleguide from '@human-connection/styleguide'
import Filters from '~/plugins/vue-filters' import Filters from '~/plugins/vue-filters'
import VTooltip from 'v-tooltip' import VTooltip from 'v-tooltip'
import FilterMenu from '~/components/FilterMenu/FilterMenu' import FilterMenu from '~/components/FilterMenu/FilterMenu'
import InfiniteScroll from '~/plugins/vue-infinite-scroll'
const localVue = createLocalVue() const localVue = createLocalVue()
@ -12,6 +13,7 @@ localVue.use(Vuex)
localVue.use(Styleguide) localVue.use(Styleguide)
localVue.use(Filters) localVue.use(Filters)
localVue.use(VTooltip) localVue.use(VTooltip)
localVue.use(InfiniteScroll)
config.stubs['no-ssr'] = '<span><slot /></span>' config.stubs['no-ssr'] = '<span><slot /></span>'
config.stubs['router-link'] = '<span><slot /></span>' config.stubs['router-link'] = '<span><slot /></span>'

View File

@ -33,7 +33,16 @@
primary primary
/> />
</no-ssr> </no-ssr>
<hc-load-more v-if="hasMore" :loading="$apollo.loading" @click="showMoreContributions" /> <div
v-if="hasMore"
v-infinite-scroll="showMoreContributions"
:infinite-scroll-immediate-check="true"
:infinite-scroll-disabled="$apollo.loading"
:infinite-scroll-distance="10"
:infinite-scroll-throttle-delay="800"
>
<hc-load-more v-if="true" :loading="$apollo.loading" @click="showMoreContributions" />
</div>
</div> </div>
</template> </template>
@ -91,7 +100,7 @@ export default {
label: this.$t('sorting.commented'), label: this.$t('sorting.commented'),
value: 'Commented', value: 'Commented',
icons: 'comment', icons: 'comment',
order: 'commentsCount_desc', order: 'commentedCount_desc',
}, },
], ],
} }

View File

@ -38,7 +38,7 @@
<!-- Tags --> <!-- Tags -->
<div v-if="post.tags && post.tags.length" class="tags"> <div v-if="post.tags && post.tags.length" class="tags">
<ds-space margin="xx-small" /> <ds-space margin="xx-small" />
<hc-tag v-for="tag in post.tags" :key="tag.id" :name="tag.name" /> <hc-tag v-for="tag in post.tags" :key="tag.id" :id="tag.id" />
</div> </div>
<ds-space margin-top="x-large"> <ds-space margin-top="x-large">
<ds-flex :gutter="{ lg: 'small' }"> <ds-flex :gutter="{ lg: 'small' }">
@ -81,10 +81,10 @@ import HcTag from '~/components/Tag'
import ContentMenu from '~/components/ContentMenu' import ContentMenu from '~/components/ContentMenu'
import HcUser from '~/components/User' import HcUser from '~/components/User'
import HcShoutButton from '~/components/ShoutButton.vue' import HcShoutButton from '~/components/ShoutButton.vue'
import HcCommentForm from '~/components/comments/CommentForm' import HcCommentForm from '~/components/CommentForm/CommentForm'
import HcCommentList from '~/components/comments/CommentList' import HcCommentList from '~/components/CommentList/CommentList'
import { postMenuModalsData, deletePostMutation } from '~/components/utils/PostHelpers' import { postMenuModalsData, deletePostMutation } from '~/components/utils/PostHelpers'
import PostQuery from '~/graphql/PostQuery.js' import PostQuery from '~/graphql/PostQuery'
import HcEmotions from '~/components/Emotions/Emotions' import HcEmotions from '~/components/Emotions/Emotions'
export default { export default {
@ -122,29 +122,6 @@ export default {
this.title = this.post.title this.title = this.post.title
}, },
}, },
async asyncData(context) {
const {
params,
error,
app: { apolloProvider, $i18n },
} = context
const client = apolloProvider.defaultClient
const query = PostQuery($i18n)
const variables = { slug: params.slug }
const {
data: { Post },
} = await client.query({ query, variables })
if (Post.length <= 0) {
// TODO: custom 404 error page with translations
const message = 'This post could not be found'
return error({ statusCode: 404, message })
}
const [post] = Post
return {
post,
title: post.title,
}
},
mounted() { mounted() {
setTimeout(() => { setTimeout(() => {
// NOTE: quick fix for jumping flexbox implementation // NOTE: quick fix for jumping flexbox implementation
@ -175,6 +152,19 @@ export default {
} }
}, },
}, },
apollo: {
Post: {
query() {
return PostQuery(this.$i18n)
},
variables() {
return {
slug: this.$route.params.slug,
}
},
fetchPolicy: 'cache-and-network',
},
},
} }
</script> </script>
@ -187,7 +177,6 @@ export default {
} }
.post-card { .post-card {
// max-width: 800px;
margin: auto; margin: auto;
.comments { .comments {

View File

@ -91,7 +91,7 @@ export default {
slug slug
contentExcerpt contentExcerpt
shoutedCount shoutedCount
commentsCount commentedCount
categories { categories {
id id
name name
@ -105,7 +105,7 @@ export default {
contributionsCount contributionsCount
followedByCount followedByCount
followedByCurrentUser followedByCurrentUser
commentsCount commentedCount
location { location {
name: name${this.$i18n.locale().toUpperCase()} name: name${this.$i18n.locale().toUpperCase()}
} }

View File

@ -3,12 +3,14 @@ import ProfileSlug from './_slug.vue'
import Vuex from 'vuex' import Vuex from 'vuex'
import Styleguide from '@human-connection/styleguide' import Styleguide from '@human-connection/styleguide'
import Filters from '~/plugins/vue-filters' import Filters from '~/plugins/vue-filters'
import InfiniteScroll from '~/plugins/vue-infinite-scroll'
const localVue = createLocalVue() const localVue = createLocalVue()
localVue.use(Vuex) localVue.use(Vuex)
localVue.use(Styleguide) localVue.use(Styleguide)
localVue.use(Filters) localVue.use(Filters)
localVue.use(InfiniteScroll)
localVue.filter('date', d => d) localVue.filter('date', d => d)
config.stubs['no-ssr'] = '<span><slot /></span>' config.stubs['no-ssr'] = '<span><slot /></span>'

View File

@ -43,14 +43,14 @@
<ds-flex-item> <ds-flex-item>
<no-ssr> <no-ssr>
<ds-number :label="$t('profile.followers')"> <ds-number :label="$t('profile.followers')">
<hc-count-to slot="count" :end-val="followedByCount" /> <hc-count-to slot="count" :end-val="user.followedByCount" />
</ds-number> </ds-number>
</no-ssr> </no-ssr>
</ds-flex-item> </ds-flex-item>
<ds-flex-item> <ds-flex-item>
<no-ssr> <no-ssr>
<ds-number :label="$t('profile.following')"> <ds-number :label="$t('profile.following')">
<hc-count-to slot="count" :end-val="Number(user.followingCount) || 0" /> <hc-count-to slot="count" :end-val="user.followingCount" />
</ds-number> </ds-number>
</no-ssr> </no-ssr>
</ds-flex-item> </ds-flex-item>
@ -229,7 +229,14 @@
</ds-grid-item> </ds-grid-item>
</template> </template>
</masonry-grid> </masonry-grid>
<hc-load-more v-if="hasMore" :loading="$apollo.loading" @click="showMoreContributions" /> <div
v-if="hasMore"
v-infinite-scroll="showMoreContributions"
infinite-scroll-disabled="$apollo.loading"
infinite-scroll-distance="10"
>
<hc-load-more :loading="$apollo.loading" @click="showMoreContributions" />
</div>
</ds-flex-item> </ds-flex-item>
</ds-flex> </ds-flex>
</div> </div>
@ -249,9 +256,9 @@ import HcUpload from '~/components/Upload'
import HcAvatar from '~/components/Avatar/Avatar.vue' import HcAvatar from '~/components/Avatar/Avatar.vue'
import MasonryGrid from '~/components/MasonryGrid/MasonryGrid.vue' import MasonryGrid from '~/components/MasonryGrid/MasonryGrid.vue'
import MasonryGridItem from '~/components/MasonryGrid/MasonryGridItem.vue' import MasonryGridItem from '~/components/MasonryGrid/MasonryGridItem.vue'
import PostQuery from '~/graphql/UserProfile/Post.js' import { filterPosts } from '~/graphql/PostQuery'
import UserQuery from '~/graphql/UserProfile/User.js' import UserQuery from '~/graphql/User'
import { Block, Unblock } from '~/graphql/settings/BlockedUsers.js' import { Block, Unblock } from '~/graphql/settings/BlockedUsers'
const tabToFilterMapping = ({ tab, id }) => { const tabToFilterMapping = ({ tab, id }) => {
return { return {
@ -306,10 +313,6 @@ export default {
myProfile() { myProfile() {
return this.$route.params.id === this.$store.getters['auth/user'].id return this.$route.params.id === this.$store.getters['auth/user'].id
}, },
followedByCount() {
let count = Number(this.user.followedByCount) || 0
return count
},
user() { user() {
return this.User ? this.User[0] : {} return this.User ? this.User[0] : {}
}, },
@ -398,7 +401,7 @@ export default {
apollo: { apollo: {
Post: { Post: {
query() { query() {
return PostQuery(this.$i18n) return filterPosts(this.$i18n)
}, },
variables() { variables() {
return { return {

View File

@ -0,0 +1,4 @@
import Vue from 'vue'
import infiniteScroll from 'vue-infinite-scroll'
Vue.use(infiniteScroll)

View File

@ -80,7 +80,7 @@ export const actions = {
about about
locationName locationName
contributionsCount contributionsCount
commentsCount commentedCount
socialMedia { socialMedia {
id id
url url

View File

@ -88,7 +88,7 @@ export const actions = {
deleted deleted
contributionsCount contributionsCount
shoutedCount shoutedCount
commentsCount commentedCount
followedByCount followedByCount
followedByCurrentUser followedByCurrentUser
location { location {
@ -99,7 +99,6 @@ export const actions = {
icon icon
} }
} }
commentsCount
categories { categories {
id id
name name

View File

@ -45,15 +45,14 @@ export const actions = {
commit('SET_QUICK_PENDING', true) commit('SET_QUICK_PENDING', true)
await this.app.apolloProvider.defaultClient await this.app.apolloProvider.defaultClient
.query({ .query({
query: gql(` query: gql`
query findPosts($query: String!) { query findPosts($query: String!) {
findPosts(query: $query, limit: 10) { findPosts(query: $query, limit: 10) {
id id
slug slug
label: title label: title
value: title, value: title
shoutedCount shoutedCount
commentsCount
createdAt createdAt
author { author {
id id
@ -62,7 +61,7 @@ export const actions = {
} }
} }
} }
`), `,
variables: { variables: {
query: value.replace(/\s/g, '~ ') + '~', query: value.replace(/\s/g, '~ ') + '~',
}, },

View File

@ -12980,6 +12980,11 @@ vue-hot-reload-api@^2.3.0:
version "2.3.3" version "2.3.3"
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.3.tgz#2756f46cb3258054c5f4723de8ae7e87302a1ccf" resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.3.tgz#2756f46cb3258054c5f4723de8ae7e87302a1ccf"
vue-infinite-scroll@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/vue-infinite-scroll/-/vue-infinite-scroll-2.0.2.tgz#ca37a91fe92ee0ad3b74acf8682c00917144b711"
integrity sha512-n+YghR059YmciANGJh9SsNWRi1YZEBVlODtmnb/12zI+4R72QZSWd+EuZ5mW6auEo/yaJXgxzwsuhvALVnm73A==
vue-izitoast@roschaefer/vue-izitoast#patch-1: vue-izitoast@roschaefer/vue-izitoast#patch-1:
version "1.1.2" version "1.1.2"
resolved "https://codeload.github.com/roschaefer/vue-izitoast/tar.gz/ba6b03eb24c7c04c299e64a9703e101bf158ae50" resolved "https://codeload.github.com/roschaefer/vue-izitoast/tar.gz/ba6b03eb24c7c04c299e64a9703e101bf158ae50"