mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
Merge branch '5059-epic-groups' of github.com:Ocelot-Social-Community/Ocelot-Social into 5344-add-group-members-management
# Conflicts: # backend/src/db/graphql/groups.js # backend/src/schema/resolvers/groups.js # webapp/components/Group/GroupCard.vue # webapp/components/Group/GroupForm.vue # webapp/components/Group/GroupTeaser.vue # webapp/graphql/groups.js # webapp/locales/de.json # webapp/locales/en.json # webapp/pages/group/edit/_id.vue
This commit is contained in:
commit
2aa85d7b05
@ -1,3 +1,3 @@
|
|||||||
// this file is duplicated in `backend/src/constants/group.js` and `webapp/constants/group.js`
|
// this file is duplicated in `backend/src/constants/group.js` and `webapp/constants/group.js`
|
||||||
export const DESCRIPTION_WITHOUT_HTML_LENGTH_MIN = 100 // with removed HTML tags
|
export const DESCRIPTION_WITHOUT_HTML_LENGTH_MIN = 100 // with removed HTML tags
|
||||||
export const DESCRIPTION_EXCERPT_HTML_LENGTH = 120 // with removed HTML tags
|
export const DESCRIPTION_EXCERPT_HTML_LENGTH = 250 // with removed HTML tags
|
||||||
|
|||||||
@ -2,171 +2,202 @@ import gql from 'graphql-tag'
|
|||||||
|
|
||||||
// ------ mutations
|
// ------ mutations
|
||||||
|
|
||||||
export const createGroupMutation = gql`
|
export const createGroupMutation = () => {
|
||||||
mutation (
|
return gql`
|
||||||
$id: ID
|
mutation (
|
||||||
$name: String!
|
$id: ID
|
||||||
$slug: String
|
$name: String!
|
||||||
$about: String
|
$slug: String
|
||||||
$description: String!
|
$about: String
|
||||||
$groupType: GroupType!
|
$description: String!
|
||||||
$actionRadius: GroupActionRadius!
|
$groupType: GroupType!
|
||||||
$categoryIds: [ID]
|
$actionRadius: GroupActionRadius!
|
||||||
$locationName: String
|
$categoryIds: [ID]
|
||||||
) {
|
$locationName: String # empty string '' sets it to null
|
||||||
CreateGroup(
|
|
||||||
id: $id
|
|
||||||
name: $name
|
|
||||||
slug: $slug
|
|
||||||
about: $about
|
|
||||||
description: $description
|
|
||||||
groupType: $groupType
|
|
||||||
actionRadius: $actionRadius
|
|
||||||
categoryIds: $categoryIds
|
|
||||||
locationName: $locationName
|
|
||||||
) {
|
) {
|
||||||
id
|
CreateGroup(
|
||||||
name
|
id: $id
|
||||||
slug
|
name: $name
|
||||||
createdAt
|
slug: $slug
|
||||||
updatedAt
|
about: $about
|
||||||
disabled
|
description: $description
|
||||||
deleted
|
groupType: $groupType
|
||||||
about
|
actionRadius: $actionRadius
|
||||||
description
|
categoryIds: $categoryIds
|
||||||
groupType
|
locationName: $locationName
|
||||||
actionRadius
|
) {
|
||||||
categories {
|
|
||||||
id
|
id
|
||||||
slug
|
|
||||||
name
|
name
|
||||||
icon
|
slug
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
disabled
|
||||||
|
deleted
|
||||||
|
about
|
||||||
|
description
|
||||||
|
descriptionExcerpt
|
||||||
|
groupType
|
||||||
|
actionRadius
|
||||||
|
categories {
|
||||||
|
id
|
||||||
|
slug
|
||||||
|
name
|
||||||
|
icon
|
||||||
|
}
|
||||||
|
locationName
|
||||||
|
location {
|
||||||
|
name
|
||||||
|
nameDE
|
||||||
|
nameEN
|
||||||
|
}
|
||||||
|
myRole
|
||||||
}
|
}
|
||||||
# locationName # test this as result
|
|
||||||
myRole
|
|
||||||
}
|
}
|
||||||
}
|
`
|
||||||
`
|
}
|
||||||
|
|
||||||
export const updateGroupMutation = gql`
|
export const updateGroupMutation = () => {
|
||||||
mutation (
|
return gql`
|
||||||
$id: ID!
|
mutation (
|
||||||
$name: String
|
$id: ID!
|
||||||
$slug: String
|
$name: String
|
||||||
$about: String
|
$slug: String
|
||||||
$description: String
|
$about: String
|
||||||
$actionRadius: GroupActionRadius
|
$description: String
|
||||||
$categoryIds: [ID]
|
$actionRadius: GroupActionRadius
|
||||||
$avatar: ImageInput
|
$categoryIds: [ID]
|
||||||
$locationName: String
|
$avatar: ImageInput
|
||||||
) {
|
$locationName: String # empty string '' sets it to null
|
||||||
UpdateGroup(
|
|
||||||
id: $id
|
|
||||||
name: $name
|
|
||||||
slug: $slug
|
|
||||||
about: $about
|
|
||||||
description: $description
|
|
||||||
actionRadius: $actionRadius
|
|
||||||
categoryIds: $categoryIds
|
|
||||||
avatar: $avatar
|
|
||||||
locationName: $locationName
|
|
||||||
) {
|
) {
|
||||||
id
|
UpdateGroup(
|
||||||
name
|
id: $id
|
||||||
slug
|
name: $name
|
||||||
createdAt
|
slug: $slug
|
||||||
updatedAt
|
about: $about
|
||||||
disabled
|
description: $description
|
||||||
deleted
|
actionRadius: $actionRadius
|
||||||
about
|
categoryIds: $categoryIds
|
||||||
description
|
avatar: $avatar
|
||||||
groupType
|
locationName: $locationName
|
||||||
actionRadius
|
) {
|
||||||
categories {
|
|
||||||
id
|
id
|
||||||
slug
|
|
||||||
name
|
name
|
||||||
icon
|
slug
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
disabled
|
||||||
|
deleted
|
||||||
|
about
|
||||||
|
description
|
||||||
|
descriptionExcerpt
|
||||||
|
groupType
|
||||||
|
actionRadius
|
||||||
|
categories {
|
||||||
|
id
|
||||||
|
slug
|
||||||
|
name
|
||||||
|
icon
|
||||||
|
}
|
||||||
|
# avatar # test this as result
|
||||||
|
locationName
|
||||||
|
location {
|
||||||
|
name
|
||||||
|
nameDE
|
||||||
|
nameEN
|
||||||
|
}
|
||||||
|
myRole
|
||||||
}
|
}
|
||||||
# avatar # test this as result
|
|
||||||
# locationName # test this as result
|
|
||||||
myRole
|
|
||||||
}
|
}
|
||||||
}
|
`
|
||||||
`
|
}
|
||||||
|
|
||||||
export const joinGroupMutation = gql`
|
export const joinGroupMutation = () => {
|
||||||
mutation ($groupId: ID!, $userId: ID!) {
|
return gql`
|
||||||
JoinGroup(groupId: $groupId, userId: $userId) {
|
mutation ($groupId: ID!, $userId: ID!) {
|
||||||
id
|
JoinGroup(groupId: $groupId, userId: $userId) {
|
||||||
name
|
id
|
||||||
slug
|
name
|
||||||
myRoleInGroup
|
slug
|
||||||
|
myRoleInGroup
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
`
|
||||||
`
|
}
|
||||||
|
|
||||||
export const leaveGroupMutation = gql`
|
export const leaveGroupMutation = () => {
|
||||||
mutation ($groupId: ID!, $userId: ID!) {
|
return gql`
|
||||||
LeaveGroup(groupId: $groupId, userId: $userId) {
|
mutation ($groupId: ID!, $userId: ID!) {
|
||||||
id
|
LeaveGroup(groupId: $groupId, userId: $userId) {
|
||||||
name
|
id
|
||||||
slug
|
name
|
||||||
myRoleInGroup
|
slug
|
||||||
|
myRoleInGroup
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
`
|
||||||
`
|
}
|
||||||
|
|
||||||
export const changeGroupMemberRoleMutation = gql`
|
export const changeGroupMemberRoleMutation = () => {
|
||||||
mutation ($groupId: ID!, $userId: ID!, $roleInGroup: GroupMemberRole!) {
|
return gql`
|
||||||
ChangeGroupMemberRole(groupId: $groupId, userId: $userId, roleInGroup: $roleInGroup) {
|
mutation ($groupId: ID!, $userId: ID!, $roleInGroup: GroupMemberRole!) {
|
||||||
id
|
ChangeGroupMemberRole(groupId: $groupId, userId: $userId, roleInGroup: $roleInGroup) {
|
||||||
name
|
id
|
||||||
slug
|
name
|
||||||
myRoleInGroup
|
slug
|
||||||
|
myRoleInGroup
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
`
|
||||||
`
|
}
|
||||||
|
|
||||||
// ------ queries
|
// ------ queries
|
||||||
|
|
||||||
export const groupQuery = gql`
|
export const groupQuery = () => {
|
||||||
query ($isMember: Boolean, $id: ID, $slug: String) {
|
return gql`
|
||||||
Group(isMember: $isMember, id: $id, slug: $slug) {
|
query ($isMember: Boolean, $id: ID, $slug: String) {
|
||||||
id
|
Group(isMember: $isMember, id: $id, slug: $slug) {
|
||||||
name
|
|
||||||
slug
|
|
||||||
createdAt
|
|
||||||
updatedAt
|
|
||||||
disabled
|
|
||||||
deleted
|
|
||||||
about
|
|
||||||
description
|
|
||||||
descriptionExcerpt
|
|
||||||
groupType
|
|
||||||
actionRadius
|
|
||||||
categories {
|
|
||||||
id
|
id
|
||||||
slug
|
|
||||||
name
|
name
|
||||||
icon
|
slug
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
disabled
|
||||||
|
deleted
|
||||||
|
about
|
||||||
|
description
|
||||||
|
descriptionExcerpt
|
||||||
|
groupType
|
||||||
|
actionRadius
|
||||||
|
categories {
|
||||||
|
id
|
||||||
|
slug
|
||||||
|
name
|
||||||
|
icon
|
||||||
|
}
|
||||||
|
avatar {
|
||||||
|
url
|
||||||
|
}
|
||||||
|
locationName
|
||||||
|
location {
|
||||||
|
name
|
||||||
|
nameDE
|
||||||
|
nameEN
|
||||||
|
}
|
||||||
|
myRole
|
||||||
}
|
}
|
||||||
avatar {
|
|
||||||
url
|
|
||||||
}
|
|
||||||
# locationName # test this as result
|
|
||||||
myRole
|
|
||||||
}
|
}
|
||||||
}
|
`
|
||||||
`
|
}
|
||||||
|
|
||||||
export const groupMembersQuery = gql`
|
export const groupMembersQuery = () => {
|
||||||
query ($id: ID!) {
|
return gql`
|
||||||
GroupMembers(id: $id) {
|
query ($id: ID!) {
|
||||||
id
|
GroupMembers(id: $id) {
|
||||||
name
|
id
|
||||||
slug
|
name
|
||||||
myRoleInGroup
|
slug
|
||||||
|
myRoleInGroup
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
`
|
||||||
`
|
}
|
||||||
|
|||||||
@ -305,7 +305,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
authenticatedUser = await peterLustig.toJson()
|
authenticatedUser = await peterLustig.toJson()
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
mutate({
|
mutate({
|
||||||
mutation: createGroupMutation,
|
mutation: createGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: 'g0',
|
id: 'g0',
|
||||||
name: 'Investigative Journalism',
|
name: 'Investigative Journalism',
|
||||||
@ -313,27 +313,28 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
description: `<p class=""><em>English:</em></p><p class="">This group is hidden.</p><h3>What is our group for?</h3><p>This group was created to allow investigative journalists to share and collaborate.</p><h3>How does it work?</h3><p>Here you can internally share posts and comments about them.</p><p><br></p><p><em>Deutsch:</em></p><p class="">Diese Gruppe ist verborgen.</p><h3>Wofür ist unsere Gruppe?</h3><p class="">Diese Gruppe wurde geschaffen, um investigativen Journalisten den Austausch und die Zusammenarbeit zu ermöglichen.</p><h3>Wie funktioniert das?</h3><p class="">Hier könnt ihr euch intern über Beiträge und Kommentare zu ihnen austauschen.</p>`,
|
description: `<p class=""><em>English:</em></p><p class="">This group is hidden.</p><h3>What is our group for?</h3><p>This group was created to allow investigative journalists to share and collaborate.</p><h3>How does it work?</h3><p>Here you can internally share posts and comments about them.</p><p><br></p><p><em>Deutsch:</em></p><p class="">Diese Gruppe ist verborgen.</p><h3>Wofür ist unsere Gruppe?</h3><p class="">Diese Gruppe wurde geschaffen, um investigativen Journalisten den Austausch und die Zusammenarbeit zu ermöglichen.</p><h3>Wie funktioniert das?</h3><p class="">Hier könnt ihr euch intern über Beiträge und Kommentare zu ihnen austauschen.</p>`,
|
||||||
groupType: 'hidden',
|
groupType: 'hidden',
|
||||||
actionRadius: 'global',
|
actionRadius: 'global',
|
||||||
categoryIds: ['cat6', 'cat9', 'cat14'],
|
categoryIds: ['cat6', 'cat12', 'cat16'],
|
||||||
|
locationName: 'Hamburg, Germany',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
mutate({
|
mutate({
|
||||||
mutation: joinGroupMutation,
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g0',
|
groupId: 'g0',
|
||||||
userId: 'u2',
|
userId: 'u2',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
mutation: joinGroupMutation,
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g0',
|
groupId: 'g0',
|
||||||
userId: 'u4',
|
userId: 'u4',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
mutation: joinGroupMutation,
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g0',
|
groupId: 'g0',
|
||||||
userId: 'u6',
|
userId: 'u6',
|
||||||
@ -342,7 +343,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
])
|
])
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
mutate({
|
mutate({
|
||||||
mutation: changeGroupMemberRoleMutation,
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g0',
|
groupId: 'g0',
|
||||||
userId: 'u2',
|
userId: 'u2',
|
||||||
@ -350,7 +351,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
mutation: changeGroupMemberRoleMutation,
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g0',
|
groupId: 'g0',
|
||||||
userId: 'u4',
|
userId: 'u4',
|
||||||
@ -362,7 +363,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
authenticatedUser = await jennyRostock.toJson()
|
authenticatedUser = await jennyRostock.toJson()
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
mutate({
|
mutate({
|
||||||
mutation: createGroupMutation,
|
mutation: createGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: 'g1',
|
id: 'g1',
|
||||||
name: 'School For Citizens',
|
name: 'School For Citizens',
|
||||||
@ -370,41 +371,42 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
description: `<p class=""><em>English</em></p><h3>Our goal</h3><p>Only those who enjoy learning and do not lose their curiosity can obtain a good education for life and continue to learn with joy throughout their lives.</p><h3>Curiosity</h3><p>For this we need a school that takes up the curiosity of the children, the people, and satisfies it through a lot of experience.</p><p><br></p><p><em>Deutsch</em></p><h3>Unser Ziel</h3><p class="">Nur wer Spaß am Lernen hat und seine Neugier nicht verliert, kann gute Bildung für's Leben erlangen und sein ganzes Leben mit Freude weiter lernen.</p><h3>Neugier</h3><p class="">Dazu benötigen wir eine Schule, die die Neugier der Kinder, der Menschen, aufnimmt und durch viel Erfahrung befriedigt.</p>`,
|
description: `<p class=""><em>English</em></p><h3>Our goal</h3><p>Only those who enjoy learning and do not lose their curiosity can obtain a good education for life and continue to learn with joy throughout their lives.</p><h3>Curiosity</h3><p>For this we need a school that takes up the curiosity of the children, the people, and satisfies it through a lot of experience.</p><p><br></p><p><em>Deutsch</em></p><h3>Unser Ziel</h3><p class="">Nur wer Spaß am Lernen hat und seine Neugier nicht verliert, kann gute Bildung für's Leben erlangen und sein ganzes Leben mit Freude weiter lernen.</p><h3>Neugier</h3><p class="">Dazu benötigen wir eine Schule, die die Neugier der Kinder, der Menschen, aufnimmt und durch viel Erfahrung befriedigt.</p>`,
|
||||||
groupType: 'closed',
|
groupType: 'closed',
|
||||||
actionRadius: 'national',
|
actionRadius: 'national',
|
||||||
categoryIds: ['cat7', 'cat9', 'cat16'],
|
categoryIds: ['cat8', 'cat14'],
|
||||||
|
locationName: 'France',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
mutate({
|
mutate({
|
||||||
mutation: joinGroupMutation,
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g1',
|
groupId: 'g1',
|
||||||
userId: 'u1',
|
userId: 'u1',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
mutation: joinGroupMutation,
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g1',
|
groupId: 'g1',
|
||||||
userId: 'u2',
|
userId: 'u2',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
mutation: joinGroupMutation,
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g1',
|
groupId: 'g1',
|
||||||
userId: 'u5',
|
userId: 'u5',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
mutation: joinGroupMutation,
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g1',
|
groupId: 'g1',
|
||||||
userId: 'u6',
|
userId: 'u6',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
mutation: joinGroupMutation,
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g1',
|
groupId: 'g1',
|
||||||
userId: 'u7',
|
userId: 'u7',
|
||||||
@ -413,7 +415,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
])
|
])
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
mutate({
|
mutate({
|
||||||
mutation: changeGroupMemberRoleMutation,
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g1',
|
groupId: 'g1',
|
||||||
userId: 'u1',
|
userId: 'u1',
|
||||||
@ -421,7 +423,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
mutation: changeGroupMemberRoleMutation,
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g1',
|
groupId: 'g1',
|
||||||
userId: 'u5',
|
userId: 'u5',
|
||||||
@ -429,7 +431,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
mutation: changeGroupMemberRoleMutation,
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g1',
|
groupId: 'g1',
|
||||||
userId: 'u6',
|
userId: 'u6',
|
||||||
@ -441,7 +443,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
authenticatedUser = await bobDerBaumeister.toJson()
|
authenticatedUser = await bobDerBaumeister.toJson()
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
mutate({
|
mutate({
|
||||||
mutation: createGroupMutation,
|
mutation: createGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: 'g2',
|
id: 'g2',
|
||||||
name: 'Yoga Practice',
|
name: 'Yoga Practice',
|
||||||
@ -449,41 +451,41 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
description: `<h3>What Is yoga?</h3><p>Yoga is not just about practicing asanas. It's about how we do it.</p><p class="">And practicing asanas doesn't have to be yoga, it can be more athletic than yogic.</p><h3>What makes practicing asanas yogic?</h3><p class="">The important thing is:</p><ul><li><p>Use the exercises (consciously) for your personal development.</p></li></ul>`,
|
description: `<h3>What Is yoga?</h3><p>Yoga is not just about practicing asanas. It's about how we do it.</p><p class="">And practicing asanas doesn't have to be yoga, it can be more athletic than yogic.</p><h3>What makes practicing asanas yogic?</h3><p class="">The important thing is:</p><ul><li><p>Use the exercises (consciously) for your personal development.</p></li></ul>`,
|
||||||
groupType: 'public',
|
groupType: 'public',
|
||||||
actionRadius: 'interplanetary',
|
actionRadius: 'interplanetary',
|
||||||
categoryIds: ['cat3', 'cat13', 'cat16'],
|
categoryIds: ['cat4', 'cat5', 'cat17'],
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
mutate({
|
mutate({
|
||||||
mutation: joinGroupMutation,
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g2',
|
groupId: 'g2',
|
||||||
userId: 'u3',
|
userId: 'u3',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
mutation: joinGroupMutation,
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g2',
|
groupId: 'g2',
|
||||||
userId: 'u4',
|
userId: 'u4',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
mutation: joinGroupMutation,
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g2',
|
groupId: 'g2',
|
||||||
userId: 'u5',
|
userId: 'u5',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
mutation: joinGroupMutation,
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g2',
|
groupId: 'g2',
|
||||||
userId: 'u6',
|
userId: 'u6',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
mutation: joinGroupMutation,
|
mutation: joinGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g2',
|
groupId: 'g2',
|
||||||
userId: 'u7',
|
userId: 'u7',
|
||||||
@ -492,31 +494,31 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
|
|||||||
])
|
])
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
mutate({
|
mutate({
|
||||||
mutation: changeGroupMemberRoleMutation,
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g2',
|
groupId: 'g2',
|
||||||
userId: 'u3',
|
userId: 'u3',
|
||||||
|
roleInGroup: 'usual',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
mutate({
|
||||||
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
|
variables: {
|
||||||
|
groupId: 'g2',
|
||||||
|
userId: 'u4',
|
||||||
roleInGroup: 'pending',
|
roleInGroup: 'pending',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
mutation: changeGroupMemberRoleMutation,
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables: {
|
|
||||||
groupId: 'g2',
|
|
||||||
userId: 'u4',
|
|
||||||
roleInGroup: 'usual',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
mutate({
|
|
||||||
mutation: changeGroupMemberRoleMutation,
|
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g2',
|
groupId: 'g2',
|
||||||
userId: 'u5',
|
userId: 'u5',
|
||||||
roleInGroup: 'usual',
|
roleInGroup: 'admin',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
mutate({
|
mutate({
|
||||||
mutation: changeGroupMemberRoleMutation,
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
groupId: 'g2',
|
groupId: 'g2',
|
||||||
userId: 'u6',
|
userId: 'u6',
|
||||||
|
|||||||
@ -82,7 +82,7 @@ const isAllowedToChangeGroupSettings = rule({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const isAllowedSeeingMembersOfGroup = rule({
|
const isAllowedSeeingGroupMembers = rule({
|
||||||
cache: 'no_cache',
|
cache: 'no_cache',
|
||||||
})(async (_parent, args, { user, driver }) => {
|
})(async (_parent, args, { user, driver }) => {
|
||||||
if (!(user && user.id)) return false
|
if (!(user && user.id)) return false
|
||||||
@ -284,7 +284,7 @@ export default shield(
|
|||||||
statistics: allow,
|
statistics: allow,
|
||||||
currentUser: allow,
|
currentUser: allow,
|
||||||
Group: isAuthenticated,
|
Group: isAuthenticated,
|
||||||
GroupMembers: isAllowedSeeingMembersOfGroup,
|
GroupMembers: isAllowedSeeingGroupMembers,
|
||||||
Post: allow,
|
Post: allow,
|
||||||
profilePagePosts: allow,
|
profilePagePosts: allow,
|
||||||
Comment: allow,
|
Comment: allow,
|
||||||
|
|||||||
@ -51,6 +51,7 @@ beforeEach(async () => {
|
|||||||
await Factory.build('category', {
|
await Factory.build('category', {
|
||||||
id: 'cat9',
|
id: 'cat9',
|
||||||
name: 'Democracy & Politics',
|
name: 'Democracy & Politics',
|
||||||
|
slug: 'democracy-politics',
|
||||||
icon: 'university',
|
icon: 'university',
|
||||||
})
|
})
|
||||||
authenticatedUser = await admin.toJson()
|
authenticatedUser = await admin.toJson()
|
||||||
@ -79,7 +80,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
it('generates a slug based on name', async () => {
|
it('generates a slug based on name', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: createGroupMutation,
|
mutation: createGroupMutation(),
|
||||||
variables,
|
variables,
|
||||||
}),
|
}),
|
||||||
).resolves.toMatchObject({
|
).resolves.toMatchObject({
|
||||||
@ -93,13 +94,14 @@ describe('slugifyMiddleware', () => {
|
|||||||
actionRadius: 'national',
|
actionRadius: 'national',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
errors: undefined,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('generates a slug based on given slug', async () => {
|
it('generates a slug based on given slug', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: createGroupMutation,
|
mutation: createGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
...variables,
|
...variables,
|
||||||
slug: 'the-group',
|
slug: 'the-group',
|
||||||
@ -111,6 +113,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
slug: 'the-group',
|
slug: 'the-group',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
errors: undefined,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -118,7 +121,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
describe('if slug exists', () => {
|
describe('if slug exists', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: createGroupMutation,
|
mutation: createGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
...variables,
|
...variables,
|
||||||
name: 'Pre-Existing Group',
|
name: 'Pre-Existing Group',
|
||||||
@ -131,7 +134,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
it('chooses another slug', async () => {
|
it('chooses another slug', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: createGroupMutation,
|
mutation: createGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
...variables,
|
...variables,
|
||||||
name: 'Pre-Existing Group',
|
name: 'Pre-Existing Group',
|
||||||
@ -144,6 +147,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
slug: 'pre-existing-group-1',
|
slug: 'pre-existing-group-1',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
errors: undefined,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -152,7 +156,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
try {
|
try {
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: createGroupMutation,
|
mutation: createGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
...variables,
|
...variables,
|
||||||
name: 'Pre-Existing Group',
|
name: 'Pre-Existing Group',
|
||||||
@ -194,7 +198,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
createGroupResult = await mutate({
|
createGroupResult = await mutate({
|
||||||
mutation: createGroupMutation,
|
mutation: createGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
name: 'The Best Group',
|
name: 'The Best Group',
|
||||||
slug: 'the-best-group',
|
slug: 'the-best-group',
|
||||||
@ -213,7 +217,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
it('has the new slug', async () => {
|
it('has the new slug', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: updateGroupMutation,
|
mutation: updateGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: createGroupResult.data.CreateGroup.id,
|
id: createGroupResult.data.CreateGroup.id,
|
||||||
name: 'My Best Group',
|
name: 'My Best Group',
|
||||||
@ -231,6 +235,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
myRole: 'owner',
|
myRole: 'owner',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
errors: undefined,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -239,7 +244,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
it('has the new slug', async () => {
|
it('has the new slug', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: updateGroupMutation,
|
mutation: updateGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: createGroupResult.data.CreateGroup.id,
|
id: createGroupResult.data.CreateGroup.id,
|
||||||
slug: 'my-best-group',
|
slug: 'my-best-group',
|
||||||
@ -257,6 +262,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
myRole: 'owner',
|
myRole: 'owner',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
errors: undefined,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -265,7 +271,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
describe('if new slug exists in another group', () => {
|
describe('if new slug exists in another group', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: createGroupMutation,
|
mutation: createGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
name: 'Pre-Existing Group',
|
name: 'Pre-Existing Group',
|
||||||
slug: 'pre-existing-group',
|
slug: 'pre-existing-group',
|
||||||
@ -282,7 +288,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
it('has unique slug "*-1"', async () => {
|
it('has unique slug "*-1"', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: updateGroupMutation,
|
mutation: updateGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: createGroupResult.data.CreateGroup.id,
|
id: createGroupResult.data.CreateGroup.id,
|
||||||
name: 'Pre-Existing Group',
|
name: 'Pre-Existing Group',
|
||||||
@ -300,6 +306,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
myRole: 'owner',
|
myRole: 'owner',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
errors: undefined,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -309,7 +316,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
try {
|
try {
|
||||||
await expect(
|
await expect(
|
||||||
mutate({
|
mutate({
|
||||||
mutation: updateGroupMutation,
|
mutation: updateGroupMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
id: createGroupResult.data.CreateGroup.id,
|
id: createGroupResult.data.CreateGroup.id,
|
||||||
slug: 'pre-existing-group',
|
slug: 'pre-existing-group',
|
||||||
@ -368,6 +375,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
slug: 'i-am-a-brand-new-post',
|
slug: 'i-am-a-brand-new-post',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
errors: undefined,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -386,6 +394,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
slug: 'the-post',
|
slug: 'the-post',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
errors: undefined,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -422,6 +431,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
slug: 'pre-existing-post-1',
|
slug: 'pre-existing-post-1',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
errors: undefined,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -504,6 +514,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
slug: 'i-am-a-user',
|
slug: 'i-am-a-user',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
errors: undefined,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -522,6 +533,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
slug: 'the-user',
|
slug: 'the-user',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
errors: undefined,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -546,6 +558,7 @@ describe('slugifyMiddleware', () => {
|
|||||||
slug: 'i-am-a-user-1',
|
slug: 'i-am-a-user-1',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
errors: undefined,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,7 @@ export default makeAugmentedSchema({
|
|||||||
'FILED',
|
'FILED',
|
||||||
'REVIEWED',
|
'REVIEWED',
|
||||||
'Report',
|
'Report',
|
||||||
|
'Group',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
mutation: false,
|
mutation: false,
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import Resolver, {
|
|||||||
convertObjectToCypherMapLiteral,
|
convertObjectToCypherMapLiteral,
|
||||||
} from './helpers/Resolver'
|
} from './helpers/Resolver'
|
||||||
import { mergeImage } from './images/images'
|
import { mergeImage } from './images/images'
|
||||||
import createOrUpdateLocations from './users/location'
|
import { createOrUpdateLocations } from './users/location'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
Query: {
|
Query: {
|
||||||
@ -86,6 +86,7 @@ export default {
|
|||||||
CreateGroup: async (_parent, params, context, _resolveInfo) => {
|
CreateGroup: async (_parent, params, context, _resolveInfo) => {
|
||||||
const { categoryIds } = params
|
const { categoryIds } = params
|
||||||
delete params.categoryIds
|
delete params.categoryIds
|
||||||
|
params.locationName = params.locationName === '' ? null : params.locationName
|
||||||
if (CONFIG.CATEGORIES_ACTIVE && (!categoryIds || categoryIds.length < CATEGORIES_MIN)) {
|
if (CONFIG.CATEGORIES_ACTIVE && (!categoryIds || categoryIds.length < CATEGORIES_MIN)) {
|
||||||
throw new UserInputError('Too view categories!')
|
throw new UserInputError('Too view categories!')
|
||||||
}
|
}
|
||||||
@ -137,7 +138,8 @@ export default {
|
|||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const group = await writeTxResultPromise
|
const group = await writeTxResultPromise
|
||||||
await createOrUpdateLocations(params.id, params.locationName, session)
|
// TODO: put in a middleware, see "UpdateGroup", "UpdateUser"
|
||||||
|
await createOrUpdateLocations('Group', params.id, params.locationName, session)
|
||||||
return group
|
return group
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.code === 'Neo.ClientError.Schema.ConstraintValidationFailed')
|
if (error.code === 'Neo.ClientError.Schema.ConstraintValidationFailed')
|
||||||
@ -149,9 +151,11 @@ export default {
|
|||||||
},
|
},
|
||||||
UpdateGroup: async (_parent, params, context, _resolveInfo) => {
|
UpdateGroup: async (_parent, params, context, _resolveInfo) => {
|
||||||
const { categoryIds } = params
|
const { categoryIds } = params
|
||||||
const { id: groupId, avatar: avatarInput } = params
|
|
||||||
delete params.categoryIds
|
delete params.categoryIds
|
||||||
|
const { id: groupId, avatar: avatarInput } = params
|
||||||
delete params.avatar
|
delete params.avatar
|
||||||
|
params.locationName = params.locationName === '' ? null : params.locationName
|
||||||
|
|
||||||
if (CONFIG.CATEGORIES_ACTIVE && categoryIds) {
|
if (CONFIG.CATEGORIES_ACTIVE && categoryIds) {
|
||||||
if (categoryIds.length < CATEGORIES_MIN) {
|
if (categoryIds.length < CATEGORIES_MIN) {
|
||||||
throw new UserInputError('Too view categories!')
|
throw new UserInputError('Too view categories!')
|
||||||
@ -210,7 +214,8 @@ export default {
|
|||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const group = await writeTxResultPromise
|
const group = await writeTxResultPromise
|
||||||
await createOrUpdateLocations(params.id, params.locationName, session)
|
// TODO: put in a middleware, see "CreateGroup", "UpdateUser"
|
||||||
|
await createOrUpdateLocations('Group', params.id, params.locationName, session)
|
||||||
return group
|
return group
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.code === 'Neo.ClientError.Schema.ConstraintValidationFailed')
|
if (error.code === 'Neo.ClientError.Schema.ConstraintValidationFailed')
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -4,7 +4,7 @@ import { UserInputError, ForbiddenError } from 'apollo-server'
|
|||||||
import { mergeImage, deleteImage } from './images/images'
|
import { mergeImage, deleteImage } from './images/images'
|
||||||
import Resolver from './helpers/Resolver'
|
import Resolver from './helpers/Resolver'
|
||||||
import log from './helpers/databaseLogger'
|
import log from './helpers/databaseLogger'
|
||||||
import createOrUpdateLocations from './users/location'
|
import { createOrUpdateLocations } from './users/location'
|
||||||
|
|
||||||
const neode = getNeode()
|
const neode = getNeode()
|
||||||
|
|
||||||
@ -139,9 +139,10 @@ export default {
|
|||||||
return blockedUser.toJson()
|
return blockedUser.toJson()
|
||||||
},
|
},
|
||||||
UpdateUser: async (_parent, params, context, _resolveInfo) => {
|
UpdateUser: async (_parent, params, context, _resolveInfo) => {
|
||||||
const { termsAndConditionsAgreedVersion } = params
|
|
||||||
const { avatar: avatarInput } = params
|
const { avatar: avatarInput } = params
|
||||||
delete params.avatar
|
delete params.avatar
|
||||||
|
params.locationName = params.locationName === '' ? null : params.locationName
|
||||||
|
const { termsAndConditionsAgreedVersion } = params
|
||||||
if (termsAndConditionsAgreedVersion) {
|
if (termsAndConditionsAgreedVersion) {
|
||||||
const regEx = new RegExp(/^[0-9]+\.[0-9]+\.[0-9]+$/g)
|
const regEx = new RegExp(/^[0-9]+\.[0-9]+\.[0-9]+$/g)
|
||||||
if (!regEx.test(termsAndConditionsAgreedVersion)) {
|
if (!regEx.test(termsAndConditionsAgreedVersion)) {
|
||||||
@ -169,7 +170,8 @@ export default {
|
|||||||
})
|
})
|
||||||
try {
|
try {
|
||||||
const user = await writeTxResultPromise
|
const user = await writeTxResultPromise
|
||||||
await createOrUpdateLocations(params.id, params.locationName, session)
|
// TODO: put in a middleware, see "CreateGroup", "UpdateGroup"
|
||||||
|
await createOrUpdateLocations('User', params.id, params.locationName, session)
|
||||||
return user
|
return user
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw new UserInputError(error.message)
|
throw new UserInputError(error.message)
|
||||||
|
|||||||
@ -161,7 +161,7 @@ describe('UpdateUser', () => {
|
|||||||
$id: ID!
|
$id: ID!
|
||||||
$name: String
|
$name: String
|
||||||
$termsAndConditionsAgreedVersion: String
|
$termsAndConditionsAgreedVersion: String
|
||||||
$locationName: String
|
$locationName: String # empty string '' sets it to null
|
||||||
) {
|
) {
|
||||||
UpdateUser(
|
UpdateUser(
|
||||||
id: $id
|
id: $id
|
||||||
@ -174,6 +174,11 @@ describe('UpdateUser', () => {
|
|||||||
termsAndConditionsAgreedVersion
|
termsAndConditionsAgreedVersion
|
||||||
termsAndConditionsAgreedAt
|
termsAndConditionsAgreedAt
|
||||||
locationName
|
locationName
|
||||||
|
location {
|
||||||
|
name
|
||||||
|
nameDE
|
||||||
|
nameEN
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
@ -289,11 +294,39 @@ describe('UpdateUser', () => {
|
|||||||
expect(errors[0]).toHaveProperty('message', 'Invalid version format!')
|
expect(errors[0]).toHaveProperty('message', 'Invalid version format!')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('supports updating location', async () => {
|
describe('supports updating location', () => {
|
||||||
variables = { ...variables, locationName: 'Hamburg, New Jersey, United States' }
|
describe('change location to "Hamburg, New Jersey, United States"', () => {
|
||||||
await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject({
|
it('has updated location to "Hamburg, New Jersey, United States"', async () => {
|
||||||
data: { UpdateUser: { locationName: 'Hamburg, New Jersey, United States' } },
|
variables = { ...variables, locationName: 'Hamburg, New Jersey, United States' }
|
||||||
errors: undefined,
|
await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject({
|
||||||
|
data: {
|
||||||
|
UpdateUser: {
|
||||||
|
locationName: 'Hamburg, New Jersey, United States',
|
||||||
|
location: expect.objectContaining({
|
||||||
|
name: 'Hamburg',
|
||||||
|
nameDE: 'Hamburg',
|
||||||
|
nameEN: 'Hamburg',
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
errors: undefined,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('change location to unset location', () => {
|
||||||
|
it('has updated location to unset location', async () => {
|
||||||
|
variables = { ...variables, locationName: '' }
|
||||||
|
await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject({
|
||||||
|
data: {
|
||||||
|
UpdateUser: {
|
||||||
|
locationName: null,
|
||||||
|
location: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
errors: undefined,
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import request from 'request'
|
import request from 'request'
|
||||||
import { UserInputError } from 'apollo-server'
|
import { UserInputError } from 'apollo-server'
|
||||||
import isEmpty from 'lodash/isEmpty'
|
|
||||||
import Debug from 'debug'
|
import Debug from 'debug'
|
||||||
import asyncForEach from '../../../helpers/asyncForEach'
|
import asyncForEach from '../../../helpers/asyncForEach'
|
||||||
import CONFIG from '../../../config'
|
import CONFIG from '../../../config'
|
||||||
@ -62,77 +61,86 @@ const createLocation = async (session, mapboxData) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const createOrUpdateLocations = async (userId, locationName, session) => {
|
export const createOrUpdateLocations = async (nodeLabel, nodeId, locationName, session) => {
|
||||||
if (isEmpty(locationName)) {
|
if (locationName === undefined) return
|
||||||
return
|
|
||||||
}
|
|
||||||
const res = await fetch(
|
|
||||||
`https://api.mapbox.com/geocoding/v5/mapbox.places/${encodeURIComponent(
|
|
||||||
locationName,
|
|
||||||
)}.json?access_token=${CONFIG.MAPBOX_TOKEN}&types=region,place,country&language=${locales.join(
|
|
||||||
',',
|
|
||||||
)}`,
|
|
||||||
)
|
|
||||||
|
|
||||||
debug(res)
|
let locationId
|
||||||
|
|
||||||
if (!res || !res.features || !res.features[0]) {
|
if (locationName !== null) {
|
||||||
throw new UserInputError('locationName is invalid')
|
const res = await fetch(
|
||||||
}
|
`https://api.mapbox.com/geocoding/v5/mapbox.places/${encodeURIComponent(
|
||||||
|
locationName,
|
||||||
|
)}.json?access_token=${
|
||||||
|
CONFIG.MAPBOX_TOKEN
|
||||||
|
}&types=region,place,country&language=${locales.join(',')}`,
|
||||||
|
)
|
||||||
|
|
||||||
let data
|
debug(res)
|
||||||
|
|
||||||
res.features.forEach((item) => {
|
if (!res || !res.features || !res.features[0]) {
|
||||||
if (item.matching_place_name === locationName) {
|
throw new UserInputError('locationName is invalid')
|
||||||
data = item
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
if (!data) {
|
|
||||||
data = res.features[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!data || !data.place_type || !data.place_type.length) {
|
let data
|
||||||
throw new UserInputError('locationName is invalid')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.place_type.length > 1) {
|
res.features.forEach((item) => {
|
||||||
data.id = 'region.' + data.id.split('.')[1]
|
if (item.matching_place_name === locationName) {
|
||||||
}
|
data = item
|
||||||
await createLocation(session, data)
|
}
|
||||||
|
|
||||||
let parent = data
|
|
||||||
|
|
||||||
if (data.context) {
|
|
||||||
await asyncForEach(data.context, async (ctx) => {
|
|
||||||
await createLocation(session, ctx)
|
|
||||||
await session.writeTransaction((transaction) => {
|
|
||||||
return transaction.run(
|
|
||||||
`
|
|
||||||
MATCH (parent:Location {id: $parentId}), (child:Location {id: $childId})
|
|
||||||
MERGE (child)<-[:IS_IN]-(parent)
|
|
||||||
RETURN child.id, parent.id
|
|
||||||
`,
|
|
||||||
{
|
|
||||||
parentId: parent.id,
|
|
||||||
childId: ctx.id,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
})
|
|
||||||
parent = ctx
|
|
||||||
})
|
})
|
||||||
|
if (!data) {
|
||||||
|
data = res.features[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data || !data.place_type || !data.place_type.length) {
|
||||||
|
throw new UserInputError('locationName is invalid')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.place_type.length > 1) {
|
||||||
|
data.id = 'region.' + data.id.split('.')[1]
|
||||||
|
}
|
||||||
|
await createLocation(session, data)
|
||||||
|
|
||||||
|
let parent = data
|
||||||
|
|
||||||
|
if (data.context) {
|
||||||
|
await asyncForEach(data.context, async (ctx) => {
|
||||||
|
await createLocation(session, ctx)
|
||||||
|
await session.writeTransaction((transaction) => {
|
||||||
|
return transaction.run(
|
||||||
|
`
|
||||||
|
MATCH (parent:Location {id: $parentId}), (child:Location {id: $childId})
|
||||||
|
MERGE (child)<-[:IS_IN]-(parent)
|
||||||
|
RETURN child.id, parent.id
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
parentId: parent.id,
|
||||||
|
childId: ctx.id,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
parent = ctx
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
locationId = data.id
|
||||||
|
} else {
|
||||||
|
locationId = 'non-existent-id'
|
||||||
}
|
}
|
||||||
// delete all current locations from user and add new location
|
|
||||||
|
// delete all current locations from node and add new location
|
||||||
await session.writeTransaction((transaction) => {
|
await session.writeTransaction((transaction) => {
|
||||||
return transaction.run(
|
return transaction.run(
|
||||||
`
|
`
|
||||||
MATCH (user:User {id: $userId})-[relationship:IS_IN]->(location:Location)
|
MATCH (node:${nodeLabel} {id: $nodeId})
|
||||||
DETACH DELETE relationship
|
OPTIONAL MATCH (node)-[relationship:IS_IN]->(:Location)
|
||||||
WITH user
|
DELETE relationship
|
||||||
MATCH (location:Location {id: $locationId})
|
WITH node
|
||||||
MERGE (user)-[:IS_IN]->(location)
|
MATCH (location:Location {id: $locationId})
|
||||||
RETURN location.id, user.id
|
MERGE (node)-[:IS_IN]->(location)
|
||||||
`,
|
RETURN location.id, node.id
|
||||||
{ userId: userId, locationId: data.id },
|
`,
|
||||||
|
{ nodeId, locationId },
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -147,5 +155,3 @@ export const queryLocations = async ({ place, lang }) => {
|
|||||||
}
|
}
|
||||||
return res.features
|
return res.features
|
||||||
}
|
}
|
||||||
|
|
||||||
export default createOrUpdateLocations
|
|
||||||
|
|||||||
@ -33,8 +33,8 @@ type Group {
|
|||||||
groupType: GroupType!
|
groupType: GroupType!
|
||||||
actionRadius: GroupActionRadius!
|
actionRadius: GroupActionRadius!
|
||||||
|
|
||||||
location: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l")
|
|
||||||
locationName: String
|
locationName: String
|
||||||
|
location: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l")
|
||||||
|
|
||||||
categories: [Category] @relation(name: "CATEGORIZED", direction: "OUT")
|
categories: [Category] @relation(name: "CATEGORIZED", direction: "OUT")
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ type Mutation {
|
|||||||
actionRadius: GroupActionRadius!
|
actionRadius: GroupActionRadius!
|
||||||
categoryIds: [ID]
|
categoryIds: [ID]
|
||||||
# avatar: ImageInput # a group can not be created with an avatar
|
# avatar: ImageInput # a group can not be created with an avatar
|
||||||
locationName: String # test this as result
|
locationName: String # empty string '' sets it to null
|
||||||
): Group
|
): Group
|
||||||
|
|
||||||
UpdateGroup(
|
UpdateGroup(
|
||||||
@ -108,7 +108,7 @@ type Mutation {
|
|||||||
actionRadius: GroupActionRadius
|
actionRadius: GroupActionRadius
|
||||||
categoryIds: [ID]
|
categoryIds: [ID]
|
||||||
avatar: ImageInput # test this as result
|
avatar: ImageInput # test this as result
|
||||||
locationName: String # test this as result
|
locationName: String # empty string '' sets it to null
|
||||||
): Group
|
): Group
|
||||||
|
|
||||||
# DeleteGroup(id: ID!): Group
|
# DeleteGroup(id: ID!): Group
|
||||||
|
|||||||
@ -33,8 +33,8 @@ type User {
|
|||||||
invitedBy: User @relation(name: "INVITED", direction: "IN")
|
invitedBy: User @relation(name: "INVITED", direction: "IN")
|
||||||
invited: [User] @relation(name: "INVITED", direction: "OUT")
|
invited: [User] @relation(name: "INVITED", direction: "OUT")
|
||||||
|
|
||||||
location: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l")
|
|
||||||
locationName: String
|
locationName: String
|
||||||
|
location: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l")
|
||||||
about: String
|
about: String
|
||||||
socialMedia: [SocialMedia]! @relation(name: "OWNED_BY", direction: "IN")
|
socialMedia: [SocialMedia]! @relation(name: "OWNED_BY", direction: "IN")
|
||||||
|
|
||||||
@ -212,7 +212,7 @@ type Mutation {
|
|||||||
email: String
|
email: String
|
||||||
slug: String
|
slug: String
|
||||||
avatar: ImageInput
|
avatar: ImageInput
|
||||||
locationName: String
|
locationName: String # empty string '' sets it to null
|
||||||
about: String
|
about: String
|
||||||
termsAndConditionsAgreedVersion: String
|
termsAndConditionsAgreedVersion: String
|
||||||
termsAndConditionsAgreedAt: String
|
termsAndConditionsAgreedAt: String
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<base-button
|
<base-button
|
||||||
class="track-button"
|
class="join-leave-button"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
:loading="localLoading"
|
:loading="localLoading"
|
||||||
:icon="icon"
|
:icon="icon"
|
||||||
@ -108,7 +108,7 @@ export default {
|
|||||||
},
|
},
|
||||||
async joinLeave() {
|
async joinLeave() {
|
||||||
const join = !this.isMember
|
const join = !this.isMember
|
||||||
const mutation = join ? joinGroupMutation : leaveGroupMutation
|
const mutation = join ? joinGroupMutation() : leaveGroupMutation()
|
||||||
|
|
||||||
this.hovered = false
|
this.hovered = false
|
||||||
this.$emit('prepare', join)
|
this.$emit('prepare', join)
|
||||||
@ -129,7 +129,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.track-button {
|
.join-leave-button {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,6 @@
|
|||||||
v-tooltip="{
|
v-tooltip="{
|
||||||
content: $t(`contribution.category.description.${category.slug}`),
|
content: $t(`contribution.category.description.${category.slug}`),
|
||||||
placement: 'bottom-start',
|
placement: 'bottom-start',
|
||||||
delay: { show: 1500 },
|
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
{{ $t(`contribution.category.name.${category.slug}`) }}
|
{{ $t(`contribution.category.name.${category.slug}`) }}
|
||||||
|
|||||||
@ -20,7 +20,6 @@
|
|||||||
v-tooltip="{
|
v-tooltip="{
|
||||||
content: $t(`contribution.category.description.${category.slug}`),
|
content: $t(`contribution.category.description.${category.slug}`),
|
||||||
placement: 'bottom-start',
|
placement: 'bottom-start',
|
||||||
delay: { show: 1500 },
|
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@ -76,7 +76,7 @@ export default {
|
|||||||
const variables = { groupId: id, userId: this.$store.getters['auth/user'].id }
|
const variables = { groupId: id, userId: this.$store.getters['auth/user'].id }
|
||||||
try {
|
try {
|
||||||
await this.$apollo.mutate({
|
await this.$apollo.mutate({
|
||||||
mutation: joinGroupMutation,
|
mutation: joinGroupMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
this.$toast.success(this.$t('group.groupCreated'))
|
this.$toast.success(this.$t('group.groupCreated'))
|
||||||
|
|||||||
@ -71,7 +71,7 @@ export default {
|
|||||||
const newRole = event.target.value
|
const newRole = event.target.value
|
||||||
try {
|
try {
|
||||||
await this.$apollo.mutate({
|
await this.$apollo.mutate({
|
||||||
mutation: changeGroupMemberRoleMutation,
|
mutation: changeGroupMemberRoleMutation(),
|
||||||
variables: { groupId: this.groupId, userId: id, roleInGroup: newRole },
|
variables: { groupId: this.groupId, userId: id, roleInGroup: newRole },
|
||||||
})
|
})
|
||||||
this.$toast.success(this.$t('group.changeMemberRole', { role: newRole }))
|
this.$toast.success(this.$t('group.changeMemberRole', { role: newRole }))
|
||||||
|
|||||||
@ -31,9 +31,8 @@
|
|||||||
v-for="category in post.categories"
|
v-for="category in post.categories"
|
||||||
:key="category.id"
|
:key="category.id"
|
||||||
v-tooltip="{
|
v-tooltip="{
|
||||||
content: $t(`contribution.category.name.${category.slug}`),
|
content: $t(`contribution.category.description.${category.slug}`),
|
||||||
placement: 'bottom-start',
|
placement: 'bottom-start',
|
||||||
delay: { show: 1500 },
|
|
||||||
}"
|
}"
|
||||||
:icon="category.icon"
|
:icon="category.icon"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -29,6 +29,7 @@ describe('AvatarUploader', () => {
|
|||||||
profile: {
|
profile: {
|
||||||
avatar: { url: '/api/generic.jpg' },
|
avatar: { url: '/api/generic.jpg' },
|
||||||
},
|
},
|
||||||
|
updateMutation: jest.fn(),
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -40,7 +41,7 @@ describe('AvatarUploader', () => {
|
|||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('sends a the UpdateUser mutation when vddrop is called', () => {
|
it('sends the UpdateUser mutation when vddrop is called', () => {
|
||||||
wrapper.vm.vddrop([{ filename: 'avatar.jpg' }])
|
wrapper.vm.vddrop([{ filename: 'avatar.jpg' }])
|
||||||
expect(mocks.$apollo.mutate).toHaveBeenCalledTimes(1)
|
expect(mocks.$apollo.mutate).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="avatar-uploader">
|
||||||
<vue-dropzone
|
<vue-dropzone
|
||||||
id="customdropzone"
|
id="customdropzone"
|
||||||
:key="avatarUrl"
|
:key="avatarUrl"
|
||||||
@ -29,7 +29,7 @@ export default {
|
|||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
profile: { type: Object, required: true },
|
profile: { type: Object, required: true },
|
||||||
updateMutation: { type: Object, required: true },
|
updateMutation: { type: Function, required: true },
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@ -69,7 +69,7 @@ export default {
|
|||||||
const avatarUpload = file[0]
|
const avatarUpload = file[0]
|
||||||
this.$apollo
|
this.$apollo
|
||||||
.mutate({
|
.mutate({
|
||||||
mutation: this.updateMutation,
|
mutation: this.updateMutation(),
|
||||||
variables: {
|
variables: {
|
||||||
avatar: {
|
avatar: {
|
||||||
upload: avatarUpload,
|
upload: avatarUpload,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<button
|
<button
|
||||||
:class="buttonClass"
|
:class="buttonClass"
|
||||||
:disabled="loading"
|
:disabled="disabled || loading"
|
||||||
:type="type"
|
:type="type"
|
||||||
@click.capture="(event) => $emit('click', event)"
|
@click.capture="(event) => $emit('click', event)"
|
||||||
>
|
>
|
||||||
@ -56,6 +56,10 @@ export default {
|
|||||||
return value.match(/(button|submit)/)
|
return value.match(/(button|submit)/)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
disabled: {
|
||||||
|
// type: Boolean, // makes some errors that an Object was passed instead a Boolean and could not find how to solve in a acceptable time
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
buttonClass() {
|
buttonClass() {
|
||||||
|
|||||||
@ -12,6 +12,7 @@ export const userFragment = gql`
|
|||||||
deleted
|
deleted
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
export const locationAndBadgesFragment = (lang) => gql`
|
export const locationAndBadgesFragment = (lang) => gql`
|
||||||
fragment locationAndBadges on User {
|
fragment locationAndBadges on User {
|
||||||
location {
|
location {
|
||||||
|
|||||||
@ -221,25 +221,25 @@ export const updateUserMutation = () => {
|
|||||||
$id: ID!
|
$id: ID!
|
||||||
$slug: String
|
$slug: String
|
||||||
$name: String
|
$name: String
|
||||||
$locationName: String
|
|
||||||
$about: String
|
$about: String
|
||||||
$allowEmbedIframes: Boolean
|
$allowEmbedIframes: Boolean
|
||||||
$showShoutsPublicly: Boolean
|
$showShoutsPublicly: Boolean
|
||||||
$sendNotificationEmails: Boolean
|
$sendNotificationEmails: Boolean
|
||||||
$termsAndConditionsAgreedVersion: String
|
$termsAndConditionsAgreedVersion: String
|
||||||
$avatar: ImageInput
|
$avatar: ImageInput
|
||||||
|
$locationName: String # empty string '' sets it to null
|
||||||
) {
|
) {
|
||||||
UpdateUser(
|
UpdateUser(
|
||||||
id: $id
|
id: $id
|
||||||
slug: $slug
|
slug: $slug
|
||||||
name: $name
|
name: $name
|
||||||
locationName: $locationName
|
|
||||||
about: $about
|
about: $about
|
||||||
allowEmbedIframes: $allowEmbedIframes
|
allowEmbedIframes: $allowEmbedIframes
|
||||||
showShoutsPublicly: $showShoutsPublicly
|
showShoutsPublicly: $showShoutsPublicly
|
||||||
sendNotificationEmails: $sendNotificationEmails
|
sendNotificationEmails: $sendNotificationEmails
|
||||||
termsAndConditionsAgreedVersion: $termsAndConditionsAgreedVersion
|
termsAndConditionsAgreedVersion: $termsAndConditionsAgreedVersion
|
||||||
avatar: $avatar
|
avatar: $avatar
|
||||||
|
locationName: $locationName
|
||||||
) {
|
) {
|
||||||
id
|
id
|
||||||
slug
|
slug
|
||||||
|
|||||||
@ -2,171 +2,191 @@ import gql from 'graphql-tag'
|
|||||||
|
|
||||||
// ------ mutations
|
// ------ mutations
|
||||||
|
|
||||||
export const createGroupMutation = gql`
|
export const createGroupMutation = () => {
|
||||||
mutation (
|
return gql`
|
||||||
$id: ID
|
mutation (
|
||||||
$name: String!
|
$id: ID
|
||||||
$slug: String
|
$name: String!
|
||||||
$about: String
|
$slug: String
|
||||||
$description: String!
|
$about: String
|
||||||
$groupType: GroupType!
|
$description: String!
|
||||||
$actionRadius: GroupActionRadius!
|
$groupType: GroupType!
|
||||||
$categoryIds: [ID]
|
$actionRadius: GroupActionRadius!
|
||||||
$locationName: String
|
$categoryIds: [ID]
|
||||||
) {
|
$locationName: String # empty string '' sets it to null
|
||||||
CreateGroup(
|
|
||||||
id: $id
|
|
||||||
name: $name
|
|
||||||
slug: $slug
|
|
||||||
about: $about
|
|
||||||
description: $description
|
|
||||||
groupType: $groupType
|
|
||||||
actionRadius: $actionRadius
|
|
||||||
categoryIds: $categoryIds
|
|
||||||
locationName: $locationName
|
|
||||||
) {
|
) {
|
||||||
id
|
CreateGroup(
|
||||||
name
|
id: $id
|
||||||
slug
|
name: $name
|
||||||
createdAt
|
slug: $slug
|
||||||
updatedAt
|
about: $about
|
||||||
disabled
|
description: $description
|
||||||
deleted
|
groupType: $groupType
|
||||||
about
|
actionRadius: $actionRadius
|
||||||
description
|
categoryIds: $categoryIds
|
||||||
groupType
|
locationName: $locationName
|
||||||
actionRadius
|
) {
|
||||||
categories {
|
|
||||||
id
|
id
|
||||||
slug
|
|
||||||
name
|
name
|
||||||
icon
|
slug
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
disabled
|
||||||
|
deleted
|
||||||
|
about
|
||||||
|
description
|
||||||
|
descriptionExcerpt
|
||||||
|
groupType
|
||||||
|
actionRadius
|
||||||
|
categories {
|
||||||
|
id
|
||||||
|
slug
|
||||||
|
name
|
||||||
|
icon
|
||||||
|
}
|
||||||
|
locationName
|
||||||
|
myRole
|
||||||
}
|
}
|
||||||
locationName # test this as result
|
|
||||||
myRole
|
|
||||||
}
|
}
|
||||||
}
|
`
|
||||||
`
|
}
|
||||||
|
|
||||||
export const updateGroupMutation = gql`
|
export const updateGroupMutation = () => {
|
||||||
mutation (
|
return gql`
|
||||||
$id: ID!
|
mutation (
|
||||||
$name: String
|
$id: ID!
|
||||||
$slug: String
|
$name: String
|
||||||
$about: String
|
$slug: String
|
||||||
$description: String
|
$about: String
|
||||||
$actionRadius: GroupActionRadius
|
$description: String
|
||||||
$categoryIds: [ID]
|
$actionRadius: GroupActionRadius
|
||||||
$avatar: ImageInput
|
$categoryIds: [ID]
|
||||||
$locationName: String
|
$avatar: ImageInput
|
||||||
) {
|
$locationName: String # empty string '' sets it to null
|
||||||
UpdateGroup(
|
|
||||||
id: $id
|
|
||||||
name: $name
|
|
||||||
slug: $slug
|
|
||||||
about: $about
|
|
||||||
description: $description
|
|
||||||
actionRadius: $actionRadius
|
|
||||||
categoryIds: $categoryIds
|
|
||||||
avatar: $avatar
|
|
||||||
locationName: $locationName
|
|
||||||
) {
|
) {
|
||||||
id
|
UpdateGroup(
|
||||||
name
|
id: $id
|
||||||
slug
|
name: $name
|
||||||
createdAt
|
slug: $slug
|
||||||
updatedAt
|
about: $about
|
||||||
disabled
|
description: $description
|
||||||
deleted
|
actionRadius: $actionRadius
|
||||||
about
|
categoryIds: $categoryIds
|
||||||
description
|
avatar: $avatar
|
||||||
groupType
|
locationName: $locationName
|
||||||
actionRadius
|
) {
|
||||||
categories {
|
|
||||||
id
|
id
|
||||||
slug
|
|
||||||
name
|
name
|
||||||
icon
|
slug
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
disabled
|
||||||
|
deleted
|
||||||
|
about
|
||||||
|
description
|
||||||
|
descriptionExcerpt
|
||||||
|
groupType
|
||||||
|
actionRadius
|
||||||
|
categories {
|
||||||
|
id
|
||||||
|
slug
|
||||||
|
name
|
||||||
|
icon
|
||||||
|
}
|
||||||
|
# avatar # test this as result
|
||||||
|
locationName
|
||||||
|
myRole
|
||||||
}
|
}
|
||||||
# avatar # test this as result
|
|
||||||
# locationName # test this as result
|
|
||||||
myRole
|
|
||||||
}
|
}
|
||||||
}
|
`
|
||||||
`
|
}
|
||||||
|
|
||||||
export const joinGroupMutation = gql`
|
export const joinGroupMutation = () => {
|
||||||
mutation ($groupId: ID!, $userId: ID!) {
|
return gql`
|
||||||
JoinGroup(groupId: $groupId, userId: $userId) {
|
mutation ($groupId: ID!, $userId: ID!) {
|
||||||
id
|
JoinGroup(groupId: $groupId, userId: $userId) {
|
||||||
name
|
id
|
||||||
slug
|
name
|
||||||
myRoleInGroup
|
slug
|
||||||
|
myRoleInGroup
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
`
|
||||||
`
|
}
|
||||||
|
|
||||||
export const leaveGroupMutation = gql`
|
export const leaveGroupMutation = () => {
|
||||||
mutation ($groupId: ID!, $userId: ID!) {
|
return gql`
|
||||||
LeaveGroup(groupId: $groupId, userId: $userId) {
|
mutation ($groupId: ID!, $userId: ID!) {
|
||||||
id
|
LeaveGroup(groupId: $groupId, userId: $userId) {
|
||||||
name
|
id
|
||||||
slug
|
name
|
||||||
myRoleInGroup
|
slug
|
||||||
|
myRoleInGroup
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
`
|
||||||
`
|
}
|
||||||
|
|
||||||
export const changeGroupMemberRoleMutation = gql`
|
export const changeGroupMemberRoleMutation = () => {
|
||||||
mutation ($groupId: ID!, $userId: ID!, $roleInGroup: GroupMemberRole!) {
|
return gql`
|
||||||
ChangeGroupMemberRole(groupId: $groupId, userId: $userId, roleInGroup: $roleInGroup) {
|
mutation ($groupId: ID!, $userId: ID!, $roleInGroup: GroupMemberRole!) {
|
||||||
id
|
ChangeGroupMemberRole(groupId: $groupId, userId: $userId, roleInGroup: $roleInGroup) {
|
||||||
name
|
id
|
||||||
slug
|
name
|
||||||
myRoleInGroup
|
slug
|
||||||
|
myRoleInGroup
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
`
|
||||||
`
|
}
|
||||||
|
|
||||||
// ------ queries
|
// ------ queries
|
||||||
|
|
||||||
export const groupQuery = gql`
|
export const groupQuery = (i18n) => {
|
||||||
query ($isMember: Boolean, $id: ID, $slug: String) {
|
const lang = i18n ? i18n.locale().toUpperCase() : 'EN'
|
||||||
Group(isMember: $isMember, id: $id, slug: $slug) {
|
return gql`
|
||||||
id
|
query ($isMember: Boolean, $id: ID, $slug: String) {
|
||||||
name
|
Group(isMember: $isMember, id: $id, slug: $slug) {
|
||||||
slug
|
|
||||||
createdAt
|
|
||||||
updatedAt
|
|
||||||
disabled
|
|
||||||
deleted
|
|
||||||
about
|
|
||||||
description
|
|
||||||
descriptionExcerpt
|
|
||||||
groupType
|
|
||||||
actionRadius
|
|
||||||
categories {
|
|
||||||
id
|
id
|
||||||
slug
|
|
||||||
name
|
name
|
||||||
icon
|
slug
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
disabled
|
||||||
|
deleted
|
||||||
|
about
|
||||||
|
description
|
||||||
|
descriptionExcerpt
|
||||||
|
groupType
|
||||||
|
actionRadius
|
||||||
|
categories {
|
||||||
|
id
|
||||||
|
slug
|
||||||
|
name
|
||||||
|
icon
|
||||||
|
}
|
||||||
|
avatar {
|
||||||
|
url
|
||||||
|
}
|
||||||
|
locationName
|
||||||
|
location {
|
||||||
|
name: name${lang}
|
||||||
|
}
|
||||||
|
myRole
|
||||||
}
|
}
|
||||||
avatar {
|
|
||||||
url
|
|
||||||
}
|
|
||||||
locationName # test this as result
|
|
||||||
myRole
|
|
||||||
}
|
}
|
||||||
}
|
`
|
||||||
`
|
}
|
||||||
|
|
||||||
export const groupMembersQuery = gql`
|
export const groupMembersQuery = () => {
|
||||||
query ($id: ID!) {
|
return gql`
|
||||||
GroupMembers(id: $id) {
|
query ($id: ID!) {
|
||||||
id
|
GroupMembers(id: $id) {
|
||||||
name
|
id
|
||||||
slug
|
name
|
||||||
myRoleInGroup
|
slug
|
||||||
|
myRoleInGroup
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
`
|
||||||
`
|
}
|
||||||
|
|||||||
@ -405,6 +405,7 @@
|
|||||||
},
|
},
|
||||||
"actionRadius": "Aktionsradius",
|
"actionRadius": "Aktionsradius",
|
||||||
"back": "zurück",
|
"back": "zurück",
|
||||||
|
"categories": "Thema ::: Themen",
|
||||||
"change-member-role": "Die Rolle wurde auf „{role}“ geändert!",
|
"change-member-role": "Die Rolle wurde auf „{role}“ geändert!",
|
||||||
"follow": "Folge",
|
"follow": "Folge",
|
||||||
"foundation": "Gründung",
|
"foundation": "Gründung",
|
||||||
@ -424,8 +425,9 @@
|
|||||||
},
|
},
|
||||||
"long-description": "Beschreibung",
|
"long-description": "Beschreibung",
|
||||||
"members": "Mitglieder",
|
"members": "Mitglieder",
|
||||||
"membersCount": "Mitglieder",
|
"membersCount": "Mitglied ::: Mitglieder",
|
||||||
"membersListTitle": "Gruppenmitglieder",
|
"membersListTitle": "Gruppenmitglieder",
|
||||||
|
"membersListTitleNotAllowedSeeingGroupMembers": "Gruppenmitglieder unsichtbar",
|
||||||
"myGroups": "Meine Gruppen",
|
"myGroups": "Meine Gruppen",
|
||||||
"newGroup": "Erstelle eine neue Gruppe",
|
"newGroup": "Erstelle eine neue Gruppe",
|
||||||
"radius": "Radius",
|
"radius": "Radius",
|
||||||
|
|||||||
@ -405,6 +405,7 @@
|
|||||||
},
|
},
|
||||||
"actionRadius": "Action radius",
|
"actionRadius": "Action radius",
|
||||||
"back": "back",
|
"back": "back",
|
||||||
|
"categories": "Topic ::: Topics",
|
||||||
"change-member-role": "The role has been changed to “{role}”!",
|
"change-member-role": "The role has been changed to “{role}”!",
|
||||||
"follow": "Follow",
|
"follow": "Follow",
|
||||||
"foundation": "Foundation",
|
"foundation": "Foundation",
|
||||||
@ -424,8 +425,9 @@
|
|||||||
},
|
},
|
||||||
"long-description": "Description",
|
"long-description": "Description",
|
||||||
"members": "Members",
|
"members": "Members",
|
||||||
"membersCount": "Members",
|
"membersCount": "Member ::: Members",
|
||||||
"membersListTitle": "Group Members",
|
"membersListTitle": "Group Members",
|
||||||
|
"membersListTitleNotAllowedSeeingGroupMembers": "Group Members invisible",
|
||||||
"myGroups": "My Groups",
|
"myGroups": "My Groups",
|
||||||
"newGroup": "Create a new Group",
|
"newGroup": "Create a new Group",
|
||||||
"radius": "Radius",
|
"radius": "Radius",
|
||||||
|
|||||||
@ -1,95 +0,0 @@
|
|||||||
// import { config, mount } from '@vue/test-utils'
|
|
||||||
// import ProfileSlug from './_slug.vue'
|
|
||||||
|
|
||||||
// const localVue = global.localVue
|
|
||||||
|
|
||||||
// localVue.filter('date', (d) => d)
|
|
||||||
|
|
||||||
// config.stubs['client-only'] = '<span><slot /></span>'
|
|
||||||
// config.stubs['v-popover'] = '<span><slot /></span>'
|
|
||||||
// config.stubs['nuxt-link'] = '<span><slot /></span>'
|
|
||||||
// config.stubs['infinite-loading'] = '<span><slot /></span>'
|
|
||||||
// config.stubs['follow-list'] = '<span><slot /></span>'
|
|
||||||
|
|
||||||
// describe('ProfileSlug', () => {
|
|
||||||
// let wrapper
|
|
||||||
// let Wrapper
|
|
||||||
// let mocks
|
|
||||||
|
|
||||||
// beforeEach(() => {
|
|
||||||
// mocks = {
|
|
||||||
// post: {
|
|
||||||
// id: 'p23',
|
|
||||||
// name: 'It is a post',
|
|
||||||
// },
|
|
||||||
// $t: jest.fn(),
|
|
||||||
// // If you're mocking router, then don't use VueRouter with localVue: https://vue-test-utils.vuejs.org/guides/using-with-vue-router.html
|
|
||||||
// $route: {
|
|
||||||
// params: {
|
|
||||||
// id: '4711',
|
|
||||||
// slug: 'john-doe',
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// $router: {
|
|
||||||
// history: {
|
|
||||||
// push: jest.fn(),
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// $toast: {
|
|
||||||
// success: jest.fn(),
|
|
||||||
// error: jest.fn(),
|
|
||||||
// },
|
|
||||||
// $apollo: {
|
|
||||||
// loading: false,
|
|
||||||
// mutate: jest.fn().mockResolvedValue(),
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
|
|
||||||
// describe('mount', () => {
|
|
||||||
// Wrapper = () => {
|
|
||||||
// return mount(ProfileSlug, {
|
|
||||||
// mocks,
|
|
||||||
// localVue,
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
|
|
||||||
// describe('given an authenticated user', () => {
|
|
||||||
// beforeEach(() => {
|
|
||||||
// mocks.$filters = {
|
|
||||||
// removeLinks: (c) => c,
|
|
||||||
// truncate: (a) => a,
|
|
||||||
// }
|
|
||||||
// mocks.$store = {
|
|
||||||
// getters: {
|
|
||||||
// 'auth/isModerator': () => false,
|
|
||||||
// 'auth/user': {
|
|
||||||
// id: 'u23',
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
|
|
||||||
// describe('given a user for the profile', () => {
|
|
||||||
// beforeEach(() => {
|
|
||||||
// wrapper = Wrapper()
|
|
||||||
// wrapper.setData({
|
|
||||||
// User: [
|
|
||||||
// {
|
|
||||||
// id: 'u3',
|
|
||||||
// name: 'Bob the builder',
|
|
||||||
// contributionsCount: 6,
|
|
||||||
// shoutedCount: 7,
|
|
||||||
// commentedCount: 8,
|
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
|
|
||||||
// it('displays name of the user', () => {
|
|
||||||
// expect(wrapper.text()).toContain('Bob the builder')
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
1562
webapp/pages/group/_id/_slug.spec.js
Normal file
1562
webapp/pages/group/_id/_slug.spec.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div v-if="isGroupVisible">
|
||||||
<ds-space />
|
<ds-space />
|
||||||
<ds-flex v-if="group" :width="{ base: '100%' }" gutter="base">
|
<ds-flex v-if="group" :width="{ base: '100%' }" gutter="base">
|
||||||
<ds-flex-item :width="{ base: '100%', sm: 2, md: 2, lg: 1 }">
|
<ds-flex-item :width="{ base: '100%', sm: 2, md: 2, lg: 1 }">
|
||||||
@ -31,24 +31,29 @@
|
|||||||
/>
|
/>
|
||||||
</client-only> -->
|
</client-only> -->
|
||||||
<ds-space margin="small">
|
<ds-space margin="small">
|
||||||
|
<!-- Group name -->
|
||||||
<ds-heading tag="h3" align="center" no-margin>
|
<ds-heading tag="h3" align="center" no-margin>
|
||||||
{{ groupName }}
|
{{ groupName }}
|
||||||
</ds-heading>
|
</ds-heading>
|
||||||
|
<!-- Group slug -->
|
||||||
<ds-text align="center" color="soft">
|
<ds-text align="center" color="soft">
|
||||||
{{ groupSlug }}
|
{{ groupSlug }}
|
||||||
</ds-text>
|
</ds-text>
|
||||||
<!-- <ds-text v-if="user.location" align="center" color="soft" size="small">
|
<!-- Group location -->
|
||||||
<base-icon name="map-marker" />
|
<ds-text v-if="group && group.location" align="center" color="soft" size="small">
|
||||||
{{ user.location.name }}
|
<base-icon name="map-marker" data-test="map-marker" />
|
||||||
</ds-text> -->
|
{{ group && group.location ? group.location.name : '' }}
|
||||||
|
</ds-text>
|
||||||
|
<!-- Group created at -->
|
||||||
<ds-text align="center" color="soft" size="small">
|
<ds-text align="center" color="soft" size="small">
|
||||||
{{ $t('group.foundation') }} {{ group.createdAt | date('MMMM yyyy') }}
|
{{ $t('group.foundation') }} {{ group.createdAt | date('MMMM yyyy') }}
|
||||||
</ds-text>
|
</ds-text>
|
||||||
</ds-space>
|
</ds-space>
|
||||||
<ds-flex>
|
<ds-flex v-if="isAllowedSeeingGroupMembers">
|
||||||
<ds-flex-item>
|
<!-- Group members count -->
|
||||||
|
<ds-flex-item v-if="isAllowedSeeingGroupMembers">
|
||||||
<client-only>
|
<client-only>
|
||||||
<ds-number :label="$t('group.membersCount')">
|
<ds-number :label="$t('group.membersCount', {}, groupMembers.length)">
|
||||||
<count-to
|
<count-to
|
||||||
slot="count"
|
slot="count"
|
||||||
:start-val="membersCountStartValue"
|
:start-val="membersCountStartValue"
|
||||||
@ -90,6 +95,7 @@
|
|||||||
@optimistic="optimisticFollow"
|
@optimistic="optimisticFollow"
|
||||||
@update="updateFollow"
|
@update="updateFollow"
|
||||||
/> -->
|
/> -->
|
||||||
|
<!-- Group join / leave -->
|
||||||
<join-leave-button
|
<join-leave-button
|
||||||
:group="group || {}"
|
:group="group || {}"
|
||||||
:userId="currentUser.id"
|
:userId="currentUser.id"
|
||||||
@ -104,35 +110,82 @@
|
|||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
<ds-space margin-top="small" margin-bottom="small">
|
<ds-space margin-top="small" margin-bottom="small">
|
||||||
|
<!-- Group my role in group -->
|
||||||
<template v-if="isGroupMember">
|
<template v-if="isGroupMember">
|
||||||
<ds-text class="centered-text hyphenate-text" color="soft" size="small">
|
<ds-text class="centered-text hyphenate-text" color="soft" size="small">
|
||||||
{{ $t('group.role') }}
|
{{ $t('group.role') }}
|
||||||
</ds-text>
|
</ds-text>
|
||||||
<div class="chip" align="center">
|
<div class="chip" align="center">
|
||||||
<ds-chip color="primary">{{ $t('group.roles.' + group.myRole) }}</ds-chip>
|
<ds-chip color="primary">
|
||||||
|
{{ group && group.myRole ? $t('group.roles.' + group.myRole) : '' }}
|
||||||
|
</ds-chip>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
<!-- Group type -->
|
||||||
<ds-text class="centered-text hyphenate-text" color="soft" size="small">
|
<ds-text class="centered-text hyphenate-text" color="soft" size="small">
|
||||||
{{ $t('group.type') }}
|
{{ $t('group.type') }}
|
||||||
</ds-text>
|
</ds-text>
|
||||||
<div class="chip" align="center">
|
<div class="chip" align="center">
|
||||||
<ds-chip color="primary">{{ $t('group.types.' + group.groupType) }}</ds-chip>
|
<ds-chip color="primary">
|
||||||
|
{{ group && group.groupType ? $t('group.types.' + group.groupType) : '' }}
|
||||||
|
</ds-chip>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Group action radius -->
|
||||||
<ds-text class="centered-text hyphenate-text" color="soft" size="small">
|
<ds-text class="centered-text hyphenate-text" color="soft" size="small">
|
||||||
{{ $t('group.actionRadius') }}
|
{{ $t('group.actionRadius') }}
|
||||||
</ds-text>
|
</ds-text>
|
||||||
<div class="chip" align="center">
|
<div class="chip" align="center">
|
||||||
<ds-chip color="primary">{{ $t('group.actionRadii.' + group.actionRadius) }}</ds-chip>
|
<ds-chip color="primary">
|
||||||
|
{{
|
||||||
|
group && group.actionRadius ? $t('group.actionRadii.' + group.actionRadius) : ''
|
||||||
|
}}
|
||||||
|
</ds-chip>
|
||||||
</div>
|
</div>
|
||||||
|
<ds-space margin="x-small" />
|
||||||
</ds-space>
|
</ds-space>
|
||||||
<template v-if="group.about">
|
<!-- Group categories -->
|
||||||
|
<template v-if="categoriesActive">
|
||||||
|
<hr />
|
||||||
|
<ds-space margin-top="small" margin-bottom="small">
|
||||||
|
<ds-text class="centered-text hyphenate-text" color="soft" size="small">
|
||||||
|
{{
|
||||||
|
$t(
|
||||||
|
'group.categories',
|
||||||
|
{},
|
||||||
|
group && group.categories ? group.categories.length : 0,
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
</ds-text>
|
||||||
|
<ds-space margin="xx-small" />
|
||||||
|
<div class="categories">
|
||||||
|
<div
|
||||||
|
v-for="(category, index) in group.categories"
|
||||||
|
:key="category.id"
|
||||||
|
align="center"
|
||||||
|
>
|
||||||
|
<category
|
||||||
|
:icon="category.icon"
|
||||||
|
:name="$t(`contribution.category.name.${category.slug}`)"
|
||||||
|
v-tooltip="{
|
||||||
|
content: $t(`contribution.category.description.${category.slug}`),
|
||||||
|
placement: 'bottom-start',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
<ds-space v-if="index < group.categories.length - 1" margin="xxx-small" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ds-space>
|
||||||
|
</template>
|
||||||
|
<!-- Group goal -->
|
||||||
|
<template v-if="group && group.about">
|
||||||
<hr />
|
<hr />
|
||||||
<ds-space margin-top="small" margin-bottom="small">
|
<ds-space margin-top="small" margin-bottom="small">
|
||||||
<ds-text class="centered-text hyphenate-text" color="soft" size="small">
|
<ds-text class="centered-text hyphenate-text" color="soft" size="small">
|
||||||
{{ $t('group.goal') }}
|
{{ $t('group.goal') }}
|
||||||
</ds-text>
|
</ds-text>
|
||||||
|
<ds-space margin="xx-small" />
|
||||||
<div class="chip" align="center">
|
<div class="chip" align="center">
|
||||||
<ds-chip>{{ group.about }}</ds-chip>
|
<ds-chip>{{ group ? group.about : '' }}</ds-chip>
|
||||||
</div>
|
</div>
|
||||||
</ds-space>
|
</ds-space>
|
||||||
</template>
|
</template>
|
||||||
@ -143,10 +196,15 @@
|
|||||||
</ds-heading>
|
</ds-heading>
|
||||||
<!-- Group members list -->
|
<!-- Group members list -->
|
||||||
<profile-list
|
<profile-list
|
||||||
:uniqueName="`groupMembersFilter`"
|
:uniqueName="'groupMembersFilter'"
|
||||||
:title="$t('group.membersListTitle')"
|
:title="$t('group.membersListTitle')"
|
||||||
:allProfilesCount="groupMembers.length"
|
:titleNobody="
|
||||||
:profiles="groupMembers"
|
!isAllowedSeeingGroupMembers
|
||||||
|
? $t('group.membersListTitleNotAllowedSeeingGroupMembers')
|
||||||
|
: null
|
||||||
|
"
|
||||||
|
:allProfilesCount="isAllowedSeeingGroupMembers ? groupMembers.length : 0"
|
||||||
|
:profiles="isAllowedSeeingGroupMembers ? groupMembers : []"
|
||||||
:loading="$apollo.loading"
|
:loading="$apollo.loading"
|
||||||
@fetchAllProfiles="fetchAllMembers"
|
@fetchAllProfiles="fetchAllMembers"
|
||||||
/>
|
/>
|
||||||
@ -168,31 +226,48 @@
|
|||||||
</ds-flex-item>
|
</ds-flex-item>
|
||||||
|
|
||||||
<ds-flex-item :width="{ base: '100%', sm: 3, md: 5, lg: 3 }">
|
<ds-flex-item :width="{ base: '100%', sm: 3, md: 5, lg: 3 }">
|
||||||
|
<!-- Group description -->
|
||||||
|
<ds-space>
|
||||||
|
<base-card class="group-description">
|
||||||
|
<!-- TODO: replace editor content with tiptap render view -->
|
||||||
|
<!-- eslint-disable vue/no-v-html -->
|
||||||
|
<div
|
||||||
|
v-if="isDescriptionCollapsed"
|
||||||
|
class="content hyphenate-text"
|
||||||
|
v-html="groupDescriptionExcerpt"
|
||||||
|
/>
|
||||||
|
<content-viewer v-else class="content hyphenate-text" :content="group.description" />
|
||||||
|
<!-- eslint-enable vue/no-v-html -->
|
||||||
|
<base-button
|
||||||
|
class="collaps-button"
|
||||||
|
size="small"
|
||||||
|
ghost
|
||||||
|
@click="isDescriptionCollapsed = !isDescriptionCollapsed"
|
||||||
|
>
|
||||||
|
{{ isDescriptionCollapsed ? $t('comment.show.more') : $t('comment.show.less') }}
|
||||||
|
</base-button>
|
||||||
|
</base-card>
|
||||||
|
</ds-space>
|
||||||
|
<ds-space v-if="isGroupMemberNonePending" centered>
|
||||||
|
<nuxt-link :to="{ name: 'post-create' }">
|
||||||
|
<base-button
|
||||||
|
class="profile-post-add-button"
|
||||||
|
:path="{ name: 'post-create' }"
|
||||||
|
icon="plus"
|
||||||
|
circle
|
||||||
|
filled
|
||||||
|
v-tooltip="{
|
||||||
|
content: $t('contribution.newPost'),
|
||||||
|
placement: 'left',
|
||||||
|
}"
|
||||||
|
/>
|
||||||
|
</nuxt-link>
|
||||||
|
</ds-space>
|
||||||
<masonry-grid>
|
<masonry-grid>
|
||||||
<!-- TapNavigation -->
|
<!-- TapNavigation -->
|
||||||
<!-- <tab-navigation :tabs="tabOptions" :activeTab="tabActive" @switch-tab="handleTab" /> -->
|
<!-- <tab-navigation :tabs="tabOptions" :activeTab="tabActive" @switch-tab="handleTab" /> -->
|
||||||
|
|
||||||
<!-- feed -->
|
<!-- Group post feed -->
|
||||||
<ds-grid-item :row-span="2" column-span="fullWidth">
|
|
||||||
<ds-space centered>
|
|
||||||
<nuxt-link :to="{ name: 'post-create' }">
|
|
||||||
<base-button
|
|
||||||
v-if="isGroupMember"
|
|
||||||
v-tooltip="{
|
|
||||||
content: $t('contribution.newPost'),
|
|
||||||
placement: 'left',
|
|
||||||
delay: { show: 500 },
|
|
||||||
}"
|
|
||||||
:path="{ name: 'post-create' }"
|
|
||||||
class="profile-post-add-button"
|
|
||||||
icon="plus"
|
|
||||||
circle
|
|
||||||
filled
|
|
||||||
/>
|
|
||||||
</nuxt-link>
|
|
||||||
</ds-space>
|
|
||||||
</ds-grid-item>
|
|
||||||
|
|
||||||
<template v-if="posts && posts.length">
|
<template v-if="posts && posts.length">
|
||||||
<masonry-grid-item
|
<masonry-grid-item
|
||||||
v-for="post in posts"
|
v-for="post in posts"
|
||||||
@ -217,7 +292,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<ds-grid-item column-span="fullWidth">
|
<ds-grid-item column-span="fullWidth">
|
||||||
<empty margin="xx-large" icon="file" />
|
<empty margin="xx-large" icon="file" data-test="icon-empty" />
|
||||||
</ds-grid-item>
|
</ds-grid-item>
|
||||||
</template>
|
</template>
|
||||||
</masonry-grid>
|
</masonry-grid>
|
||||||
@ -238,7 +313,9 @@ import { updateGroupMutation, groupQuery, groupMembersQuery } from '~/graphql/gr
|
|||||||
// import UpdateQuery from '~/components/utils/UpdateQuery'
|
// import UpdateQuery from '~/components/utils/UpdateQuery'
|
||||||
import postListActions from '~/mixins/postListActions'
|
import postListActions from '~/mixins/postListActions'
|
||||||
import AvatarUploader from '~/components/Uploader/AvatarUploader'
|
import AvatarUploader from '~/components/Uploader/AvatarUploader'
|
||||||
|
import Category from '~/components/Category'
|
||||||
// import ContentMenu from '~/components/ContentMenu/ContentMenu'
|
// import ContentMenu from '~/components/ContentMenu/ContentMenu'
|
||||||
|
import ContentViewer from '~/components/Editor/ContentViewer'
|
||||||
import CountTo from '~/components/CountTo.vue'
|
import CountTo from '~/components/CountTo.vue'
|
||||||
import Empty from '~/components/Empty/Empty'
|
import Empty from '~/components/Empty/Empty'
|
||||||
// import FollowButton from '~/components/Button/FollowButton'
|
// import FollowButton from '~/components/Button/FollowButton'
|
||||||
@ -263,7 +340,9 @@ import ProfileList from '~/components/features/ProfileList/ProfileList'
|
|||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
AvatarUploader,
|
AvatarUploader,
|
||||||
|
Category,
|
||||||
// ContentMenu,
|
// ContentMenu,
|
||||||
|
ContentViewer,
|
||||||
CountTo,
|
CountTo,
|
||||||
Empty,
|
Empty,
|
||||||
// FollowButton,
|
// FollowButton,
|
||||||
@ -290,8 +369,10 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
// const filter = tabToFilterMapping({ tab: 'post', id: this.$route.params.id })
|
// const filter = tabToFilterMapping({ tab: 'post', id: this.$route.params.id })
|
||||||
return {
|
return {
|
||||||
|
categoriesActive: this.$env.CATEGORIES_ACTIVE,
|
||||||
Group: [],
|
Group: [],
|
||||||
GroupMembers: [],
|
GroupMembers: [],
|
||||||
|
loadGroupMembers: false,
|
||||||
posts: [],
|
posts: [],
|
||||||
// hasMore: true,
|
// hasMore: true,
|
||||||
// offset: 0,
|
// offset: 0,
|
||||||
@ -304,6 +385,7 @@ export default {
|
|||||||
membersCountStartValue: 0,
|
membersCountStartValue: 0,
|
||||||
membersCountToLoad: Infinity,
|
membersCountToLoad: Infinity,
|
||||||
updateGroupMutation,
|
updateGroupMutation,
|
||||||
|
isDescriptionCollapsed: true,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -311,16 +393,7 @@ export default {
|
|||||||
return this.$store.getters['auth/user']
|
return this.$store.getters['auth/user']
|
||||||
},
|
},
|
||||||
group() {
|
group() {
|
||||||
return this.Group[0] ? this.Group[0] : {}
|
return this.Group && this.Group[0] ? this.Group[0] : {}
|
||||||
},
|
|
||||||
groupMembers() {
|
|
||||||
return this.GroupMembers ? this.GroupMembers : []
|
|
||||||
},
|
|
||||||
isGroupOwner() {
|
|
||||||
return this.group ? this.group.myRole === 'owner' : false
|
|
||||||
},
|
|
||||||
isGroupMember() {
|
|
||||||
return this.group ? !!this.group.myRole : false
|
|
||||||
},
|
},
|
||||||
groupName() {
|
groupName() {
|
||||||
const { name } = this.group || {}
|
const { name } = this.group || {}
|
||||||
@ -330,6 +403,31 @@ export default {
|
|||||||
const { slug } = this.group || {}
|
const { slug } = this.group || {}
|
||||||
return slug && `@${slug}`
|
return slug && `@${slug}`
|
||||||
},
|
},
|
||||||
|
groupDescriptionExcerpt() {
|
||||||
|
return this.group ? this.$filters.removeLinks(this.group.descriptionExcerpt) : ''
|
||||||
|
},
|
||||||
|
isGroupOwner() {
|
||||||
|
return this.group ? this.group.myRole === 'owner' : false
|
||||||
|
},
|
||||||
|
isGroupMember() {
|
||||||
|
return this.group ? !!this.group.myRole : false
|
||||||
|
},
|
||||||
|
isGroupMemberNonePending() {
|
||||||
|
return this.group ? ['usual', 'admin', 'owner'].includes(this.group.myRole) : false
|
||||||
|
},
|
||||||
|
isGroupVisible() {
|
||||||
|
return this.group && !(this.group.groupType === 'hidden' && !this.isGroupMemberNonePending)
|
||||||
|
},
|
||||||
|
groupMembers() {
|
||||||
|
return this.GroupMembers ? this.GroupMembers : []
|
||||||
|
},
|
||||||
|
isAllowedSeeingGroupMembers() {
|
||||||
|
return (
|
||||||
|
this.group &&
|
||||||
|
(this.group.groupType === 'public' ||
|
||||||
|
(['closed', 'hidden'].includes(this.group.groupType) && this.isGroupMemberNonePending))
|
||||||
|
)
|
||||||
|
},
|
||||||
// tabOptions() {
|
// tabOptions() {
|
||||||
// return [
|
// return [
|
||||||
// {
|
// {
|
||||||
@ -353,6 +451,11 @@ export default {
|
|||||||
// ]
|
// ]
|
||||||
// },
|
// },
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
isAllowedSeeingGroupMembers(to, _from) {
|
||||||
|
this.loadGroupMembers = to
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// handleTab(tab) {
|
// handleTab(tab) {
|
||||||
// if (this.tabActive !== tab) {
|
// if (this.tabActive !== tab) {
|
||||||
@ -463,7 +566,11 @@ export default {
|
|||||||
},
|
},
|
||||||
updateJoinLeave({ myRoleInGroup }) {
|
updateJoinLeave({ myRoleInGroup }) {
|
||||||
this.Group[0].myRole = myRoleInGroup
|
this.Group[0].myRole = myRoleInGroup
|
||||||
this.$apollo.queries.GroupMembers.refetch()
|
if (this.isAllowedSeeingGroupMembers) {
|
||||||
|
this.$apollo.queries.GroupMembers.refetch()
|
||||||
|
} else {
|
||||||
|
this.GroupMembers = []
|
||||||
|
}
|
||||||
},
|
},
|
||||||
fetchAllMembers() {
|
fetchAllMembers() {
|
||||||
this.membersCountToLoad = Infinity
|
this.membersCountToLoad = Infinity
|
||||||
@ -489,8 +596,7 @@ export default {
|
|||||||
// },
|
// },
|
||||||
Group: {
|
Group: {
|
||||||
query() {
|
query() {
|
||||||
// return groupQuery(this.$i18n) // language will be needed for locations
|
return groupQuery(this.$i18n)
|
||||||
return groupQuery
|
|
||||||
},
|
},
|
||||||
variables() {
|
variables() {
|
||||||
return {
|
return {
|
||||||
@ -499,17 +605,26 @@ export default {
|
|||||||
// followingCount: this.followingCount,
|
// followingCount: this.followingCount,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
error(error) {
|
||||||
|
this.$toast.error(error.message)
|
||||||
|
},
|
||||||
fetchPolicy: 'cache-and-network',
|
fetchPolicy: 'cache-and-network',
|
||||||
},
|
},
|
||||||
GroupMembers: {
|
GroupMembers: {
|
||||||
query() {
|
query() {
|
||||||
return groupMembersQuery
|
return groupMembersQuery()
|
||||||
},
|
},
|
||||||
variables() {
|
variables() {
|
||||||
return {
|
return {
|
||||||
id: this.$route.params.id,
|
id: this.$route.params.id,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
skip() {
|
||||||
|
return !this.loadGroupMembers
|
||||||
|
},
|
||||||
|
error(error) {
|
||||||
|
this.$toast.error(error.message)
|
||||||
|
},
|
||||||
fetchPolicy: 'cache-and-network',
|
fetchPolicy: 'cache-and-network',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -547,4 +662,17 @@ export default {
|
|||||||
.chip {
|
.chip {
|
||||||
margin-bottom: $space-x-small;
|
margin-bottom: $space-x-small;
|
||||||
}
|
}
|
||||||
|
.group-description > .base-card {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
> .content {
|
||||||
|
flex-grow: 1;
|
||||||
|
margin-bottom: $space-small;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.collaps-button {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -41,7 +41,7 @@ export default {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await this.$apollo.mutate({
|
await this.$apollo.mutate({
|
||||||
mutation: createGroupMutation,
|
mutation: createGroupMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
this.$toast.success(this.$t('group.groupCreated'))
|
this.$toast.success(this.$t('group.groupCreated'))
|
||||||
|
|||||||
@ -56,7 +56,7 @@ export default {
|
|||||||
Group: [group],
|
Group: [group],
|
||||||
},
|
},
|
||||||
} = await client.query({
|
} = await client.query({
|
||||||
query: groupQuery,
|
query: groupQuery(), // "this.$i18n" is undefined here, so we use default lang
|
||||||
variables: { id },
|
variables: { id },
|
||||||
})
|
})
|
||||||
if (group.myRole !== 'owner') {
|
if (group.myRole !== 'owner') {
|
||||||
|
|||||||
@ -37,7 +37,7 @@ export default {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await this.$apollo.mutate({
|
await this.$apollo.mutate({
|
||||||
mutation: updateGroupMutation,
|
mutation: updateGroupMutation(),
|
||||||
variables,
|
variables,
|
||||||
})
|
})
|
||||||
this.$toast.success(this.$t('group.group-updated'))
|
this.$toast.success(this.$t('group.group-updated'))
|
||||||
|
|||||||
@ -28,7 +28,7 @@ export default {
|
|||||||
async groupMembersQueryList() {
|
async groupMembersQueryList() {
|
||||||
try {
|
try {
|
||||||
const response = await this.$apollo.query({
|
const response = await this.$apollo.query({
|
||||||
query: groupMembersQuery,
|
query: groupMembersQuery(),
|
||||||
variables: { id: this.group.id },
|
variables: { id: this.group.id },
|
||||||
})
|
})
|
||||||
this.responseGroupMembersQuery = response.data.GroupMembers
|
this.responseGroupMembersQuery = response.data.GroupMembers
|
||||||
|
|||||||
@ -38,7 +38,6 @@
|
|||||||
v-tooltip="{
|
v-tooltip="{
|
||||||
content: $t('contribution.newPost'),
|
content: $t('contribution.newPost'),
|
||||||
placement: 'left',
|
placement: 'left',
|
||||||
delay: { show: 500 },
|
|
||||||
}"
|
}"
|
||||||
class="post-add-button"
|
class="post-add-button"
|
||||||
icon="plus"
|
icon="plus"
|
||||||
|
|||||||
@ -40,11 +40,12 @@ export default {
|
|||||||
async groupListQuery() {
|
async groupListQuery() {
|
||||||
try {
|
try {
|
||||||
const response = await this.$apollo.query({
|
const response = await this.$apollo.query({
|
||||||
query: groupQuery,
|
query: groupQuery(this.$i18n),
|
||||||
})
|
})
|
||||||
this.responseGroupListQuery = response.data.Group
|
this.responseGroupListQuery = response.data.Group
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.responseGroupListQuery = []
|
this.responseGroupListQuery = []
|
||||||
|
this.$toast.error(error.message)
|
||||||
} finally {
|
} finally {
|
||||||
this.pending = false
|
this.pending = false
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,7 +46,6 @@
|
|||||||
<content-viewer class="content hyphenate-text" :content="post.content" />
|
<content-viewer class="content hyphenate-text" :content="post.content" />
|
||||||
<!-- Categories -->
|
<!-- Categories -->
|
||||||
<div v-if="categoriesActive" class="categories">
|
<div v-if="categoriesActive" class="categories">
|
||||||
<!-- eslint-enable vue/no-v-html -->
|
|
||||||
<ds-space margin="xx-large" />
|
<ds-space margin="xx-large" />
|
||||||
<ds-space margin="xx-small" />
|
<ds-space margin="xx-small" />
|
||||||
<hc-category
|
<hc-category
|
||||||
@ -57,7 +56,6 @@
|
|||||||
v-tooltip="{
|
v-tooltip="{
|
||||||
content: $t(`contribution.category.description.${category.slug}`),
|
content: $t(`contribution.category.description.${category.slug}`),
|
||||||
placement: 'bottom-start',
|
placement: 'bottom-start',
|
||||||
delay: { show: 1500 },
|
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -120,7 +120,6 @@
|
|||||||
v-tooltip="{
|
v-tooltip="{
|
||||||
content: $t('contribution.newPost'),
|
content: $t('contribution.newPost'),
|
||||||
placement: 'left',
|
placement: 'left',
|
||||||
delay: { show: 500 },
|
|
||||||
}"
|
}"
|
||||||
:path="{ name: 'post-create' }"
|
:path="{ name: 'post-create' }"
|
||||||
class="profile-post-add-button"
|
class="profile-post-add-button"
|
||||||
@ -238,7 +237,7 @@ export default {
|
|||||||
followedByCountStartValue: 0,
|
followedByCountStartValue: 0,
|
||||||
followedByCount: followListVisibleCount,
|
followedByCount: followListVisibleCount,
|
||||||
followingCount: followListVisibleCount,
|
followingCount: followListVisibleCount,
|
||||||
updateUserMutation: updateUserMutation(),
|
updateUserMutation,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|||||||
@ -25,6 +25,7 @@ import { VERSION } from '~/constants/terms-and-conditions-version.js'
|
|||||||
import { updateUserMutation } from '~/graphql/User.js'
|
import { updateUserMutation } from '~/graphql/User.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
name: 'TermsAndConditionsConfirm',
|
||||||
layout: 'default',
|
layout: 'default',
|
||||||
head() {
|
head() {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import VTooltip from 'v-tooltip'
|
|||||||
|
|
||||||
Vue.use(VTooltip, {
|
Vue.use(VTooltip, {
|
||||||
defaultDelay: {
|
defaultDelay: {
|
||||||
show: 500,
|
show: 1500,
|
||||||
hide: 50,
|
hide: 50,
|
||||||
},
|
},
|
||||||
defaultOffset: 2,
|
defaultOffset: 2,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user