mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
Merge branch 'master' of github.com:Ocelot-Social-Community/Ocelot-Social into 6593-@all-mention-for-network-admins
This commit is contained in:
commit
cf8c224062
2
.github/file-filters.yml
vendored
2
.github/file-filters.yml
vendored
@ -1,4 +1,5 @@
|
|||||||
backend: &backend
|
backend: &backend
|
||||||
|
- '.github/workflows/test-backend.yml'
|
||||||
- 'backend/**/*'
|
- 'backend/**/*'
|
||||||
- 'neo4j/**/*'
|
- 'neo4j/**/*'
|
||||||
|
|
||||||
@ -6,4 +7,5 @@ docker: &docker
|
|||||||
- 'docker-compose.*'
|
- 'docker-compose.*'
|
||||||
|
|
||||||
webapp: &webapp
|
webapp: &webapp
|
||||||
|
- '.github/workflows/test-webapp.yml'
|
||||||
- 'webapp/**/*'
|
- 'webapp/**/*'
|
||||||
|
|||||||
42
.github/workflows/cleanup-cache-at-pr-closing.yml
vendored
Normal file
42
.github/workflows/cleanup-cache-at-pr-closing.yml
vendored
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
###############################################################################
|
||||||
|
# A Github repo has max 10 GB of cache.
|
||||||
|
# https://github.blog/changelog/2021-11-23-github-actions-cache-size-is-now-increased-to-10gb-per-repository/
|
||||||
|
#
|
||||||
|
# To avoid "cache thrashing" by their cache eviction policy it is recommended
|
||||||
|
# to apply a cache cleanup workflow at PR closing to dele cache leftovers of
|
||||||
|
# the current branch:
|
||||||
|
# https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#force-deleting-cache-entries
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
name: ocelot.social cache cleanup on pr closing
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types:
|
||||||
|
- closed
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
clean-branch-cache:
|
||||||
|
name: Cleanup branch cache
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
continue-on-error: true
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Cleanup
|
||||||
|
run: |
|
||||||
|
gh extension install actions/gh-actions-cache
|
||||||
|
REPO=${{ github.repository }}
|
||||||
|
BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge"
|
||||||
|
echo "Fetching list of cache key"
|
||||||
|
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 )
|
||||||
|
set +e
|
||||||
|
echo "Deleting caches..."
|
||||||
|
for cacheKey in $cacheKeysForPR
|
||||||
|
do
|
||||||
|
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
|
||||||
|
done
|
||||||
|
echo "Done"
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
70
.github/workflows/test-backend.yml
vendored
70
.github/workflows/test-backend.yml
vendored
@ -1,7 +1,7 @@
|
|||||||
name: ocelot.social backend test CI
|
name: ocelot.social backend test CI
|
||||||
|
|
||||||
|
|
||||||
on: [push]
|
on: push
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
files-changed:
|
files-changed:
|
||||||
@ -13,7 +13,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3.3.0
|
- uses: actions/checkout@v3.3.0
|
||||||
|
|
||||||
- name: Check for frontend file changes
|
- name: Check for backend file changes
|
||||||
uses: dorny/paths-filter@v2.11.1
|
uses: dorny/paths-filter@v2.11.1
|
||||||
id: changes
|
id: changes
|
||||||
with:
|
with:
|
||||||
@ -35,11 +35,12 @@ jobs:
|
|||||||
docker build --target community -t "ocelotsocialnetwork/neo4j-community:test" neo4j/
|
docker build --target community -t "ocelotsocialnetwork/neo4j-community:test" neo4j/
|
||||||
docker save "ocelotsocialnetwork/neo4j-community:test" > /tmp/neo4j.tar
|
docker save "ocelotsocialnetwork/neo4j-community:test" > /tmp/neo4j.tar
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Cache docker images
|
||||||
uses: actions/upload-artifact@v3
|
id: cache-neo4j
|
||||||
|
uses: actions/cache/save@v3.3.1
|
||||||
with:
|
with:
|
||||||
name: docker-neo4j-image
|
|
||||||
path: /tmp/neo4j.tar
|
path: /tmp/neo4j.tar
|
||||||
|
key: ${{ github.run_id }}-backend-neo4j-cache
|
||||||
|
|
||||||
build_test_backend:
|
build_test_backend:
|
||||||
name: Docker Build Test - Backend
|
name: Docker Build Test - Backend
|
||||||
@ -55,11 +56,12 @@ jobs:
|
|||||||
docker build --target test -t "ocelotsocialnetwork/backend:test" backend/
|
docker build --target test -t "ocelotsocialnetwork/backend:test" backend/
|
||||||
docker save "ocelotsocialnetwork/backend:test" > /tmp/backend.tar
|
docker save "ocelotsocialnetwork/backend:test" > /tmp/backend.tar
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Cache docker images
|
||||||
uses: actions/upload-artifact@v3
|
id: cache-backend
|
||||||
|
uses: actions/cache/save@v3.3.1
|
||||||
with:
|
with:
|
||||||
name: docker-backend-test
|
|
||||||
path: /tmp/backend.tar
|
path: /tmp/backend.tar
|
||||||
|
key: ${{ github.run_id }}-backend-cache
|
||||||
|
|
||||||
lint_backend:
|
lint_backend:
|
||||||
name: Lint Backend
|
name: Lint Backend
|
||||||
@ -84,28 +86,29 @@ jobs:
|
|||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Download Docker Image (Neo4J)
|
- name: Restore Neo4J cache
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/cache/restore@v3.3.1
|
||||||
with:
|
with:
|
||||||
name: docker-neo4j-image
|
path: /tmp/neo4j.tar
|
||||||
path: /tmp
|
key: ${{ github.run_id }}-backend-neo4j-cache
|
||||||
|
fail-on-cache-miss: true
|
||||||
|
|
||||||
- name: Load Docker Image
|
- name: Restore Backend cache
|
||||||
run: docker load < /tmp/neo4j.tar
|
uses: actions/cache/restore@v3.3.1
|
||||||
|
|
||||||
- name: Download Docker Image (Backend)
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
with:
|
||||||
name: docker-backend-test
|
path: /tmp/backend.tar
|
||||||
path: /tmp
|
key: ${{ github.run_id }}-backend-cache
|
||||||
|
fail-on-cache-miss: true
|
||||||
|
|
||||||
- name: Load Docker Image
|
- name: Load Docker Images
|
||||||
run: docker load < /tmp/backend.tar
|
run: |
|
||||||
|
docker load < /tmp/neo4j.tar
|
||||||
|
docker load < /tmp/backend.tar
|
||||||
|
|
||||||
- name: backend | copy env files webapp
|
- name: backend | copy env files
|
||||||
run: cp webapp/.env.template webapp/.env
|
run: |
|
||||||
- name: backend | copy env files backend
|
cp webapp/.env.template webapp/.env
|
||||||
run: cp backend/.env.template backend/.env
|
cp backend/.env.template backend/.env
|
||||||
|
|
||||||
- name: backend | docker-compose
|
- name: backend | docker-compose
|
||||||
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps neo4j backend
|
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps neo4j backend
|
||||||
@ -118,3 +121,20 @@ jobs:
|
|||||||
|
|
||||||
- name: backend | Unit test incl. coverage check
|
- name: backend | Unit test incl. coverage check
|
||||||
run: docker-compose exec -T backend yarn test
|
run: docker-compose exec -T backend yarn test
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
name: Cleanup
|
||||||
|
if: ${{ needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.docker == 'true' }}
|
||||||
|
needs: [files-changed, unit_test_backend]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
continue-on-error: true
|
||||||
|
steps:
|
||||||
|
- name: Delete cache
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
gh extension install actions/gh-actions-cache
|
||||||
|
KEY="${{ github.run_id }}-backend-neo4j-cache"
|
||||||
|
gh actions-cache delete $KEY -R Ocelot-Social-Community/Ocelot-Social --confirm
|
||||||
|
KEY="${{ github.run_id }}-backend-cache"
|
||||||
|
gh actions-cache delete $KEY -R Ocelot-Social-Community/Ocelot-Social --confirm
|
||||||
|
|||||||
15
.github/workflows/test-e2e.yml
vendored
15
.github/workflows/test-e2e.yml
vendored
@ -1,12 +1,11 @@
|
|||||||
name: ocelot.social end-to-end test CI
|
name: ocelot.social end-to-end test CI
|
||||||
|
|
||||||
on: push
|
on: push
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker_preparation:
|
docker_preparation:
|
||||||
name: Fullstack test preparation
|
name: Fullstack test preparation
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
|
||||||
pr-number: ${{ steps.pr.outputs.number }}
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
@ -35,10 +34,6 @@ jobs:
|
|||||||
cd ..
|
cd ..
|
||||||
yarn install
|
yarn install
|
||||||
|
|
||||||
- name: Get pr number
|
|
||||||
id: pr
|
|
||||||
uses: 8BitJonny/gh-get-current-pr@2.2.0
|
|
||||||
|
|
||||||
- name: Cache docker images
|
- name: Cache docker images
|
||||||
id: cache
|
id: cache
|
||||||
uses: actions/cache/save@v3.3.1
|
uses: actions/cache/save@v3.3.1
|
||||||
@ -48,7 +43,7 @@ jobs:
|
|||||||
/home/runner/.cache/Cypress
|
/home/runner/.cache/Cypress
|
||||||
/home/runner/work/Ocelot-Social/Ocelot-Social
|
/home/runner/work/Ocelot-Social/Ocelot-Social
|
||||||
/tmp/images/
|
/tmp/images/
|
||||||
key: e2e-preparation-cache-pr${{ steps.pr.outputs.number }}
|
key: ${{ github.run_id }}-e2e-preparation-cache
|
||||||
|
|
||||||
fullstack_tests:
|
fullstack_tests:
|
||||||
name: Fullstack tests
|
name: Fullstack tests
|
||||||
@ -71,7 +66,7 @@ jobs:
|
|||||||
/home/runner/.cache/Cypress
|
/home/runner/.cache/Cypress
|
||||||
/home/runner/work/Ocelot-Social/Ocelot-Social
|
/home/runner/work/Ocelot-Social/Ocelot-Social
|
||||||
/tmp/images/
|
/tmp/images/
|
||||||
key: e2e-preparation-cache-pr${{ needs.docker_preparation.outputs.pr-number }}
|
key: ${{ github.run_id }}-e2e-preparation-cache
|
||||||
fail-on-cache-miss: true
|
fail-on-cache-miss: true
|
||||||
|
|
||||||
- name: Boot up test system | docker-compose
|
- name: Boot up test system | docker-compose
|
||||||
@ -104,14 +99,14 @@ jobs:
|
|||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
name: Cleanup
|
name: Cleanup
|
||||||
if: always()
|
|
||||||
needs: [docker_preparation, fullstack_tests]
|
needs: [docker_preparation, fullstack_tests]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
continue-on-error: true
|
||||||
steps:
|
steps:
|
||||||
- name: Delete cache
|
- name: Delete cache
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
gh extension install actions/gh-actions-cache
|
gh extension install actions/gh-actions-cache
|
||||||
KEY="e2e-preparation-cache-pr${{ needs.docker_preparation.outputs.pr-number }}"
|
KEY="${{ github.run_id }}-e2e-preparation-cache"
|
||||||
gh actions-cache delete $KEY -R Ocelot-Social-Community/Ocelot-Social --confirm
|
gh actions-cache delete $KEY -R Ocelot-Social-Community/Ocelot-Social --confirm
|
||||||
42
.github/workflows/test-webapp.yml
vendored
42
.github/workflows/test-webapp.yml
vendored
@ -1,7 +1,7 @@
|
|||||||
name: ocelot.social webapp test CI
|
name: ocelot.social webapp test CI
|
||||||
|
|
||||||
|
|
||||||
on: [push]
|
on: push
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
files-changed:
|
files-changed:
|
||||||
@ -44,16 +44,16 @@ jobs:
|
|||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: webapp | Build 'test' image
|
- name: Webapp | Build 'test' image
|
||||||
run: |
|
run: |
|
||||||
docker build --target test -t "ocelotsocialnetwork/webapp:test" webapp/
|
docker build --target test -t "ocelotsocialnetwork/webapp:test" webapp/
|
||||||
docker save "ocelotsocialnetwork/webapp:test" > /tmp/webapp.tar
|
docker save "ocelotsocialnetwork/webapp:test" > /tmp/webapp.tar
|
||||||
|
|
||||||
- name: Upload Artifact
|
- name: Cache docker image
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/cache/save@v3.3.1
|
||||||
with:
|
with:
|
||||||
name: docker-webapp-test
|
|
||||||
path: /tmp/webapp.tar
|
path: /tmp/webapp.tar
|
||||||
|
key: ${{ github.run_id }}-webapp-cache
|
||||||
|
|
||||||
lint_webapp:
|
lint_webapp:
|
||||||
name: Lint Webapp
|
name: Lint Webapp
|
||||||
@ -78,20 +78,19 @@ jobs:
|
|||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Download Docker Image (Webapp)
|
- name: Restore webapp cache
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/cache/restore@v3.3.1
|
||||||
with:
|
with:
|
||||||
name: docker-webapp-test
|
path: /tmp/webapp.tar
|
||||||
path: /tmp
|
key: ${{ github.run_id }}-webapp-cache
|
||||||
|
|
||||||
- name: Load Docker Image
|
- name: Load Docker Image
|
||||||
run: docker load < /tmp/webapp.tar
|
run: docker load < /tmp/webapp.tar
|
||||||
|
|
||||||
- name: backend | copy env files webapp
|
- name: Copy env files
|
||||||
run: cp webapp/.env.template webapp/.env
|
run: |
|
||||||
|
cp webapp/.env.template webapp/.env
|
||||||
- name: backend | copy env files backend
|
cp backend/.env.template backend/.env
|
||||||
run: cp backend/.env.template backend/.env
|
|
||||||
|
|
||||||
- name: backend | docker-compose
|
- name: backend | docker-compose
|
||||||
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps webapp
|
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps webapp
|
||||||
@ -99,3 +98,18 @@ jobs:
|
|||||||
- name: webapp | Unit tests incl. coverage check
|
- name: webapp | Unit tests incl. coverage check
|
||||||
run: docker-compose exec -T webapp yarn test
|
run: docker-compose exec -T webapp yarn test
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
name: Cleanup
|
||||||
|
if: ${{ needs.files-changed.outputs.docker == 'true' || needs.files-changed.outputs.webapp == 'true' }}
|
||||||
|
needs: [files-changed, unit_test_webapp]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
continue-on-error: true
|
||||||
|
steps:
|
||||||
|
- name: Delete cache
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
gh extension install actions/gh-actions-cache
|
||||||
|
KEY="${{ github.run_id }}-webapp-cache"
|
||||||
|
gh actions-cache delete $KEY -R Ocelot-Social-Community/Ocelot-Social --confirm
|
||||||
|
|
||||||
|
|||||||
@ -269,17 +269,17 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
await dagobert.relateTo(louie, 'blocked')
|
await dagobert.relateTo(louie, 'blocked')
|
||||||
|
|
||||||
// categories
|
// categories
|
||||||
await Promise.all(
|
let i = 0
|
||||||
categories.map(({ icon, name }, index) => {
|
for (const category of categories) {
|
||||||
return Factory.build('category', {
|
await Factory.build('category', {
|
||||||
id: `cat${index + 1}`,
|
id: `cat${i++}`,
|
||||||
slug: name,
|
slug: category.name,
|
||||||
name,
|
naem: category.name,
|
||||||
icon,
|
icon: category.icon,
|
||||||
})
|
})
|
||||||
}),
|
}
|
||||||
)
|
|
||||||
|
|
||||||
|
// tags
|
||||||
const environment = await Factory.build('tag', {
|
const environment = await Factory.build('tag', {
|
||||||
id: 'Environment',
|
id: 'Environment',
|
||||||
})
|
})
|
||||||
@ -295,8 +295,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
|
|
||||||
// groups
|
// groups
|
||||||
authenticatedUser = await peterLustig.toJson()
|
authenticatedUser = await peterLustig.toJson()
|
||||||
await Promise.all([
|
await mutate({
|
||||||
mutate({
|
|
||||||
mutation: createGroupMutation(),
|
mutation: createGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: 'g0',
|
id: 'g0',
|
||||||
@ -308,53 +307,49 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
categoryIds: ['cat6', 'cat12', 'cat16'],
|
categoryIds: ['cat6', 'cat12', 'cat16'],
|
||||||
locationName: 'Hamburg, Germany',
|
locationName: 'Hamburg, Germany',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
])
|
await mutate({
|
||||||
await Promise.all([
|
|
||||||
mutate({
|
|
||||||
mutation: joinGroupMutation(),
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g0',
|
groupId: 'g0',
|
||||||
userId: 'u2',
|
userId: 'u2',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: joinGroupMutation(),
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g0',
|
groupId: 'g0',
|
||||||
userId: 'u4',
|
userId: 'u4',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: joinGroupMutation(),
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g0',
|
groupId: 'g0',
|
||||||
userId: 'u6',
|
userId: 'u6',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
])
|
|
||||||
await Promise.all([
|
await mutate({
|
||||||
mutate({
|
|
||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g0',
|
groupId: 'g0',
|
||||||
userId: 'u2',
|
userId: 'u2',
|
||||||
roleInGroup: 'usual',
|
roleInGroup: 'usual',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
|
||||||
|
await mutate({
|
||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g0',
|
groupId: 'g0',
|
||||||
userId: 'u4',
|
userId: 'u4',
|
||||||
roleInGroup: 'admin',
|
roleInGroup: 'admin',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
])
|
|
||||||
|
|
||||||
// post into group
|
// post into group
|
||||||
await Promise.all([
|
await mutate({
|
||||||
mutate({
|
|
||||||
mutation: createPostMutation(),
|
mutation: createPostMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: 'p0-g0',
|
id: 'p0-g0',
|
||||||
@ -363,11 +358,10 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
content: 'A sack of rise dropped in Shanghai. Should we further investigate?',
|
content: 'A sack of rise dropped in Shanghai. Should we further investigate?',
|
||||||
categoryIds: ['cat6'],
|
categoryIds: ['cat6'],
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
])
|
|
||||||
authenticatedUser = await bobDerBaumeister.toJson()
|
authenticatedUser = await bobDerBaumeister.toJson()
|
||||||
await Promise.all([
|
await mutate({
|
||||||
mutate({
|
|
||||||
mutation: createPostMutation(),
|
mutation: createPostMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: 'p1-g0',
|
id: 'p1-g0',
|
||||||
@ -376,12 +370,10 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
content: 'We have to further investigate about the stories of a man living on the moon.',
|
content: 'We have to further investigate about the stories of a man living on the moon.',
|
||||||
categoryIds: ['cat12', 'cat16'],
|
categoryIds: ['cat12', 'cat16'],
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
])
|
|
||||||
|
|
||||||
authenticatedUser = await jennyRostock.toJson()
|
authenticatedUser = await jennyRostock.toJson()
|
||||||
await Promise.all([
|
await mutate({
|
||||||
mutate({
|
|
||||||
mutation: createGroupMutation(),
|
mutation: createGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: 'g1',
|
id: 'g1',
|
||||||
@ -393,74 +385,69 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
categoryIds: ['cat8', 'cat14'],
|
categoryIds: ['cat8', 'cat14'],
|
||||||
locationName: 'France',
|
locationName: 'France',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
])
|
await mutate({
|
||||||
await Promise.all([
|
|
||||||
mutate({
|
|
||||||
mutation: joinGroupMutation(),
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g1',
|
groupId: 'g1',
|
||||||
userId: 'u1',
|
userId: 'u1',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: joinGroupMutation(),
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g1',
|
groupId: 'g1',
|
||||||
userId: 'u2',
|
userId: 'u2',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: joinGroupMutation(),
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g1',
|
groupId: 'g1',
|
||||||
userId: 'u5',
|
userId: 'u5',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: joinGroupMutation(),
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g1',
|
groupId: 'g1',
|
||||||
userId: 'u6',
|
userId: 'u6',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: joinGroupMutation(),
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g1',
|
groupId: 'g1',
|
||||||
userId: 'u7',
|
userId: 'u7',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
])
|
|
||||||
await Promise.all([
|
await mutate({
|
||||||
mutate({
|
|
||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g1',
|
groupId: 'g1',
|
||||||
userId: 'u1',
|
userId: 'u1',
|
||||||
roleInGroup: 'usual',
|
roleInGroup: 'usual',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g1',
|
groupId: 'g1',
|
||||||
userId: 'u5',
|
userId: 'u5',
|
||||||
roleInGroup: 'admin',
|
roleInGroup: 'admin',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g1',
|
groupId: 'g1',
|
||||||
userId: 'u6',
|
userId: 'u6',
|
||||||
roleInGroup: 'owner',
|
roleInGroup: 'owner',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
])
|
|
||||||
// post into group
|
// post into group
|
||||||
await Promise.all([
|
await mutate({
|
||||||
mutate({
|
|
||||||
mutation: createPostMutation(),
|
mutation: createPostMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: 'p0-g1',
|
id: 'p0-g1',
|
||||||
@ -469,11 +456,9 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
content: 'I like the concept of this school. Can we use our software in this?',
|
content: 'I like the concept of this school. Can we use our software in this?',
|
||||||
categoryIds: ['cat8'],
|
categoryIds: ['cat8'],
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
])
|
|
||||||
authenticatedUser = await peterLustig.toJson()
|
authenticatedUser = await peterLustig.toJson()
|
||||||
await Promise.all([
|
await mutate({
|
||||||
mutate({
|
|
||||||
mutation: createPostMutation(),
|
mutation: createPostMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: 'p1-g1',
|
id: 'p1-g1',
|
||||||
@ -482,12 +467,10 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
content: 'This idea is too inportant to have the scope only on France.',
|
content: 'This idea is too inportant to have the scope only on France.',
|
||||||
categoryIds: ['cat14'],
|
categoryIds: ['cat14'],
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
])
|
|
||||||
|
|
||||||
authenticatedUser = await bobDerBaumeister.toJson()
|
authenticatedUser = await bobDerBaumeister.toJson()
|
||||||
await Promise.all([
|
await mutate({
|
||||||
mutate({
|
|
||||||
mutation: createGroupMutation(),
|
mutation: createGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: 'g2',
|
id: 'g2',
|
||||||
@ -498,83 +481,78 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
actionRadius: 'interplanetary',
|
actionRadius: 'interplanetary',
|
||||||
categoryIds: ['cat4', 'cat5', 'cat17'],
|
categoryIds: ['cat4', 'cat5', 'cat17'],
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
])
|
await mutate({
|
||||||
await Promise.all([
|
|
||||||
mutate({
|
|
||||||
mutation: joinGroupMutation(),
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g2',
|
groupId: 'g2',
|
||||||
userId: 'u3',
|
userId: 'u3',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: joinGroupMutation(),
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g2',
|
groupId: 'g2',
|
||||||
userId: 'u4',
|
userId: 'u4',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: joinGroupMutation(),
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g2',
|
groupId: 'g2',
|
||||||
userId: 'u5',
|
userId: 'u5',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: joinGroupMutation(),
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g2',
|
groupId: 'g2',
|
||||||
userId: 'u6',
|
userId: 'u6',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: joinGroupMutation(),
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g2',
|
groupId: 'g2',
|
||||||
userId: 'u7',
|
userId: 'u7',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
])
|
|
||||||
await Promise.all([
|
await mutate({
|
||||||
mutate({
|
|
||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g2',
|
groupId: 'g2',
|
||||||
userId: 'u3',
|
userId: 'u3',
|
||||||
roleInGroup: 'usual',
|
roleInGroup: 'usual',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g2',
|
groupId: 'g2',
|
||||||
userId: 'u4',
|
userId: 'u4',
|
||||||
roleInGroup: 'pending',
|
roleInGroup: 'pending',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g2',
|
groupId: 'g2',
|
||||||
userId: 'u5',
|
userId: 'u5',
|
||||||
roleInGroup: 'admin',
|
roleInGroup: 'admin',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: changeGroupMemberRoleMutation(),
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g2',
|
groupId: 'g2',
|
||||||
userId: 'u6',
|
userId: 'u6',
|
||||||
roleInGroup: 'usual',
|
roleInGroup: 'usual',
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
])
|
|
||||||
|
|
||||||
authenticatedUser = await louie.toJson()
|
authenticatedUser = await louie.toJson()
|
||||||
await Promise.all([
|
await mutate({
|
||||||
mutate({
|
|
||||||
mutation: createPostMutation(),
|
mutation: createPostMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: 'p0-g2',
|
id: 'p0-g2',
|
||||||
@ -583,15 +561,13 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
content: 'I am new to Yoga and did not join this group so far.',
|
content: 'I am new to Yoga and did not join this group so far.',
|
||||||
categoryIds: ['cat4'],
|
categoryIds: ['cat4'],
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
])
|
|
||||||
|
|
||||||
// Create Events (by peter lustig)
|
// Create Events (by peter lustig)
|
||||||
authenticatedUser = await peterLustig.toJson()
|
authenticatedUser = await peterLustig.toJson()
|
||||||
const now = new Date()
|
const now = new Date()
|
||||||
|
|
||||||
await Promise.all([
|
await mutate({
|
||||||
mutate({
|
|
||||||
mutation: createPostMutation(),
|
mutation: createPostMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: 'e0',
|
id: 'e0',
|
||||||
@ -600,17 +576,13 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
categoryIds: ['cat4'],
|
categoryIds: ['cat4'],
|
||||||
postType: 'Event',
|
postType: 'Event',
|
||||||
eventInput: {
|
eventInput: {
|
||||||
eventStart: new Date(
|
eventStart: new Date(now.getFullYear(), now.getMonth(), now.getDate() + 7).toISOString(),
|
||||||
now.getFullYear(),
|
|
||||||
now.getMonth(),
|
|
||||||
now.getDate() + 7,
|
|
||||||
).toISOString(),
|
|
||||||
eventVenue: 'Ellis Kinderzimmer',
|
eventVenue: 'Ellis Kinderzimmer',
|
||||||
eventLocationName: 'Deutschland',
|
eventLocationName: 'Deutschland',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: createPostMutation(),
|
mutation: createPostMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: 'e1',
|
id: 'e1',
|
||||||
@ -619,17 +591,13 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
categoryIds: ['cat5'],
|
categoryIds: ['cat5'],
|
||||||
postType: 'Event',
|
postType: 'Event',
|
||||||
eventInput: {
|
eventInput: {
|
||||||
eventStart: new Date(
|
eventStart: new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1).toISOString(),
|
||||||
now.getFullYear(),
|
|
||||||
now.getMonth(),
|
|
||||||
now.getDate() + 1,
|
|
||||||
).toISOString(),
|
|
||||||
eventVenue: 'Schlossgarten',
|
eventVenue: 'Schlossgarten',
|
||||||
eventLocationName: 'Stuttgart',
|
eventLocationName: 'Stuttgart',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: createPostMutation(),
|
mutation: createPostMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: 'e2',
|
id: 'e2',
|
||||||
@ -638,18 +606,13 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
categoryIds: ['cat5'],
|
categoryIds: ['cat5'],
|
||||||
postType: 'Event',
|
postType: 'Event',
|
||||||
eventInput: {
|
eventInput: {
|
||||||
eventStart: new Date(
|
eventStart: new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1).toISOString(),
|
||||||
now.getFullYear(),
|
|
||||||
now.getMonth(),
|
|
||||||
now.getDate() + 1,
|
|
||||||
).toISOString(),
|
|
||||||
eventEnd: new Date(now.getFullYear(), now.getMonth(), now.getDate() + 4).toISOString(),
|
eventEnd: new Date(now.getFullYear(), now.getMonth(), now.getDate() + 4).toISOString(),
|
||||||
eventVenue: 'Ferienlager',
|
eventVenue: 'Ferienlager',
|
||||||
eventLocationName: 'Bahra, Sachsen',
|
eventLocationName: 'Bahra, Sachsen',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
])
|
|
||||||
|
|
||||||
let passedEvent = await neode.find('Post', 'e1')
|
let passedEvent = await neode.find('Post', 'e1')
|
||||||
await passedEvent.update({ eventStart: new Date(2010, 8, 30, 10).toISOString() })
|
await passedEvent.update({ eventStart: new Date(2010, 8, 30, 10).toISOString() })
|
||||||
@ -836,8 +799,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
const hashtagAndMention1 =
|
const hashtagAndMention1 =
|
||||||
'The new physics of <a class="hashtag" data-hashtag-id="QuantenFlussTheorie" href="/?hashtag=QuantenFlussTheorie">#QuantenFlussTheorie</a> can explain <a class="hashtag" data-hashtag-id="QuantumGravity" href="/?hashtag=QuantumGravity">#QuantumGravity</a>! <a class="mention" data-mention-id="u1" href="/profile/u1">@peter-lustig</a> got that already. ;-)'
|
'The new physics of <a class="hashtag" data-hashtag-id="QuantenFlussTheorie" href="/?hashtag=QuantenFlussTheorie">#QuantenFlussTheorie</a> can explain <a class="hashtag" data-hashtag-id="QuantumGravity" href="/?hashtag=QuantumGravity">#QuantumGravity</a>! <a class="mention" data-mention-id="u1" href="/profile/u1">@peter-lustig</a> got that already. ;-)'
|
||||||
|
|
||||||
await Promise.all([
|
await mutate({
|
||||||
mutate({
|
|
||||||
mutation: createPostMutation(),
|
mutation: createPostMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: 'p2',
|
id: 'p2',
|
||||||
@ -845,8 +807,8 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
content: hashtag1,
|
content: hashtag1,
|
||||||
categoryIds: ['cat2'],
|
categoryIds: ['cat2'],
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: createPostMutation(),
|
mutation: createPostMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: 'p7',
|
id: 'p7',
|
||||||
@ -854,8 +816,8 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
content: `${mention1} ${faker.lorem.paragraph()}`,
|
content: `${mention1} ${faker.lorem.paragraph()}`,
|
||||||
categoryIds: ['cat7'],
|
categoryIds: ['cat7'],
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: createPostMutation(),
|
mutation: createPostMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: 'p8',
|
id: 'p8',
|
||||||
@ -864,8 +826,8 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
content: hashtagAndMention1,
|
content: hashtagAndMention1,
|
||||||
categoryIds: ['cat8'],
|
categoryIds: ['cat8'],
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: createPostMutation(),
|
mutation: createPostMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: 'p12',
|
id: 'p12',
|
||||||
@ -873,11 +835,13 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
content: `${mention2} ${faker.lorem.paragraph()}`,
|
content: `${mention2} ${faker.lorem.paragraph()}`,
|
||||||
categoryIds: ['cat12'],
|
categoryIds: ['cat12'],
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
])
|
|
||||||
const [p2, p7, p8, p12] = await Promise.all(
|
const p2 = await neode.find('Post', 'p2')
|
||||||
['p2', 'p7', 'p8', 'p12'].map((id) => neode.find('Post', id)),
|
const p7 = await neode.find('Post', 'p7')
|
||||||
)
|
const p8 = await neode.find('Post', 'p8')
|
||||||
|
const p12 = await neode.find('Post', 'p12')
|
||||||
|
|
||||||
authenticatedUser = null
|
authenticatedUser = null
|
||||||
|
|
||||||
authenticatedUser = await dewey.toJson()
|
authenticatedUser = await dewey.toJson()
|
||||||
@ -885,31 +849,30 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
'I heard <a class="mention" data-mention-id="u3" href="/profile/u3">@jenny-rostock</a> has practiced it for 3 years now.'
|
'I heard <a class="mention" data-mention-id="u3" href="/profile/u3">@jenny-rostock</a> has practiced it for 3 years now.'
|
||||||
const mentionInComment2 =
|
const mentionInComment2 =
|
||||||
'Did <a class="mention" data-mention-id="u1" href="/profile/u1">@peter-lustig</a> tell you?'
|
'Did <a class="mention" data-mention-id="u1" href="/profile/u1">@peter-lustig</a> tell you?'
|
||||||
await Promise.all([
|
await mutate({
|
||||||
mutate({
|
|
||||||
mutation: createCommentMutation,
|
mutation: createCommentMutation,
|
||||||
variables: {
|
variables: {
|
||||||
id: 'c4',
|
id: 'c4',
|
||||||
postId: 'p2',
|
postId: 'p2',
|
||||||
content: mentionInComment1,
|
content: mentionInComment1,
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: createCommentMutation,
|
mutation: createCommentMutation,
|
||||||
variables: {
|
variables: {
|
||||||
id: 'c4-1',
|
id: 'c4-1',
|
||||||
postId: 'p2',
|
postId: 'p2',
|
||||||
content: mentionInComment2,
|
content: mentionInComment2,
|
||||||
},
|
},
|
||||||
}),
|
})
|
||||||
mutate({
|
await mutate({
|
||||||
mutation: createCommentMutation,
|
mutation: createCommentMutation,
|
||||||
variables: {
|
variables: {
|
||||||
postId: 'p14',
|
postId: 'p14',
|
||||||
content: faker.lorem.paragraph(),
|
content: faker.lorem.paragraph(),
|
||||||
},
|
},
|
||||||
}), // should send a notification
|
}) // should send a notification
|
||||||
])
|
|
||||||
authenticatedUser = null
|
authenticatedUser = null
|
||||||
|
|
||||||
const comments: any[] = []
|
const comments: any[] = []
|
||||||
@ -1193,24 +1156,22 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
closed: true,
|
closed: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const additionalUsers = await Promise.all(
|
const additionalUsers: any[] = []
|
||||||
[...Array(30).keys()].map(() => Factory.build('user')),
|
for (let i = 0; i < 30; i++) {
|
||||||
)
|
const user = await Factory.build('user')
|
||||||
|
|
||||||
await Promise.all(
|
|
||||||
additionalUsers.map(async (user) => {
|
|
||||||
await jennyRostock.relateTo(user, 'following')
|
await jennyRostock.relateTo(user, 'following')
|
||||||
await user.relateTo(jennyRostock, 'following')
|
await user.relateTo(jennyRostock, 'following')
|
||||||
}),
|
additionalUsers.push(user)
|
||||||
)
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// Jenny users
|
||||||
[...Array(30).keys()].map((index) => Factory.build('user', { name: `Jenny${index}` })),
|
for (let i = 0; i < 30; i++) {
|
||||||
)
|
await Factory.build('user', { name: `Jenny${i}` })
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// Jenny posts
|
||||||
[...Array(30).keys()].map(() =>
|
for (let i = 0; i < 30; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'post',
|
'post',
|
||||||
{ content: `Jenny ${faker.lorem.sentence()}` },
|
{ content: `Jenny ${faker.lorem.sentence()}` },
|
||||||
{
|
{
|
||||||
@ -1220,68 +1181,48 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
url: faker.image.unsplash.objects(),
|
url: faker.image.unsplash.objects(),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// comments on p2 jenny
|
||||||
[...Array(30).keys()].map(() =>
|
for (let i = 0; i < 6; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'post',
|
|
||||||
{},
|
|
||||||
{
|
|
||||||
categoryIds: ['cat1'],
|
|
||||||
author: jennyRostock,
|
|
||||||
image: Factory.build('image', {
|
|
||||||
url: faker.image.unsplash.objects(),
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
await Promise.all(
|
|
||||||
[...Array(6).keys()].map(() =>
|
|
||||||
Factory.build(
|
|
||||||
'comment',
|
'comment',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
author: jennyRostock,
|
author: jennyRostock,
|
||||||
postId: 'p2',
|
postId: 'p2',
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// comments on p15 jenny
|
||||||
[...Array(4).keys()].map(() =>
|
for (let i = 0; i < 4; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'comment',
|
'comment',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
author: jennyRostock,
|
author: jennyRostock,
|
||||||
postId: 'p15',
|
postId: 'p15',
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// comments on p4 jenny
|
||||||
[...Array(2).keys()].map(() =>
|
for (let i = 0; i < 2; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'comment',
|
'comment',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
author: jennyRostock,
|
author: jennyRostock,
|
||||||
postId: 'p4',
|
postId: 'p4',
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// Posts Peter Lustig
|
||||||
[...Array(21).keys()].map(() =>
|
for (let i = 0; i < 21; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'post',
|
'post',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
@ -1291,52 +1232,48 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
url: faker.image.unsplash.buildings(),
|
url: faker.image.unsplash.buildings(),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// comments p4 peter
|
||||||
[...Array(3).keys()].map(() =>
|
for (let i = 0; i < 3; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'comment',
|
'comment',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
author: peterLustig,
|
author: peterLustig,
|
||||||
postId: 'p4',
|
postId: 'p4',
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// comments p14 peter
|
||||||
[...Array(3).keys()].map(() =>
|
for (let i = 0; i < 3; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'comment',
|
'comment',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
author: peterLustig,
|
author: peterLustig,
|
||||||
postId: 'p14',
|
postId: 'p14',
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// comments p0 peter
|
||||||
[...Array(6).keys()].map(() =>
|
for (let i = 0; i < 3; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'comment',
|
'comment',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
author: peterLustig,
|
author: peterLustig,
|
||||||
postId: 'p0',
|
postId: 'p0',
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// Posts dewey
|
||||||
[...Array(11).keys()].map(() =>
|
for (let i = 0; i < 11; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'post',
|
'post',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
@ -1346,52 +1283,48 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
url: faker.image.unsplash.food(),
|
url: faker.image.unsplash.food(),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// Comments p2 dewey
|
||||||
[...Array(7).keys()].map(() =>
|
for (let i = 0; i < 7; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'comment',
|
'comment',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
author: dewey,
|
author: dewey,
|
||||||
postId: 'p2',
|
postId: 'p2',
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// Comments p6 dewey
|
||||||
[...Array(5).keys()].map(() =>
|
for (let i = 0; i < 5; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'comment',
|
'comment',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
author: dewey,
|
author: dewey,
|
||||||
postId: 'p6',
|
postId: 'p6',
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// Comments p9 dewey
|
||||||
[...Array(2).keys()].map(() =>
|
for (let i = 0; i < 2; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'comment',
|
'comment',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
author: dewey,
|
author: dewey,
|
||||||
postId: 'p9',
|
postId: 'p9',
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// Posts louie
|
||||||
[...Array(16).keys()].map(() =>
|
for (let i = 0; i < 16; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'post',
|
'post',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
@ -1401,52 +1334,48 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
url: faker.image.unsplash.technology(),
|
url: faker.image.unsplash.technology(),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// Comments p1 louie
|
||||||
[...Array(4).keys()].map(() =>
|
for (let i = 0; i < 4; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'comment',
|
'comment',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
postId: 'p1',
|
postId: 'p1',
|
||||||
author: louie,
|
author: louie,
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// Comments p10 louie
|
||||||
[...Array(8).keys()].map(() =>
|
for (let i = 0; i < 8; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'comment',
|
'comment',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
author: louie,
|
author: louie,
|
||||||
postId: 'p10',
|
postId: 'p10',
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// Comments p13 louie
|
||||||
[...Array(5).keys()].map(() =>
|
for (let i = 0; i < 5; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'comment',
|
'comment',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
author: louie,
|
author: louie,
|
||||||
postId: 'p13',
|
postId: 'p13',
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// Posts Bob der Baumeister
|
||||||
[...Array(45).keys()].map(() =>
|
for (let i = 0; i < 45; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'post',
|
'post',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
@ -1456,52 +1385,48 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
url: faker.image.unsplash.people(),
|
url: faker.image.unsplash.people(),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// Comments p2 bob
|
||||||
[...Array(2).keys()].map(() =>
|
for (let i = 0; i < 2; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'comment',
|
'comment',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
author: bobDerBaumeister,
|
author: bobDerBaumeister,
|
||||||
postId: 'p2',
|
postId: 'p2',
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// Comments p12 bob
|
||||||
[...Array(3).keys()].map(() =>
|
for (let i = 0; i < 3; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'comment',
|
'comment',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
author: bobDerBaumeister,
|
author: bobDerBaumeister,
|
||||||
postId: 'p12',
|
postId: 'p12',
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// Comments p13 bob
|
||||||
[...Array(7).keys()].map(() =>
|
for (let i = 0; i < 7; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'comment',
|
'comment',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
author: bobDerBaumeister,
|
author: bobDerBaumeister,
|
||||||
postId: 'p13',
|
postId: 'p13',
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// Posts huey
|
||||||
[...Array(8).keys()].map(() =>
|
for (let i = 0; i < 8; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'post',
|
'post',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
@ -1511,48 +1436,44 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
url: faker.image.unsplash.nature(),
|
url: faker.image.unsplash.nature(),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// Comments p0 huey
|
||||||
[...Array(6).keys()].map(() =>
|
for (let i = 0; i < 6; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'comment',
|
'comment',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
author: huey,
|
author: huey,
|
||||||
postId: 'p0',
|
postId: 'p0',
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// Comments p13 huey
|
||||||
[...Array(8).keys()].map(() =>
|
for (let i = 0; i < 8; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'comment',
|
'comment',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
author: huey,
|
author: huey,
|
||||||
postId: 'p13',
|
postId: 'p13',
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Promise.all(
|
// Comments p15 huey
|
||||||
[...Array(8).keys()].map(() =>
|
for (let i = 0; i < 8; i++) {
|
||||||
Factory.build(
|
await Factory.build(
|
||||||
'comment',
|
'comment',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
author: huey,
|
author: huey,
|
||||||
postId: 'p15',
|
postId: 'p15',
|
||||||
},
|
},
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
await Factory.build('donations')
|
await Factory.build('donations')
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,9 @@ export const messageQuery = () => {
|
|||||||
indexId
|
indexId
|
||||||
content
|
content
|
||||||
senderId
|
senderId
|
||||||
|
author {
|
||||||
|
id
|
||||||
|
}
|
||||||
username
|
username
|
||||||
avatar
|
avatar
|
||||||
date
|
date
|
||||||
|
|||||||
@ -9,6 +9,7 @@ export const createRoomMutation = () => {
|
|||||||
roomName
|
roomName
|
||||||
lastMessageAt
|
lastMessageAt
|
||||||
unreadCount
|
unreadCount
|
||||||
|
#avatar
|
||||||
users {
|
users {
|
||||||
_id
|
_id
|
||||||
id
|
id
|
||||||
@ -25,10 +26,11 @@ export const createRoomMutation = () => {
|
|||||||
export const roomQuery = () => {
|
export const roomQuery = () => {
|
||||||
return gql`
|
return gql`
|
||||||
query Room($first: Int, $offset: Int, $id: ID) {
|
query Room($first: Int, $offset: Int, $id: ID) {
|
||||||
Room(first: $first, offset: $offset, id: $id, orderBy: createdAt_desc) {
|
Room(first: $first, offset: $offset, id: $id, orderBy: lastMessageAt_desc) {
|
||||||
id
|
id
|
||||||
roomId
|
roomId
|
||||||
roomName
|
roomName
|
||||||
|
avatar
|
||||||
lastMessageAt
|
lastMessageAt
|
||||||
unreadCount
|
unreadCount
|
||||||
lastMessage {
|
lastMessage {
|
||||||
|
|||||||
@ -9,10 +9,9 @@ function walkRecursive(data, fields, fieldName, callback, _key?) {
|
|||||||
if (!Array.isArray(fields)) {
|
if (!Array.isArray(fields)) {
|
||||||
throw new Error('please provide an fields array for the walkRecursive helper')
|
throw new Error('please provide an fields array for the walkRecursive helper')
|
||||||
}
|
}
|
||||||
if (data && typeof data === 'string' && fields.includes(_key)) {
|
const fieldDef = fields.find((f) => f.field === _key)
|
||||||
// well we found what we searched for, lets replace the value with our callback result
|
if (data && typeof data === 'string' && fieldDef) {
|
||||||
const key = _key.split('!')
|
if (!fieldDef.excludes?.includes(fieldName)) data = callback(data, _key)
|
||||||
if (key.length === 1 || key[1] !== fieldName) data = callback(data, key[0])
|
|
||||||
} else if (data && Array.isArray(data)) {
|
} else if (data && Array.isArray(data)) {
|
||||||
// go into the rabbit hole and dig through that array
|
// go into the rabbit hole and dig through that array
|
||||||
data.forEach((res, index) => {
|
data.forEach((res, index) => {
|
||||||
|
|||||||
@ -54,4 +54,7 @@ export default {
|
|||||||
Mutation: {
|
Mutation: {
|
||||||
CreateRoom: roomProperties,
|
CreateRoom: roomProperties,
|
||||||
},
|
},
|
||||||
|
Subscription: {
|
||||||
|
chatMessageAdded: messageProperties,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -30,6 +30,7 @@ const standardSanitizeHtmlOptions = {
|
|||||||
'strike',
|
'strike',
|
||||||
'span',
|
'span',
|
||||||
'blockquote',
|
'blockquote',
|
||||||
|
'usertag',
|
||||||
],
|
],
|
||||||
allowedAttributes: {
|
allowedAttributes: {
|
||||||
a: ['href', 'class', 'target', 'data-*', 'contenteditable'],
|
a: ['href', 'class', 'target', 'data-*', 'contenteditable'],
|
||||||
|
|||||||
@ -3,11 +3,11 @@ import { cleanHtml } from '../middleware/helpers/cleanHtml'
|
|||||||
|
|
||||||
// exclamation mark separetes field names, that should not be sanitized
|
// exclamation mark separetes field names, that should not be sanitized
|
||||||
const fields = [
|
const fields = [
|
||||||
'content',
|
{ field: 'content', excludes: ['CreateMessage', 'Message'] },
|
||||||
'contentExcerpt',
|
{ field: 'contentExcerpt' },
|
||||||
'reasonDescription',
|
{ field: 'reasonDescription' },
|
||||||
'description!embed',
|
{ field: 'description', excludes: ['embed'] },
|
||||||
'descriptionExcerpt',
|
{ field: 'descriptionExcerpt' },
|
||||||
]
|
]
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|||||||
@ -117,7 +117,7 @@ describe('Message', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('user chats in room', () => {
|
describe('user chats in room', () => {
|
||||||
it('returns the message and publishes subscription', async () => {
|
it('returns the message and publishes subscriptions', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: createMessageMutation(),
|
mutation: createMessageMutation(),
|
||||||
@ -146,6 +146,20 @@ describe('Message', () => {
|
|||||||
roomCountUpdated: '1',
|
roomCountUpdated: '1',
|
||||||
userId: 'other-chatting-user',
|
userId: 'other-chatting-user',
|
||||||
})
|
})
|
||||||
|
expect(pubsubSpy).toBeCalledWith('CHAT_MESSAGE_ADDED', {
|
||||||
|
chatMessageAdded: expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
content: 'Some nice message to other chatting user',
|
||||||
|
senderId: 'chatting-user',
|
||||||
|
username: 'Chatting User',
|
||||||
|
avatar: expect.any(String),
|
||||||
|
date: expect.any(String),
|
||||||
|
saved: true,
|
||||||
|
distributed: false,
|
||||||
|
seen: false,
|
||||||
|
}),
|
||||||
|
userId: 'other-chatting-user',
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('room is updated as well', () => {
|
describe('room is updated as well', () => {
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
import { neo4jgraphql } from 'neo4j-graphql-js'
|
import { neo4jgraphql } from 'neo4j-graphql-js'
|
||||||
import Resolver from './helpers/Resolver'
|
import Resolver from './helpers/Resolver'
|
||||||
|
|
||||||
import { getUnreadRoomsCount } from './rooms'
|
import { getUnreadRoomsCount } from './rooms'
|
||||||
import { pubsub, ROOM_COUNT_UPDATED } from '../../server'
|
import { pubsub, ROOM_COUNT_UPDATED, CHAT_MESSAGE_ADDED } from '../../server'
|
||||||
|
import { withFilter } from 'graphql-subscriptions'
|
||||||
|
|
||||||
const setMessagesAsDistributed = async (undistributedMessagesIds, session) => {
|
const setMessagesAsDistributed = async (undistributedMessagesIds, session) => {
|
||||||
return session.writeTransaction(async (transaction) => {
|
return session.writeTransaction(async (transaction) => {
|
||||||
@ -19,6 +21,16 @@ const setMessagesAsDistributed = async (undistributedMessagesIds, session) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
Subscription: {
|
||||||
|
chatMessageAdded: {
|
||||||
|
subscribe: withFilter(
|
||||||
|
() => pubsub.asyncIterator(CHAT_MESSAGE_ADDED),
|
||||||
|
(payload, variables) => {
|
||||||
|
return payload.userId === variables.userId
|
||||||
|
},
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
Query: {
|
Query: {
|
||||||
Message: async (object, params, context, resolveInfo) => {
|
Message: async (object, params, context, resolveInfo) => {
|
||||||
const { roomId } = params
|
const { roomId } = params
|
||||||
@ -69,7 +81,7 @@ export default {
|
|||||||
createdAt: toString(datetime()),
|
createdAt: toString(datetime()),
|
||||||
id: apoc.create.uuid(),
|
id: apoc.create.uuid(),
|
||||||
indexId: CASE WHEN maxIndex IS NOT NULL THEN maxIndex + 1 ELSE 0 END,
|
indexId: CASE WHEN maxIndex IS NOT NULL THEN maxIndex + 1 ELSE 0 END,
|
||||||
content: $content,
|
content: LEFT($content,2000),
|
||||||
saved: true,
|
saved: true,
|
||||||
distributed: false,
|
distributed: false,
|
||||||
seen: false
|
seen: false
|
||||||
@ -77,6 +89,7 @@ export default {
|
|||||||
SET room.lastMessageAt = toString(datetime())
|
SET room.lastMessageAt = toString(datetime())
|
||||||
RETURN message {
|
RETURN message {
|
||||||
.*,
|
.*,
|
||||||
|
indexId: toString(message.indexId),
|
||||||
recipientId: recipientUser.id,
|
recipientId: recipientUser.id,
|
||||||
senderId: currentUser.id,
|
senderId: currentUser.id,
|
||||||
username: currentUser.name,
|
username: currentUser.name,
|
||||||
@ -102,10 +115,14 @@ export default {
|
|||||||
const roomCountUpdated = await getUnreadRoomsCount(message.recipientId, session)
|
const roomCountUpdated = await getUnreadRoomsCount(message.recipientId, session)
|
||||||
|
|
||||||
// send subscriptions
|
// send subscriptions
|
||||||
await pubsub.publish(ROOM_COUNT_UPDATED, {
|
void pubsub.publish(ROOM_COUNT_UPDATED, {
|
||||||
roomCountUpdated,
|
roomCountUpdated,
|
||||||
userId: message.recipientId,
|
userId: message.recipientId,
|
||||||
})
|
})
|
||||||
|
void pubsub.publish(CHAT_MESSAGE_ADDED, {
|
||||||
|
chatMessageAdded: message,
|
||||||
|
userId: message.recipientId,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return message
|
return message
|
||||||
|
|||||||
@ -423,58 +423,111 @@ describe('Room', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('returns the rooms paginated', async () => {
|
it('returns the rooms paginated', async () => {
|
||||||
expect(await query({ query: roomQuery(), variables: { first: 3, offset: 0 } })).toMatchObject(
|
await expect(
|
||||||
{
|
query({ query: roomQuery(), variables: { first: 3, offset: 0 } }),
|
||||||
|
).resolves.toMatchObject({
|
||||||
errors: undefined,
|
errors: undefined,
|
||||||
data: {
|
data: {
|
||||||
Room: [
|
Room: expect.arrayContaining([
|
||||||
{
|
expect.objectContaining({
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
roomId: expect.any(String),
|
roomId: expect.any(String),
|
||||||
roomName: 'Third Chatting User',
|
roomName: 'Third Chatting User',
|
||||||
|
lastMessageAt: null,
|
||||||
|
unreadCount: 0,
|
||||||
|
lastMessage: null,
|
||||||
users: expect.arrayContaining([
|
users: expect.arrayContaining([
|
||||||
{
|
expect.objectContaining({
|
||||||
_id: 'chatting-user',
|
_id: 'chatting-user',
|
||||||
id: 'chatting-user',
|
id: 'chatting-user',
|
||||||
name: 'Chatting User',
|
name: 'Chatting User',
|
||||||
avatar: {
|
avatar: {
|
||||||
url: expect.any(String),
|
url: expect.any(String),
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
{
|
expect.objectContaining({
|
||||||
_id: 'third-chatting-user',
|
_id: 'third-chatting-user',
|
||||||
id: 'third-chatting-user',
|
id: 'third-chatting-user',
|
||||||
name: 'Third Chatting User',
|
name: 'Third Chatting User',
|
||||||
avatar: {
|
avatar: {
|
||||||
url: expect.any(String),
|
url: expect.any(String),
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
]),
|
]),
|
||||||
},
|
}),
|
||||||
{
|
expect.objectContaining({
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
roomId: expect.any(String),
|
roomId: expect.any(String),
|
||||||
roomName: 'Second Chatting User',
|
roomName: 'Second Chatting User',
|
||||||
|
lastMessageAt: null,
|
||||||
|
unreadCount: 0,
|
||||||
|
lastMessage: null,
|
||||||
users: expect.arrayContaining([
|
users: expect.arrayContaining([
|
||||||
{
|
expect.objectContaining({
|
||||||
_id: 'chatting-user',
|
_id: 'chatting-user',
|
||||||
id: 'chatting-user',
|
id: 'chatting-user',
|
||||||
name: 'Chatting User',
|
name: 'Chatting User',
|
||||||
avatar: {
|
avatar: {
|
||||||
url: expect.any(String),
|
url: expect.any(String),
|
||||||
},
|
},
|
||||||
},
|
}),
|
||||||
{
|
expect.objectContaining({
|
||||||
_id: 'second-chatting-user',
|
_id: 'second-chatting-user',
|
||||||
id: 'second-chatting-user',
|
id: 'second-chatting-user',
|
||||||
name: 'Second Chatting User',
|
name: 'Second Chatting User',
|
||||||
avatar: {
|
avatar: {
|
||||||
url: expect.any(String),
|
url: expect.any(String),
|
||||||
},
|
},
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
roomId: expect.any(String),
|
||||||
|
roomName: 'Other Chatting User',
|
||||||
|
lastMessageAt: expect.any(String),
|
||||||
|
unreadCount: 0,
|
||||||
|
lastMessage: {
|
||||||
|
_id: expect.any(String),
|
||||||
|
id: expect.any(String),
|
||||||
|
content: '2nd message to other chatting user',
|
||||||
|
senderId: 'chatting-user',
|
||||||
|
username: 'Chatting User',
|
||||||
|
avatar: expect.any(String),
|
||||||
|
date: expect.any(String),
|
||||||
|
saved: true,
|
||||||
|
distributed: false,
|
||||||
|
seen: false,
|
||||||
},
|
},
|
||||||
|
users: expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
_id: 'chatting-user',
|
||||||
|
id: 'chatting-user',
|
||||||
|
name: 'Chatting User',
|
||||||
|
avatar: {
|
||||||
|
url: expect.any(String),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
_id: 'other-chatting-user',
|
||||||
|
id: 'other-chatting-user',
|
||||||
|
name: 'Other Chatting User',
|
||||||
|
avatar: {
|
||||||
|
url: expect.any(String),
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
}),
|
||||||
]),
|
]),
|
||||||
},
|
},
|
||||||
{
|
})
|
||||||
|
await expect(
|
||||||
|
query({ query: roomQuery(), variables: { first: 3, offset: 3 } }),
|
||||||
|
).resolves.toMatchObject({
|
||||||
|
errors: undefined,
|
||||||
|
data: {
|
||||||
|
Room: [
|
||||||
|
expect.objectContaining({
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
roomId: expect.any(String),
|
roomId: expect.any(String),
|
||||||
roomName: 'Not Chatting User',
|
roomName: 'Not Chatting User',
|
||||||
@ -496,52 +549,21 @@ describe('Room', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
},
|
}),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
})
|
||||||
)
|
|
||||||
expect(await query({ query: roomQuery(), variables: { first: 3, offset: 3 } })).toMatchObject(
|
|
||||||
{
|
|
||||||
errors: undefined,
|
|
||||||
data: {
|
|
||||||
Room: [
|
|
||||||
{
|
|
||||||
id: expect.any(String),
|
|
||||||
roomId: expect.any(String),
|
|
||||||
roomName: 'Other Chatting User',
|
|
||||||
users: expect.arrayContaining([
|
|
||||||
{
|
|
||||||
_id: 'chatting-user',
|
|
||||||
id: 'chatting-user',
|
|
||||||
name: 'Chatting User',
|
|
||||||
avatar: {
|
|
||||||
url: expect.any(String),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
_id: 'other-chatting-user',
|
|
||||||
id: 'other-chatting-user',
|
|
||||||
name: 'Other Chatting User',
|
|
||||||
avatar: {
|
|
||||||
url: expect.any(String),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('query single room', () => {
|
describe('query single room', () => {
|
||||||
let result: any = null
|
let result: any = null
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
authenticatedUser = await chattingUser.toJson()
|
authenticatedUser = await chattingUser.toJson()
|
||||||
result = await query({ query: roomQuery() })
|
result = await query({ query: roomQuery() })
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('as chatter of room', () => {
|
describe('as chatter of room', () => {
|
||||||
it('returns the room', async () => {
|
it('returns the room', async () => {
|
||||||
expect(
|
expect(
|
||||||
@ -556,34 +578,19 @@ describe('Room', () => {
|
|||||||
{
|
{
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
roomId: expect.any(String),
|
roomId: expect.any(String),
|
||||||
roomName: 'Third Chatting User',
|
roomName: result.data.Room[0].roomName,
|
||||||
users: expect.arrayContaining([
|
users: expect.any(Array),
|
||||||
{
|
|
||||||
_id: 'chatting-user',
|
|
||||||
id: 'chatting-user',
|
|
||||||
name: 'Chatting User',
|
|
||||||
avatar: {
|
|
||||||
url: expect.any(String),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
_id: 'third-chatting-user',
|
|
||||||
id: 'third-chatting-user',
|
|
||||||
name: 'Third Chatting User',
|
|
||||||
avatar: {
|
|
||||||
url: expect.any(String),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('as not chatter of room', () => {
|
describe('as not chatter of room', () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
authenticatedUser = await notChattingUser.toJson()
|
authenticatedUser = await notChattingUser.toJson()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('returns no room', async () => {
|
it('returns no room', async () => {
|
||||||
authenticatedUser = await notChattingUser.toJson()
|
authenticatedUser = await notChattingUser.toJson()
|
||||||
expect(
|
expect(
|
||||||
|
|||||||
@ -44,3 +44,7 @@ type Query {
|
|||||||
orderBy: [_MessageOrdering]
|
orderBy: [_MessageOrdering]
|
||||||
): [Message]
|
): [Message]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Subscription {
|
||||||
|
chatMessageAdded(userId: ID!): Message
|
||||||
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
# TODO change this to last message date
|
# TODO change this to last message date
|
||||||
enum _RoomOrdering {
|
enum _RoomOrdering {
|
||||||
|
lastMessageAt_desc
|
||||||
createdAt_desc
|
createdAt_desc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import bodyParser from 'body-parser'
|
|||||||
import { graphqlUploadExpress } from 'graphql-upload'
|
import { graphqlUploadExpress } from 'graphql-upload'
|
||||||
|
|
||||||
export const NOTIFICATION_ADDED = 'NOTIFICATION_ADDED'
|
export const NOTIFICATION_ADDED = 'NOTIFICATION_ADDED'
|
||||||
// export const CHAT_MESSAGE_ADDED = 'CHAT_MESSAGE_ADDED'
|
export const CHAT_MESSAGE_ADDED = 'CHAT_MESSAGE_ADDED'
|
||||||
export const ROOM_COUNT_UPDATED = 'ROOM_COUNT_UPDATED'
|
export const ROOM_COUNT_UPDATED = 'ROOM_COUNT_UPDATED'
|
||||||
const { REDIS_DOMAIN, REDIS_PORT, REDIS_PASSWORD } = CONFIG
|
const { REDIS_DOMAIN, REDIS_PORT, REDIS_PASSWORD } = CONFIG
|
||||||
let prodPubsub, devPubsub
|
let prodPubsub, devPubsub
|
||||||
|
|||||||
@ -27,4 +27,8 @@
|
|||||||
chatMessageBgOthers: $chat-message-bg-others;
|
chatMessageBgOthers: $chat-message-bg-others;
|
||||||
|
|
||||||
chatNewMessageColor: $chat-new-message-color;
|
chatNewMessageColor: $chat-new-message-color;
|
||||||
|
|
||||||
|
chatMessageTimestamp: $chat-message-timestamp;
|
||||||
|
chatMessageCheckmarkSeen: $chat-message-checkmark-seen;
|
||||||
|
chatMessageCheckmark: $chat-message-checkmark;
|
||||||
}
|
}
|
||||||
@ -417,3 +417,6 @@ $chat-message-color: $text-color-base;
|
|||||||
$chat-message-bg-others: $color-neutral-80;
|
$chat-message-bg-others: $color-neutral-80;
|
||||||
$chat-sidemenu-bg: $color-secondary-active;
|
$chat-sidemenu-bg: $color-secondary-active;
|
||||||
$chat-new-message-color: $color-secondary-active;
|
$chat-new-message-color: $color-secondary-active;
|
||||||
|
$chat-message-timestamp: $text-color-soft;
|
||||||
|
$chat-message-checkmark-seen: $text-color-secondary;
|
||||||
|
$chat-message-checkmark: $text-color-soft;
|
||||||
|
|||||||
67
webapp/components/Chat/AddChatRoomByUserSearch.vue
Normal file
67
webapp/components/Chat/AddChatRoomByUserSearch.vue
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<template>
|
||||||
|
<div class="add-chat-room-by-user-search">
|
||||||
|
<ds-flex class="headline">
|
||||||
|
<h2 class="title">{{ $t('chat.addRoomHeadline') }}</h2>
|
||||||
|
<base-button class="close-button" icon="close" circle @click="closeUserSearch" />
|
||||||
|
</ds-flex>
|
||||||
|
<ds-space margin-bottom="small" />
|
||||||
|
<ds-space>
|
||||||
|
<select-user-search :id="id" ref="selectUserSearch" @select-user="selectUser" />
|
||||||
|
</ds-space>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import SelectUserSearch from '~/components/generic/SelectUserSearch/SelectUserSearch'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'AddChatRoomByUserSearch',
|
||||||
|
components: {
|
||||||
|
SelectUserSearch,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
// chatRooms: {
|
||||||
|
// type: Array,
|
||||||
|
// default: [],
|
||||||
|
// },
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
id: 'search-user-to-add-to-group',
|
||||||
|
user: {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
selectUser(user) {
|
||||||
|
this.user = user
|
||||||
|
// if (this.groupMembers.find((member) => member.id === this.user.id)) {
|
||||||
|
// this.$toast.error(this.$t('group.errors.userAlreadyMember', { name: this.user.name }))
|
||||||
|
// this.$refs.selectUserSearch.clear()
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
this.$refs.selectUserSearch.clear()
|
||||||
|
this.$emit('close-user-search')
|
||||||
|
this.addChatRoom(this.user?.id)
|
||||||
|
},
|
||||||
|
async addChatRoom(userId) {
|
||||||
|
this.$emit('add-chat-room', userId)
|
||||||
|
},
|
||||||
|
closeUserSearch() {
|
||||||
|
this.$emit('close-user-search')
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.add-chat-room-by-user-search {
|
||||||
|
background-color: white;
|
||||||
|
padding: $space-base;
|
||||||
|
}
|
||||||
|
.ds-flex.headline {
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.ds-flex.headline .close-button {
|
||||||
|
margin-top: -6px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -4,7 +4,7 @@
|
|||||||
<vue-advanced-chat
|
<vue-advanced-chat
|
||||||
:theme="theme"
|
:theme="theme"
|
||||||
:current-user-id="currentUser.id"
|
:current-user-id="currentUser.id"
|
||||||
:room-id="null"
|
:room-id="computedRoomId"
|
||||||
:template-actions="JSON.stringify(templatesText)"
|
:template-actions="JSON.stringify(templatesText)"
|
||||||
:menu-actions="JSON.stringify(menuActions)"
|
:menu-actions="JSON.stringify(menuActions)"
|
||||||
:text-messages="JSON.stringify(textMessages)"
|
:text-messages="JSON.stringify(textMessages)"
|
||||||
@ -19,23 +19,42 @@
|
|||||||
show-audio="false"
|
show-audio="false"
|
||||||
:styles="JSON.stringify(computedChatStyle)"
|
:styles="JSON.stringify(computedChatStyle)"
|
||||||
:show-footer="true"
|
:show-footer="true"
|
||||||
@send-message="sendMessage($event.detail[0])"
|
|
||||||
@fetch-messages="fetchMessages($event.detail[0])"
|
|
||||||
@fetch-more-rooms="fetchRooms"
|
|
||||||
:responsive-breakpoint="responsiveBreakpoint"
|
:responsive-breakpoint="responsiveBreakpoint"
|
||||||
:single-room="singleRoom"
|
:single-room="singleRoom"
|
||||||
show-reaction-emojis="false"
|
show-reaction-emojis="false"
|
||||||
|
@send-message="sendMessage($event.detail[0])"
|
||||||
|
@fetch-messages="fetchMessages($event.detail[0])"
|
||||||
|
@fetch-more-rooms="fetchRooms"
|
||||||
|
@add-room="toggleUserSearch"
|
||||||
@show-demo-options="showDemoOptions = $event"
|
@show-demo-options="showDemoOptions = $event"
|
||||||
>
|
>
|
||||||
<div slot="menu-icon" @click.prevent.stop="$emit('close-single-room', true)">
|
<div
|
||||||
<div v-if="singleRoom">
|
v-if="selectedRoom && selectedRoom.roomId"
|
||||||
<ds-icon name="close"></ds-icon>
|
slot="room-options"
|
||||||
|
class="chat-room-options"
|
||||||
|
>
|
||||||
|
<ds-flex v-if="singleRoom">
|
||||||
|
<ds-flex-item centered class="single-chat-bubble">
|
||||||
|
<nuxt-link :to="{ name: 'chat' }">
|
||||||
|
<base-icon name="chat-bubble" />
|
||||||
|
</nuxt-link>
|
||||||
|
</ds-flex-item>
|
||||||
|
<ds-flex-item centered>
|
||||||
|
<div
|
||||||
|
class="vac-svg-button vac-room-options"
|
||||||
|
@click="$emit('close-single-room', true)"
|
||||||
|
>
|
||||||
|
<slot name="menu-icon">
|
||||||
|
<ds-icon name="close" />
|
||||||
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
|
</ds-flex-item>
|
||||||
|
</ds-flex>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div slot="room-header-avatar">
|
<div slot="room-header-avatar">
|
||||||
<div
|
<div
|
||||||
v-if="selectedRoom && selectedRoom.avatar && selectedRoom.avatar !== 'default-avatar'"
|
v-if="selectedRoom && selectedRoom.avatar"
|
||||||
class="vac-avatar"
|
class="vac-avatar"
|
||||||
:style="{ 'background-image': `url('${selectedRoom.avatar}')` }"
|
:style="{ 'background-image': `url('${selectedRoom.avatar}')` }"
|
||||||
/>
|
/>
|
||||||
@ -46,7 +65,7 @@
|
|||||||
|
|
||||||
<div v-for="room in rooms" :slot="'room-list-avatar_' + room.id" :key="room.id">
|
<div v-for="room in rooms" :slot="'room-list-avatar_' + room.id" :key="room.id">
|
||||||
<div
|
<div
|
||||||
v-if="room.avatar && room.avatar !== 'default-avatar'"
|
v-if="room.avatar"
|
||||||
class="vac-avatar"
|
class="vac-avatar"
|
||||||
:style="{ 'background-image': `url('${room.avatar}')` }"
|
:style="{ 'background-image': `url('${room.avatar}')` }"
|
||||||
/>
|
/>
|
||||||
@ -61,7 +80,12 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { roomQuery, createRoom, unreadRoomsQuery } from '~/graphql/Rooms'
|
import { roomQuery, createRoom, unreadRoomsQuery } from '~/graphql/Rooms'
|
||||||
import { messageQuery, createMessageMutation, markMessagesAsSeen } from '~/graphql/Messages'
|
import {
|
||||||
|
messageQuery,
|
||||||
|
createMessageMutation,
|
||||||
|
chatMessageAdded,
|
||||||
|
markMessagesAsSeen,
|
||||||
|
} from '~/graphql/Messages'
|
||||||
import chatStyle from '~/constants/chat.js'
|
import chatStyle from '~/constants/chat.js'
|
||||||
import { mapGetters, mapMutations } from 'vuex'
|
import { mapGetters, mapMutations } from 'vuex'
|
||||||
|
|
||||||
@ -70,8 +94,13 @@ export default {
|
|||||||
props: {
|
props: {
|
||||||
theme: {
|
theme: {
|
||||||
type: String,
|
type: String,
|
||||||
|
default: 'light',
|
||||||
},
|
},
|
||||||
singleRoomId: {
|
singleRoom: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
roomId: {
|
||||||
type: String,
|
type: String,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
@ -79,11 +108,6 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
menuActions: [
|
menuActions: [
|
||||||
// NOTE: if menuActions is empty, the related slot is not shown
|
|
||||||
{
|
|
||||||
name: 'dummyItem',
|
|
||||||
title: 'Just a dummy item',
|
|
||||||
},
|
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
name: 'inviteUser',
|
name: 'inviteUser',
|
||||||
@ -139,8 +163,7 @@ export default {
|
|||||||
roomsLoaded: false,
|
roomsLoaded: false,
|
||||||
roomPage: 0,
|
roomPage: 0,
|
||||||
roomPageSize: 10,
|
roomPageSize: 10,
|
||||||
singleRoom: !!this.singleRoomId || false,
|
selectedRoom: this.roomId,
|
||||||
selectedRoom: null,
|
|
||||||
loadingRooms: true,
|
loadingRooms: true,
|
||||||
messagesLoaded: false,
|
messagesLoaded: false,
|
||||||
messagePage: 0,
|
messagePage: 0,
|
||||||
@ -150,33 +173,47 @@ export default {
|
|||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (this.singleRoom) {
|
if (this.singleRoom) {
|
||||||
this.$apollo
|
this.newRoom(this.roomId)
|
||||||
.mutate({
|
|
||||||
mutation: createRoom(),
|
|
||||||
variables: {
|
|
||||||
userId: this.singleRoomId,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.then(({ data: { CreateRoom } }) => {
|
|
||||||
this.fetchRooms({ room: CreateRoom })
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
this.$toast.error(error)
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
// this.loading = false
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
this.fetchRooms()
|
this.fetchRooms()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Subscriptions
|
||||||
|
const observer = this.$apollo.subscribe({
|
||||||
|
query: chatMessageAdded(),
|
||||||
|
variables: {
|
||||||
|
userId: this.currentUser.id,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
observer.subscribe({
|
||||||
|
next: this.chatMessageAdded,
|
||||||
|
error(error) {
|
||||||
|
this.$toast.error(error)
|
||||||
|
},
|
||||||
|
})
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters({
|
...mapGetters({
|
||||||
currentUser: 'auth/user',
|
currentUser: 'auth/user',
|
||||||
|
getStoreRoomId: 'chat/roomID',
|
||||||
}),
|
}),
|
||||||
computedChatStyle() {
|
computedChatStyle() {
|
||||||
return chatStyle.STYLE.light
|
return chatStyle.STYLE.light
|
||||||
},
|
},
|
||||||
|
computedRoomId() {
|
||||||
|
let roomId = null
|
||||||
|
|
||||||
|
if (!this.singleRoom) {
|
||||||
|
roomId = this.roomId
|
||||||
|
|
||||||
|
if (this.getStoreRoomId.roomId) {
|
||||||
|
roomId = this.getStoreRoomId.roomId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return roomId
|
||||||
|
},
|
||||||
textMessages() {
|
textMessages() {
|
||||||
return {
|
return {
|
||||||
ROOMS_EMPTY: this.$t('chat.roomsEmpty'),
|
ROOMS_EMPTY: this.$t('chat.roomsEmpty'),
|
||||||
@ -197,7 +234,9 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
...mapMutations({
|
...mapMutations({
|
||||||
commitUnreadRoomCount: 'chat/UPDATE_ROOM_COUNT',
|
commitUnreadRoomCount: 'chat/UPDATE_ROOM_COUNT',
|
||||||
|
commitRoomIdFromSingleRoom: 'chat/UPDATE_ROOM_ID',
|
||||||
}),
|
}),
|
||||||
|
|
||||||
async fetchRooms({ room } = {}) {
|
async fetchRooms({ room } = {}) {
|
||||||
this.roomsLoaded = false
|
this.roomsLoaded = false
|
||||||
const offset = this.roomPage * this.roomPageSize
|
const offset = this.roomPage * this.roomPageSize
|
||||||
@ -214,21 +253,27 @@ export default {
|
|||||||
fetchPolicy: 'no-cache',
|
fetchPolicy: 'no-cache',
|
||||||
})
|
})
|
||||||
|
|
||||||
const newRooms = Room.map((r) => {
|
const rms = []
|
||||||
return {
|
const rmsIds = []
|
||||||
...r,
|
;[...Room, ...this.rooms].forEach((r) => {
|
||||||
users: r.users.map((u) => {
|
if (!rmsIds.find((v) => v === r.id)) {
|
||||||
return { ...u, username: u.name, avatar: u.avatar?.url }
|
rms.push(this.fixRoomObject(r))
|
||||||
}),
|
rmsIds.push(r.id)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
this.rooms = rms
|
||||||
this.rooms = [...this.rooms, ...newRooms]
|
|
||||||
|
|
||||||
if (Room.length < this.roomPageSize) {
|
if (Room.length < this.roomPageSize) {
|
||||||
this.roomsLoaded = true
|
this.roomsLoaded = true
|
||||||
}
|
}
|
||||||
this.roomPage += 1
|
this.roomPage += 1
|
||||||
|
|
||||||
|
if (this.singleRoom && this.rooms.length > 0) {
|
||||||
|
this.commitRoomIdFromSingleRoom(this.rooms[0].roomId)
|
||||||
|
} else if (this.getStoreRoomId.roomId) {
|
||||||
|
// reset store room id
|
||||||
|
this.commitRoomIdFromSingleRoom(null)
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.rooms = []
|
this.rooms = []
|
||||||
this.$toast.error(error.message)
|
this.$toast.error(error.message)
|
||||||
@ -258,8 +303,14 @@ export default {
|
|||||||
fetchPolicy: 'no-cache',
|
fetchPolicy: 'no-cache',
|
||||||
})
|
})
|
||||||
|
|
||||||
const newMsgIds = Message.filter((m) => m.seen === false).map((m) => m.id)
|
const newMsgIds = Message.filter(
|
||||||
|
(m) => m.seen === false && m.senderId !== this.currentUser.id,
|
||||||
|
).map((m) => m.id)
|
||||||
if (newMsgIds.length) {
|
if (newMsgIds.length) {
|
||||||
|
const roomIndex = this.rooms.findIndex((r) => r.id === room.id)
|
||||||
|
const changedRoom = { ...this.rooms[roomIndex] }
|
||||||
|
changedRoom.unreadCount = changedRoom.unreadCount - newMsgIds.length
|
||||||
|
this.rooms[roomIndex] = changedRoom
|
||||||
this.$apollo
|
this.$apollo
|
||||||
.mutate({
|
.mutate({
|
||||||
mutation: markMessagesAsSeen(),
|
mutation: markMessagesAsSeen(),
|
||||||
@ -297,21 +348,41 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async chatMessageAdded({ data }) {
|
||||||
|
const roomIndex = this.rooms.findIndex((r) => r.id === data.chatMessageAdded.room.id)
|
||||||
|
const changedRoom = { ...this.rooms[roomIndex] }
|
||||||
|
changedRoom.lastMessage = data.chatMessageAdded
|
||||||
|
changedRoom.lastMessage.content = changedRoom.lastMessage.content.trim().substring(0, 30)
|
||||||
|
changedRoom.lastMessageAt = data.chatMessageAdded.date
|
||||||
|
changedRoom.unreadCount++
|
||||||
|
this.rooms[roomIndex] = changedRoom
|
||||||
|
if (data.chatMessageAdded.room.id === this.selectedRoom?.id) {
|
||||||
|
this.fetchMessages({ room: this.selectedRoom, options: { refetch: true } })
|
||||||
|
} else {
|
||||||
|
this.fetchRooms({ options: { refetch: true } })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
async sendMessage(message) {
|
async sendMessage(message) {
|
||||||
// check for usersTag and change userid to username
|
|
||||||
message.usersTag.forEach((userTag) => {
|
|
||||||
const needle = `<usertag>${userTag.id}</usertag>`
|
|
||||||
const replacement = `<usertag>@${userTag.name.replaceAll(' ', '-').toLowerCase()}</usertag>`
|
|
||||||
message.content = message.content.replaceAll(needle, replacement)
|
|
||||||
})
|
|
||||||
try {
|
try {
|
||||||
await this.$apollo.mutate({
|
const {
|
||||||
|
data: { CreateMessage: createdMessage },
|
||||||
|
} = await this.$apollo.mutate({
|
||||||
mutation: createMessageMutation(),
|
mutation: createMessageMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
roomId: message.roomId,
|
roomId: message.roomId,
|
||||||
content: message.content,
|
content: message.content,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
const roomIndex = this.rooms.findIndex((r) => r.id === message.roomId)
|
||||||
|
const changedRoom = { ...this.rooms[roomIndex] }
|
||||||
|
changedRoom.lastMessage = createdMessage
|
||||||
|
changedRoom.lastMessage.content = changedRoom.lastMessage.content.trim().substring(0, 30)
|
||||||
|
// move current room to top (not 100% working)
|
||||||
|
// const rooms = [...this.rooms]
|
||||||
|
// rooms.splice(roomIndex,1)
|
||||||
|
// this.rooms = [changedRoom, ...rooms]
|
||||||
|
this.rooms[roomIndex] = changedRoom
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.$toast.error(error.message)
|
this.$toast.error(error.message)
|
||||||
}
|
}
|
||||||
@ -325,6 +396,58 @@ export default {
|
|||||||
if (!fullname) return
|
if (!fullname) return
|
||||||
return fullname.match(/\b\w/g).join('').substring(0, 3).toUpperCase()
|
return fullname.match(/\b\w/g).join('').substring(0, 3).toUpperCase()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
toggleUserSearch() {
|
||||||
|
this.$emit('toggle-user-search')
|
||||||
|
},
|
||||||
|
|
||||||
|
fixRoomObject(room) {
|
||||||
|
// This fixes the room object which arrives from the backend
|
||||||
|
const fixedRoom = {
|
||||||
|
...room,
|
||||||
|
index: room.lastMessage ? room.lastMessage.date : room.createdAt,
|
||||||
|
lastMessage: room.lastMessage
|
||||||
|
? {
|
||||||
|
...room.lastMessage,
|
||||||
|
content: room.lastMessage?.content?.trim().substring(0, 30),
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
users: room.users.map((u) => {
|
||||||
|
return { ...u, username: u.name, avatar: u.avatar?.url }
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
if (!fixedRoom.avatar) {
|
||||||
|
// as long as we cannot query avatar on CreateRoom
|
||||||
|
fixedRoom.avatar = fixedRoom.users.find((u) => u.id !== this.currentUser.id).avatar
|
||||||
|
}
|
||||||
|
return fixedRoom
|
||||||
|
},
|
||||||
|
|
||||||
|
newRoom(userId) {
|
||||||
|
this.$apollo
|
||||||
|
.mutate({
|
||||||
|
mutation: createRoom(),
|
||||||
|
variables: {
|
||||||
|
userId,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.then(({ data: { CreateRoom } }) => {
|
||||||
|
const roomIndex = this.rooms.findIndex((r) => r.id === CreateRoom.roomId)
|
||||||
|
const room = this.fixRoomObject(CreateRoom)
|
||||||
|
|
||||||
|
if (roomIndex === -1) {
|
||||||
|
this.rooms = [room, ...this.rooms]
|
||||||
|
}
|
||||||
|
this.fetchMessages({ room, options: { refetch: true } })
|
||||||
|
this.$emit('show-chat', CreateRoom.id)
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.$toast.error(error.message)
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
// this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@ -353,4 +476,8 @@ body {
|
|||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ds-flex-item.single-chat-bubble {
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -8,7 +8,6 @@
|
|||||||
:disabled="disabled && !update"
|
:disabled="disabled && !update"
|
||||||
@click="handleCancel"
|
@click="handleCancel"
|
||||||
data-test="cancel-button"
|
data-test="cancel-button"
|
||||||
danger
|
|
||||||
>
|
>
|
||||||
{{ $t('actions.cancel') }}
|
{{ $t('actions.cancel') }}
|
||||||
</base-button>
|
</base-button>
|
||||||
|
|||||||
@ -58,14 +58,14 @@ export default {
|
|||||||
routes.push({
|
routes.push({
|
||||||
label: this.$t('group.contentMenu.visitGroupPage'),
|
label: this.$t('group.contentMenu.visitGroupPage'),
|
||||||
icon: 'home',
|
icon: 'home',
|
||||||
name: 'group-id-slug',
|
path: `/groups/${this.group.id}`,
|
||||||
params: { id: this.group.id, slug: this.group.slug },
|
params: { id: this.group.id, slug: this.group.slug },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (this.group.myRole === 'owner') {
|
if (this.group.myRole === 'owner') {
|
||||||
routes.push({
|
routes.push({
|
||||||
label: this.$t('admin.settings.name'),
|
label: this.$t('admin.settings.name'),
|
||||||
path: `/group/edit/${this.group.id}`,
|
path: `/groups/edit/${this.group.id}`,
|
||||||
icon: 'edit',
|
icon: 'edit',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -169,12 +169,7 @@
|
|||||||
</ds-flex-item>
|
</ds-flex-item>
|
||||||
<ds-flex-item width="0.15" />
|
<ds-flex-item width="0.15" />
|
||||||
<ds-flex-item class="action-buttons-group" width="2">
|
<ds-flex-item class="action-buttons-group" width="2">
|
||||||
<base-button
|
<base-button data-test="cancel-button" :disabled="loading" @click="$router.back()">
|
||||||
data-test="cancel-button"
|
|
||||||
:disabled="loading"
|
|
||||||
@click="$router.back()"
|
|
||||||
danger
|
|
||||||
>
|
|
||||||
{{ $t('actions.cancel') }}
|
{{ $t('actions.cancel') }}
|
||||||
</base-button>
|
</base-button>
|
||||||
<base-button type="submit" icon="check" :loading="loading" :disabled="errors" filled>
|
<base-button type="submit" icon="check" :loading="loading" :disabled="errors" filled>
|
||||||
|
|||||||
@ -3,33 +3,7 @@
|
|||||||
<h2 class="title">{{ $t('group.addUser') }}</h2>
|
<h2 class="title">{{ $t('group.addUser') }}</h2>
|
||||||
<ds-space margin-bottom="small" />
|
<ds-space margin-bottom="small" />
|
||||||
<ds-space>
|
<ds-space>
|
||||||
<ds-select
|
<select-user-search :id="id" ref="selectUserSearch" @select-user="selectUser" />
|
||||||
type="search"
|
|
||||||
icon="search"
|
|
||||||
label-prop="id"
|
|
||||||
v-model="query"
|
|
||||||
:id="id"
|
|
||||||
:icon-right="null"
|
|
||||||
:options="users"
|
|
||||||
:loading="$apollo.queries.searchUsers.loading"
|
|
||||||
:filter="(item) => item"
|
|
||||||
:no-options-available="$t('group.addUserNoOptions')"
|
|
||||||
:auto-reset-search="true"
|
|
||||||
:placeholder="$t('group.addUserPlaceholder')"
|
|
||||||
@focus.capture.native="onFocus"
|
|
||||||
@input.native="handleInput"
|
|
||||||
@keyup.enter.native="onEnter"
|
|
||||||
@keyup.delete.native="onDelete"
|
|
||||||
@keyup.esc.native="clear"
|
|
||||||
@blur.capture.native="onBlur"
|
|
||||||
@input.exact="onSelect"
|
|
||||||
>
|
|
||||||
<template #option="{ option }">
|
|
||||||
<p>
|
|
||||||
<user-teaser :user="option" :showPopover="false" :linkToProfile="false" />
|
|
||||||
</p>
|
|
||||||
</template>
|
|
||||||
</ds-select>
|
|
||||||
<ds-modal
|
<ds-modal
|
||||||
v-if="isOpen"
|
v-if="isOpen"
|
||||||
force
|
force
|
||||||
@ -49,16 +23,15 @@
|
|||||||
</ds-space>
|
</ds-space>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { changeGroupMemberRoleMutation } from '~/graphql/groups.js'
|
import { changeGroupMemberRoleMutation } from '~/graphql/groups.js'
|
||||||
import { searchUsers } from '~/graphql/Search.js'
|
import SelectUserSearch from '~/components/generic/SelectUserSearch/SelectUserSearch'
|
||||||
import UserTeaser from '~/components/UserTeaser/UserTeaser.vue'
|
|
||||||
import { isEmpty } from 'lodash'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AddGroupMember',
|
name: 'AddGroupMember',
|
||||||
components: {
|
components: {
|
||||||
UserTeaser,
|
SelectUserSearch,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
groupId: {
|
groupId: {
|
||||||
@ -72,62 +45,34 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
users: [],
|
|
||||||
id: 'search-user-to-add-to-group',
|
id: 'search-user-to-add-to-group',
|
||||||
query: '',
|
|
||||||
user: {},
|
user: {},
|
||||||
isOpen: false,
|
isOpen: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
startSearch() {
|
|
||||||
return this.query && this.query.length > 3
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
cancelModal() {
|
cancelModal() {
|
||||||
this.clear()
|
this.$refs.selectUserSearch.clear()
|
||||||
this.isOpen = false
|
this.isOpen = false
|
||||||
},
|
},
|
||||||
closeModal() {
|
closeModal() {
|
||||||
this.clear()
|
this.$refs.selectUserSearch.clear()
|
||||||
this.isOpen = false
|
this.isOpen = false
|
||||||
},
|
},
|
||||||
confirmModal() {
|
confirmModal() {
|
||||||
this.addMemberToGroup()
|
this.addMemberToGroup()
|
||||||
this.isOpen = false
|
this.isOpen = false
|
||||||
this.clear()
|
this.$refs.selectUserSearch.clear()
|
||||||
},
|
},
|
||||||
onFocus() {},
|
selectUser(user) {
|
||||||
onBlur() {
|
this.user = user
|
||||||
this.query = ''
|
|
||||||
},
|
|
||||||
handleInput(event) {
|
|
||||||
this.query = event.target ? event.target.value.trim() : ''
|
|
||||||
},
|
|
||||||
onDelete(event) {
|
|
||||||
const value = event.target ? event.target.value.trim() : ''
|
|
||||||
if (isEmpty(value)) {
|
|
||||||
this.clear()
|
|
||||||
} else {
|
|
||||||
this.handleInput(event)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
clear() {
|
|
||||||
this.query = ''
|
|
||||||
this.user = {}
|
|
||||||
this.users = []
|
|
||||||
},
|
|
||||||
onSelect(item) {
|
|
||||||
this.user = item
|
|
||||||
if (this.groupMembers.find((member) => member.id === this.user.id)) {
|
if (this.groupMembers.find((member) => member.id === this.user.id)) {
|
||||||
this.$toast.error(this.$t('group.errors.userAlreadyMember', { name: this.user.name }))
|
this.$toast.error(this.$t('group.errors.userAlreadyMember', { name: this.user.name }))
|
||||||
this.clear()
|
this.$refs.selectUserSearch.clear()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.isOpen = true
|
this.isOpen = true
|
||||||
},
|
},
|
||||||
onEnter() {},
|
|
||||||
async addMemberToGroup() {
|
async addMemberToGroup() {
|
||||||
const newRole = 'usual'
|
const newRole = 'usual'
|
||||||
const username = this.user.name
|
const username = this.user.name
|
||||||
@ -148,29 +93,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
apollo: {
|
|
||||||
searchUsers: {
|
|
||||||
query() {
|
|
||||||
return searchUsers
|
|
||||||
},
|
|
||||||
variables() {
|
|
||||||
return {
|
|
||||||
query: this.query,
|
|
||||||
firstUsers: 5,
|
|
||||||
usersOffset: 0,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
skip() {
|
|
||||||
return !this.startSearch
|
|
||||||
},
|
|
||||||
update({ searchUsers }) {
|
|
||||||
this.users = searchUsers.users
|
|
||||||
},
|
|
||||||
fetchPolicy: 'cache-and-network',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.add-group-member {
|
.add-group-member {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<nuxt-link
|
<nuxt-link
|
||||||
class="group-teaser"
|
class="group-teaser"
|
||||||
:to="{ name: 'group-id-slug', params: { id: group.id, slug: group.slug } }"
|
:to="{ name: 'groups-id-slug', params: { id: group.id, slug: group.slug } }"
|
||||||
>
|
>
|
||||||
<base-card
|
<base-card
|
||||||
:class="{
|
:class="{
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
<p class="description">{{ $t(`notifications.reason.${notification.reason}`) }}</p>
|
<p class="description">{{ $t(`notifications.reason.${notification.reason}`) }}</p>
|
||||||
<nuxt-link
|
<nuxt-link
|
||||||
class="link"
|
class="link"
|
||||||
:to="{ name: isGroup ? 'group-id-slug' : 'post-id-slug', params, ...hashParam }"
|
:to="{ name: isGroup ? 'groups-id-slug' : 'post-id-slug', params, ...hashParam }"
|
||||||
@click.native="$emit('read')"
|
@click.native="$emit('read')"
|
||||||
>
|
>
|
||||||
<base-card wideContent>
|
<base-card wideContent>
|
||||||
|
|||||||
@ -65,7 +65,7 @@
|
|||||||
class="notification-mention-post"
|
class="notification-mention-post"
|
||||||
:class="{ 'notification-status': notification.read }"
|
:class="{ 'notification-status': notification.read }"
|
||||||
:to="{
|
:to="{
|
||||||
name: isGroup(notification.from) ? 'group-id-slug' : 'post-id-slug',
|
name: isGroup(notification.from) ? 'groups-id-slug' : 'post-id-slug',
|
||||||
params: params(notification.from),
|
params: params(notification.from),
|
||||||
hash: hashParam(notification.from),
|
hash: hashParam(notification.from),
|
||||||
}"
|
}"
|
||||||
|
|||||||
@ -96,7 +96,7 @@ export default {
|
|||||||
groupLink() {
|
groupLink() {
|
||||||
const { id, slug } = this.group
|
const { id, slug } = this.group
|
||||||
if (!(id && slug)) return ''
|
if (!(id && slug)) return ''
|
||||||
return { name: 'group-id-slug', params: { slug, id } }
|
return { name: 'groups-id-slug', params: { slug, id } }
|
||||||
},
|
},
|
||||||
groupSlug() {
|
groupSlug() {
|
||||||
const { slug } = this.group || {}
|
const { slug } = this.group || {}
|
||||||
|
|||||||
@ -56,7 +56,7 @@
|
|||||||
>
|
>
|
||||||
{{ isEditing ? $t('actions.save') : texts.addButton }}
|
{{ isEditing ? $t('actions.save') : texts.addButton }}
|
||||||
</base-button>
|
</base-button>
|
||||||
<base-button v-if="isEditing" id="cancel" danger @click="handleCancel()">
|
<base-button v-if="isEditing" id="cancel" @click="handleCancel()">
|
||||||
{{ $t('actions.cancel') }}
|
{{ $t('actions.cancel') }}
|
||||||
</base-button>
|
</base-button>
|
||||||
</ds-space>
|
</ds-space>
|
||||||
|
|||||||
@ -148,7 +148,7 @@ export default {
|
|||||||
case 'User':
|
case 'User':
|
||||||
return 'profile-id-slug'
|
return 'profile-id-slug'
|
||||||
case 'Group':
|
case 'Group':
|
||||||
return 'group-id-slug'
|
return 'groups-id-slug'
|
||||||
default:
|
default:
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
109
webapp/components/generic/SelectUserSearch/SelectUserSearch.vue
Normal file
109
webapp/components/generic/SelectUserSearch/SelectUserSearch.vue
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
<template>
|
||||||
|
<ds-select
|
||||||
|
class="select-user-search"
|
||||||
|
type="search"
|
||||||
|
icon="search"
|
||||||
|
label-prop="id"
|
||||||
|
v-model="query"
|
||||||
|
:id="id"
|
||||||
|
:icon-right="null"
|
||||||
|
:options="users"
|
||||||
|
:loading="$apollo.queries.searchUsers.loading"
|
||||||
|
:filter="(item) => item"
|
||||||
|
:no-options-available="$t('group.addUserNoOptions')"
|
||||||
|
:auto-reset-search="true"
|
||||||
|
:placeholder="$t('group.addUserPlaceholder')"
|
||||||
|
@focus.capture.native="onFocus"
|
||||||
|
@input.native="handleInput"
|
||||||
|
@keyup.enter.native="onEnter"
|
||||||
|
@keyup.delete.native="onDelete"
|
||||||
|
@keyup.esc.native="clear"
|
||||||
|
@blur.capture.native="onBlur"
|
||||||
|
@input.exact="onSelect"
|
||||||
|
>
|
||||||
|
<template #option="{ option }">
|
||||||
|
<p>
|
||||||
|
<user-teaser :user="option" :showPopover="false" :linkToProfile="false" />
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
</ds-select>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { isEmpty } from 'lodash'
|
||||||
|
import { searchUsers } from '~/graphql/Search.js'
|
||||||
|
import UserTeaser from '~/components/UserTeaser/UserTeaser.vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'SelectUserSearch',
|
||||||
|
components: {
|
||||||
|
UserTeaser,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
id: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
users: [],
|
||||||
|
query: '',
|
||||||
|
user: {},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
startSearch() {
|
||||||
|
return this.query && this.query.length > 3
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onFocus() {},
|
||||||
|
onBlur() {
|
||||||
|
this.query = ''
|
||||||
|
},
|
||||||
|
handleInput(event) {
|
||||||
|
this.query = event.target ? event.target.value.trim() : ''
|
||||||
|
},
|
||||||
|
onDelete(event) {
|
||||||
|
const value = event.target ? event.target.value.trim() : ''
|
||||||
|
if (isEmpty(value)) {
|
||||||
|
this.clear()
|
||||||
|
} else {
|
||||||
|
this.handleInput(event)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clear() {
|
||||||
|
this.query = ''
|
||||||
|
this.user = {}
|
||||||
|
this.users = []
|
||||||
|
},
|
||||||
|
onSelect(item) {
|
||||||
|
this.user = item
|
||||||
|
this.$emit('select-user', this.user)
|
||||||
|
},
|
||||||
|
onEnter() {},
|
||||||
|
},
|
||||||
|
apollo: {
|
||||||
|
searchUsers: {
|
||||||
|
query() {
|
||||||
|
return searchUsers
|
||||||
|
},
|
||||||
|
variables() {
|
||||||
|
return {
|
||||||
|
query: this.query,
|
||||||
|
firstUsers: 5,
|
||||||
|
usersOffset: 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
skip() {
|
||||||
|
return !this.startSearch
|
||||||
|
},
|
||||||
|
update({ searchUsers }) {
|
||||||
|
this.users = searchUsers.users
|
||||||
|
},
|
||||||
|
fetchPolicy: 'cache-and-network',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@ -65,7 +65,7 @@ const STYLE = {
|
|||||||
backgroundSelected: '#c2dcf2',
|
backgroundSelected: '#c2dcf2',
|
||||||
colorDeleted: '#757e85',
|
colorDeleted: '#757e85',
|
||||||
colorUsername: '#9ca6af',
|
colorUsername: '#9ca6af',
|
||||||
colorTimestamp: '#828c94',
|
colorTimestamp: styleData.chatMessageTimestamp,
|
||||||
backgroundDate: '#e5effa',
|
backgroundDate: '#e5effa',
|
||||||
colorDate: '#505a62',
|
colorDate: '#505a62',
|
||||||
backgroundSystem: '#e5effa',
|
backgroundSystem: '#e5effa',
|
||||||
@ -134,8 +134,8 @@ const STYLE = {
|
|||||||
emojiReaction: 'rgba(0, 0, 0, 0.3)',
|
emojiReaction: 'rgba(0, 0, 0, 0.3)',
|
||||||
document: styleData.colorPrimary,
|
document: styleData.colorPrimary,
|
||||||
pencil: '#9e9e9e',
|
pencil: '#9e9e9e',
|
||||||
checkmark: '#9e9e9e',
|
checkmark: styleData.chatMessageCheckmark,
|
||||||
checkmarkSeen: '#0696c7',
|
checkmarkSeen: styleData.chatMessageCheckmarkSeen,
|
||||||
eye: '#fff',
|
eye: '#fff',
|
||||||
dropdownMessage: '#fff',
|
dropdownMessage: '#fff',
|
||||||
dropdownMessageBackground: 'rgba(0, 0, 0, 0.25)',
|
dropdownMessageBackground: 'rgba(0, 0, 0, 0.25)',
|
||||||
|
|||||||
@ -1,5 +1,31 @@
|
|||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
|
export const createMessageMutation = () => {
|
||||||
|
return gql`
|
||||||
|
mutation ($roomId: ID!, $content: String!) {
|
||||||
|
CreateMessage(roomId: $roomId, content: $content) {
|
||||||
|
#_id
|
||||||
|
id
|
||||||
|
indexId
|
||||||
|
content
|
||||||
|
senderId
|
||||||
|
author {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
username
|
||||||
|
avatar
|
||||||
|
date
|
||||||
|
room {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
saved
|
||||||
|
distributed
|
||||||
|
seen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
}
|
||||||
|
|
||||||
export const messageQuery = () => {
|
export const messageQuery = () => {
|
||||||
return gql`
|
return gql`
|
||||||
query ($roomId: ID!, $first: Int, $offset: Int) {
|
query ($roomId: ID!, $first: Int, $offset: Int) {
|
||||||
@ -15,6 +41,9 @@ export const messageQuery = () => {
|
|||||||
username
|
username
|
||||||
avatar
|
avatar
|
||||||
date
|
date
|
||||||
|
room {
|
||||||
|
id
|
||||||
|
}
|
||||||
saved
|
saved
|
||||||
distributed
|
distributed
|
||||||
seen
|
seen
|
||||||
@ -23,12 +52,27 @@ export const messageQuery = () => {
|
|||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createMessageMutation = () => {
|
export const chatMessageAdded = () => {
|
||||||
return gql`
|
return gql`
|
||||||
mutation ($roomId: ID!, $content: String!) {
|
subscription chatMessageAdded($userId: ID!) {
|
||||||
CreateMessage(roomId: $roomId, content: $content) {
|
chatMessageAdded(userId: $userId) {
|
||||||
|
_id
|
||||||
id
|
id
|
||||||
|
indexId
|
||||||
content
|
content
|
||||||
|
senderId
|
||||||
|
author {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
username
|
||||||
|
avatar
|
||||||
|
date
|
||||||
|
room {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
saved
|
||||||
|
distributed
|
||||||
|
seen
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,12 +1,15 @@
|
|||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
export const roomQuery = () => gql`
|
export const createRoom = () => gql`
|
||||||
query Room($first: Int, $offset: Int, $id: ID) {
|
mutation ($userId: ID!) {
|
||||||
Room(first: $first, offset: $offset, id: $id, orderBy: createdAt_desc) {
|
CreateRoom(userId: $userId) {
|
||||||
id
|
id
|
||||||
roomId
|
roomId
|
||||||
roomName
|
roomName
|
||||||
avatar
|
lastMessageAt
|
||||||
|
createdAt
|
||||||
|
unreadCount
|
||||||
|
#avatar
|
||||||
users {
|
users {
|
||||||
_id
|
_id
|
||||||
id
|
id
|
||||||
@ -19,11 +22,36 @@ export const roomQuery = () => gql`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
export const createRoom = () => gql`
|
export const roomQuery = () => gql`
|
||||||
mutation ($userId: ID!) {
|
query Room($first: Int, $offset: Int, $id: ID) {
|
||||||
CreateRoom(userId: $userId) {
|
Room(first: $first, offset: $offset, id: $id, orderBy: [createdAt_desc, lastMessageAt_desc]) {
|
||||||
id
|
id
|
||||||
roomId
|
roomId
|
||||||
|
roomName
|
||||||
|
avatar
|
||||||
|
lastMessageAt
|
||||||
|
createdAt
|
||||||
|
unreadCount
|
||||||
|
lastMessage {
|
||||||
|
_id
|
||||||
|
id
|
||||||
|
content
|
||||||
|
senderId
|
||||||
|
username
|
||||||
|
avatar
|
||||||
|
date
|
||||||
|
saved
|
||||||
|
distributed
|
||||||
|
seen
|
||||||
|
}
|
||||||
|
users {
|
||||||
|
_id
|
||||||
|
id
|
||||||
|
name
|
||||||
|
avatar {
|
||||||
|
url
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|||||||
@ -13,33 +13,40 @@
|
|||||||
<client-only>
|
<client-only>
|
||||||
<modal />
|
<modal />
|
||||||
</client-only>
|
</client-only>
|
||||||
<div v-if="$store.getters['chat/showChat'].showChat" class="chat-modul">
|
<div v-if="getShowChat.showChat" class="chat-modul">
|
||||||
<chat-module
|
<chat singleRoom :roomId="getShowChat.roomID" @close-single-room="closeSingleRoom" />
|
||||||
v-on:close-single-room="closeSingleRoom"
|
|
||||||
:singleRoomId="$store.getters['chat/showChat'].roomID"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { mapGetters, mapMutations } from 'vuex'
|
||||||
import seo from '~/mixins/seo'
|
import seo from '~/mixins/seo'
|
||||||
import mobile from '~/mixins/mobile'
|
import mobile from '~/mixins/mobile'
|
||||||
import HeaderMenu from '~/components/HeaderMenu/HeaderMenu'
|
import HeaderMenu from '~/components/HeaderMenu/HeaderMenu'
|
||||||
import Modal from '~/components/Modal'
|
import Modal from '~/components/Modal'
|
||||||
import PageFooter from '~/components/PageFooter/PageFooter'
|
import PageFooter from '~/components/PageFooter/PageFooter'
|
||||||
import ChatModule from '~/components/Chat/Chat.vue'
|
import Chat from '~/components/Chat/Chat.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
HeaderMenu,
|
HeaderMenu,
|
||||||
Modal,
|
Modal,
|
||||||
PageFooter,
|
PageFooter,
|
||||||
ChatModule,
|
Chat,
|
||||||
},
|
},
|
||||||
mixins: [seo, mobile()],
|
mixins: [seo, mobile()],
|
||||||
|
computed: {
|
||||||
|
...mapGetters({
|
||||||
|
getShowChat: 'chat/showChat',
|
||||||
|
}),
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
...mapMutations({
|
||||||
|
showChat: 'chat/SET_OPEN_CHAT',
|
||||||
|
}),
|
||||||
closeSingleRoom() {
|
closeSingleRoom() {
|
||||||
this.$store.commit('chat/SET_OPEN_CHAT', { showChat: false, roomID: null })
|
this.showChat({ showChat: false, roomID: null })
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
beforeCreate() {
|
beforeCreate() {
|
||||||
|
|||||||
@ -78,6 +78,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"chat": {
|
"chat": {
|
||||||
|
"addRoomHeadline": "Suche Nutzer für neuen Chat",
|
||||||
"cancelSelectMessage": "Abbrechen",
|
"cancelSelectMessage": "Abbrechen",
|
||||||
"conversationStarted": "Unterhaltung startete am:",
|
"conversationStarted": "Unterhaltung startete am:",
|
||||||
"isOnline": "online",
|
"isOnline": "online",
|
||||||
@ -86,9 +87,12 @@
|
|||||||
"messageDeleted": "Diese Nachricht wuerde gelöscht",
|
"messageDeleted": "Diese Nachricht wuerde gelöscht",
|
||||||
"messagesEmpty": "Keine Nachrichten",
|
"messagesEmpty": "Keine Nachrichten",
|
||||||
"newMessages": "Neue Nachrichten",
|
"newMessages": "Neue Nachrichten",
|
||||||
|
"page": {
|
||||||
|
"headline": "Chat"
|
||||||
|
},
|
||||||
"roomEmpty": "Keinen Raum selektiert",
|
"roomEmpty": "Keinen Raum selektiert",
|
||||||
"roomsEmpty": "Keine Räume",
|
"roomsEmpty": "Keine Räume",
|
||||||
"search": "Suche",
|
"search": "Chat-Räume filtern",
|
||||||
"typeMessage": "Nachricht schreiben",
|
"typeMessage": "Nachricht schreiben",
|
||||||
"userProfileButton": {
|
"userProfileButton": {
|
||||||
"label": "Chat",
|
"label": "Chat",
|
||||||
|
|||||||
@ -78,6 +78,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"chat": {
|
"chat": {
|
||||||
|
"addRoomHeadline": "Search User for new Chat",
|
||||||
"cancelSelectMessage": "Cancel",
|
"cancelSelectMessage": "Cancel",
|
||||||
"conversationStarted": "Conversation started on:",
|
"conversationStarted": "Conversation started on:",
|
||||||
"isOnline": "is online",
|
"isOnline": "is online",
|
||||||
@ -86,9 +87,12 @@
|
|||||||
"messageDeleted": "This message was deleted",
|
"messageDeleted": "This message was deleted",
|
||||||
"messagesEmpty": "No messages",
|
"messagesEmpty": "No messages",
|
||||||
"newMessages": "New Messages",
|
"newMessages": "New Messages",
|
||||||
|
"page": {
|
||||||
|
"headline": "Chat"
|
||||||
|
},
|
||||||
"roomEmpty": "No room selected",
|
"roomEmpty": "No room selected",
|
||||||
"roomsEmpty": "No rooms",
|
"roomsEmpty": "No rooms",
|
||||||
"search": "Search",
|
"search": "Filter chat rooms",
|
||||||
"typeMessage": "Type message",
|
"typeMessage": "Type message",
|
||||||
"userProfileButton": {
|
"userProfileButton": {
|
||||||
"label": "Chat",
|
"label": "Chat",
|
||||||
@ -472,7 +476,7 @@
|
|||||||
"addMemberToGroupSuccess": "“{name}” was added to the group with the role “{role}”!",
|
"addMemberToGroupSuccess": "“{name}” was added to the group with the role “{role}”!",
|
||||||
"addUser": "Add User",
|
"addUser": "Add User",
|
||||||
"addUserNoOptions": "No users found!",
|
"addUserNoOptions": "No users found!",
|
||||||
"addUserPlaceholder": " Username",
|
"addUserPlaceholder": "User name",
|
||||||
"allGroups": "All Groups",
|
"allGroups": "All Groups",
|
||||||
"button": {
|
"button": {
|
||||||
"tooltip": "Show groups"
|
"tooltip": "Show groups"
|
||||||
|
|||||||
@ -75,6 +75,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"chat": {
|
||||||
|
"search": "Filtrar salas de chat"
|
||||||
|
},
|
||||||
"code-of-conduct": {
|
"code-of-conduct": {
|
||||||
"subheader": "para la red social de {ORGANIZATION_NAME}"
|
"subheader": "para la red social de {ORGANIZATION_NAME}"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -75,6 +75,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"chat": {
|
||||||
|
"search": "Filtrer les salons de chat"
|
||||||
|
},
|
||||||
"code-of-conduct": {
|
"code-of-conduct": {
|
||||||
"subheader": "pour le réseau social de {ORGANIZATION_NAME}"
|
"subheader": "pour le réseau social de {ORGANIZATION_NAME}"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,11 +1,54 @@
|
|||||||
<template>
|
<template>
|
||||||
<chat />
|
<div>
|
||||||
|
<ds-heading tag="h1">{{ $t('chat.page.headline') }}</ds-heading>
|
||||||
|
<add-chat-room-by-user-search
|
||||||
|
v-if="showUserSearch"
|
||||||
|
@add-chat-room="addChatRoom"
|
||||||
|
@close-user-search="showUserSearch = false"
|
||||||
|
/>
|
||||||
|
<ds-space margin-bottom="small" />
|
||||||
|
<chat
|
||||||
|
:roomId="getShowChat.showChat ? getShowChat.roomID : null"
|
||||||
|
ref="chat"
|
||||||
|
@toggle-user-search="showUserSearch = !showUserSearch"
|
||||||
|
:show-room="showRoom"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { mapGetters, mapMutations } from 'vuex'
|
||||||
|
import AddChatRoomByUserSearch from '~/components/Chat/AddChatRoomByUserSearch'
|
||||||
import Chat from '../components/Chat/Chat.vue'
|
import Chat from '../components/Chat/Chat.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { Chat },
|
components: {
|
||||||
|
AddChatRoomByUserSearch,
|
||||||
|
Chat,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showUserSearch: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.showChat({ showChat: false, roomID: null })
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters({
|
||||||
|
getShowChat: 'chat/showChat',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapMutations({
|
||||||
|
showChat: 'chat/SET_OPEN_CHAT',
|
||||||
|
}),
|
||||||
|
addChatRoom(userID) {
|
||||||
|
this.$refs.chat.newRoom(userID)
|
||||||
|
},
|
||||||
|
showRoom(roomId) {
|
||||||
|
this.showChat({ showChat: true, roomID: roomId })
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -24,7 +24,7 @@ const options = {
|
|||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
message: 'error-pages.group-not-found',
|
message: 'error-pages.group-not-found',
|
||||||
path: 'group',
|
path: 'groups',
|
||||||
}
|
}
|
||||||
const persistentLinks = PersistentLinks(options)
|
const persistentLinks = PersistentLinks(options)
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ export default {
|
|||||||
})
|
})
|
||||||
this.$toast.success(this.$t('group.groupCreated'))
|
this.$toast.success(this.$t('group.groupCreated'))
|
||||||
this.$router.history.push({
|
this.$router.history.push({
|
||||||
name: 'group-id-slug',
|
name: 'groups-id-slug',
|
||||||
params: { id: responseId, slug: responseSlug },
|
params: { id: responseId, slug: responseSlug },
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -33,11 +33,11 @@ export default {
|
|||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
name: this.$t('group.general'),
|
name: this.$t('group.general'),
|
||||||
path: `/group/edit/${this.group.id}`,
|
path: `/groups/edit/${this.group.id}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: this.$t('group.members'),
|
name: this.$t('group.members'),
|
||||||
path: `/group/edit/${this.group.id}/members`,
|
path: `/groups/edit/${this.group.id}/members`,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@ -60,7 +60,7 @@ export default {
|
|||||||
})
|
})
|
||||||
this.$toast.success(this.$t('group.updatedGroup'))
|
this.$toast.success(this.$t('group.updatedGroup'))
|
||||||
this.$router.history.push({
|
this.$router.history.push({
|
||||||
name: 'group-id-slug',
|
name: 'groups-id-slug',
|
||||||
params: { id: responseId, slug: responseSlug },
|
params: { id: responseId, slug: responseSlug },
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import { mount } from '@vue/test-utils'
|
import { mount } from '@vue/test-utils'
|
||||||
import groups from './groups.vue'
|
import groups from './index.vue'
|
||||||
|
|
||||||
const localVue = global.localVue
|
const localVue = global.localVue
|
||||||
|
|
||||||
@ -7,7 +7,7 @@
|
|||||||
<ds-space>
|
<ds-space>
|
||||||
<!-- create group -->
|
<!-- create group -->
|
||||||
<ds-space centered>
|
<ds-space centered>
|
||||||
<nuxt-link :to="{ name: 'group-create' }">
|
<nuxt-link :to="{ name: 'groups-create' }">
|
||||||
<base-button
|
<base-button
|
||||||
class="group-add-button"
|
class="group-add-button"
|
||||||
icon="plus"
|
icon="plus"
|
||||||
@ -85,7 +85,7 @@
|
|||||||
content: $t('chat.userProfileButton.tooltip', { name: userName }),
|
content: $t('chat.userProfileButton.tooltip', { name: userName }),
|
||||||
placement: 'bottom-start',
|
placement: 'bottom-start',
|
||||||
}"
|
}"
|
||||||
@click="showChat({ showChat: true, roomID: user.id })"
|
@click="showOrChangeChat(user.id)"
|
||||||
>
|
>
|
||||||
{{ $t('chat.userProfileButton.label') }}
|
{{ $t('chat.userProfileButton.label') }}
|
||||||
</base-button>
|
</base-button>
|
||||||
@ -182,7 +182,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import uniqBy from 'lodash/uniqBy'
|
import uniqBy from 'lodash/uniqBy'
|
||||||
import { mapMutations } from 'vuex'
|
import { mapGetters, mapMutations } from 'vuex'
|
||||||
import postListActions from '~/mixins/postListActions'
|
import postListActions from '~/mixins/postListActions'
|
||||||
import PostTeaser from '~/components/PostTeaser/PostTeaser.vue'
|
import PostTeaser from '~/components/PostTeaser/PostTeaser.vue'
|
||||||
import HcFollowButton from '~/components/Button/FollowButton'
|
import HcFollowButton from '~/components/Button/FollowButton'
|
||||||
@ -254,6 +254,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapGetters({
|
||||||
|
getShowChat: 'chat/showChat',
|
||||||
|
}),
|
||||||
myProfile() {
|
myProfile() {
|
||||||
return this.$route.params.id === this.$store.getters['auth/user'].id
|
return this.$route.params.id === this.$store.getters['auth/user'].id
|
||||||
},
|
},
|
||||||
@ -403,6 +406,12 @@ export default {
|
|||||||
if (type === 'following') this.followingCount = count
|
if (type === 'following') this.followingCount = count
|
||||||
if (type === 'followedBy') this.followedByCount = count
|
if (type === 'followedBy') this.followedByCount = count
|
||||||
},
|
},
|
||||||
|
async showOrChangeChat(roomID) {
|
||||||
|
if (this.getShowChat.showChat) {
|
||||||
|
await this.showChat({ showChat: false, roomID: null })
|
||||||
|
}
|
||||||
|
await this.showChat({ showChat: true, roomID })
|
||||||
|
},
|
||||||
},
|
},
|
||||||
apollo: {
|
apollo: {
|
||||||
profilePagePosts: {
|
profilePagePosts: {
|
||||||
|
|||||||
@ -14,6 +14,9 @@ export const mutations = {
|
|||||||
UPDATE_ROOM_COUNT(state, count) {
|
UPDATE_ROOM_COUNT(state, count) {
|
||||||
state.unreadRoomCount = count
|
state.unreadRoomCount = count
|
||||||
},
|
},
|
||||||
|
UPDATE_ROOM_ID(state, roomid) {
|
||||||
|
state.roomId = roomid || null
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getters = {
|
export const getters = {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user