Skip to content

Commit

Permalink
Merge pull request #868 from Hylozoic/861-post-collections
Browse files Browse the repository at this point in the history
Add support for post Collections
  • Loading branch information
tibetsprague authored Oct 11, 2022
2 parents f5837c7 + fc4e8ed commit e71b55c
Show file tree
Hide file tree
Showing 13 changed files with 482 additions and 18 deletions.
16 changes: 16 additions & 0 deletions api/graphql/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
addMember,
addModerator,
addPeopleToProjectRole,
addPostToCollection,
addSkill,
addSkillToLearn,
addSuggestedSkillToGroup,
Expand All @@ -18,6 +19,7 @@ import {
cancelGroupRelationshipInvite,
cancelJoinRequest,
createAffiliation,
createCollection,
createComment,
createGroup,
createInvitation,
Expand Down Expand Up @@ -65,9 +67,11 @@ import {
rejectGroupRelationshipInvite,
reactivateUser,
register,
reorderPostInCollection,
removeMember,
removeModerator,
removePost,
removePostFromCollection,
removeSkill,
removeSkillToLearn,
removeSuggestedSkillFromGroup,
Expand Down Expand Up @@ -190,6 +194,7 @@ export function makeAuthenticatedQueries (userId, fetchOne, fetchMany) {
activity: (root, { id }) => fetchOne('Activity', id),
checkInvitation: (root, { invitationToken, accessCode }) =>
InvitationService.check(invitationToken, accessCode),
collection: (root, { id }) => fetchOne('Collection', id),
comment: (root, { id }) => fetchOne('Comment', id),
connections: (root, args) => fetchMany('PersonConnection', args),
group: async (root, { id, slug, updateLastViewed }) => {
Expand Down Expand Up @@ -278,6 +283,9 @@ export function makeMutations (expressContext, userId, isAdmin, fetchOne) {
addPeopleToProjectRole: (root, { peopleIds, projectRoleId }) =>
addPeopleToProjectRole(userId, peopleIds, projectRoleId),

addPostToCollection: (root, { collectionId, postId }) =>
addPostToCollection(userId, collectionId, postId),

addSkill: (root, { name }) => addSkill(userId, name),
addSkillToLearn: (root, { name }) => addSkillToLearn(userId, name),
addSuggestedSkillToGroup: (root, { groupId, name }) => addSuggestedSkillToGroup(userId, groupId, name),
Expand All @@ -292,6 +300,8 @@ export function makeMutations (expressContext, userId, isAdmin, fetchOne) {

createAffiliation: (root, { data }) => createAffiliation(userId, data),

createCollection: (root, { data }) => createCollection(userId, data),

createComment: (root, { data }) => createComment(userId, data),

createGroup: (root, { data }) => createGroup(userId, data),
Expand Down Expand Up @@ -400,10 +410,16 @@ export function makeMutations (expressContext, userId, isAdmin, fetchOne) {
removePost: (root, { postId, groupId, slug }) =>
removePost(userId, postId, groupId || slug),

removePostFromCollection: (root, { collectionId, postId }) =>
removePostFromCollection(userId, collectionId, postId),

removeSkill: (root, { id, name }) => removeSkill(userId, id || name),
removeSkillToLearn: (root, { id, name }) => removeSkillToLearn(userId, id || name),
removeSuggestedSkillFromGroup: (root, { groupId, id, name }) => removeSuggestedSkillFromGroup(userId, groupId, id || name),

reorderPostInCollection: (root, { collectionId, postId, newOrderIndex }) =>
reorderPostInCollection(userId, collectionId, postId, newOrderIndex),

requestToAddGroupToParent: (root, { parentId, childId, questionAnswers }) =>
inviteGroupToGroup(userId, childId, parentId, GroupRelationshipInvite.TYPE.ChildToParent, questionAnswers),

Expand Down
75 changes: 66 additions & 9 deletions api/graphql/makeModels.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,34 @@ export default function makeModels (userId, isAdmin, apiClient) {
],
filter: postFilter(userId, isAdmin),
isDefaultTypeForTable: true,
fetchMany: ({ activePostsOnly = false, afterTime, beforeTime, boundingBox, context, filter, first, groupSlugs, isFulfilled, offset, order, sortBy, search, topic, topics, types }) =>
fetchMany: ({
activePostsOnly = false,
afterTime,
beforeTime,
boundingBox,
collectionToFilterOut,
context,
filter,
first,
forCollection,
groupSlugs,
isFulfilled,
offset,
order,
sortBy,
search,
topic,
topics,
types
}) =>
searchQuerySet('posts', {
activePostsOnly,
afterTime,
beforeTime,
boundingBox,
collectionToFilterOut,
currentUserId: userId,
forCollection,
groupSlugs,
isFulfilled,
limit: first,
Expand Down Expand Up @@ -266,12 +287,14 @@ export default function makeModels (userId, isAdmin, apiClient) {
{parentGroups: {querySet: true}},
{posts: {
querySet: true,
filter: (relation, { activePostsOnly = false, afterTime, beforeTime, boundingBox, filter, isAnnouncement, isFulfilled, order, search, sortBy, topic, topics, types }) =>
filter: (relation, { activePostsOnly = false, afterTime, beforeTime, boundingBox, collectionToFilterOut, forCollection, filter, isAnnouncement, isFulfilled, order, search, sortBy, topic, topics, types }) =>
relation.query(filterAndSortPosts({
activePostsOnly,
afterTime,
beforeTime,
boundingBox,
collectionToFilterOut,
forCollection,
isAnnouncement,
isFulfilled,
order,
Expand Down Expand Up @@ -310,12 +333,14 @@ export default function makeModels (userId, isAdmin, apiClient) {
{viewPosts: {
querySet: true,
arguments: () => [userId],
filter: (relation, { activePostsOnly = false, afterTime, beforeTime, boundingBox, filter, isFulfilled, order, search, sortBy, topic, topics, types }) =>
filter: (relation, { activePostsOnly = false, afterTime, beforeTime, boundingBox, collectionToFilterOut, filter, forCollection, isFulfilled, order, search, sortBy, topic, topics, types }) =>
relation.query(filterAndSortPosts({
activePostsOnly,
afterTime,
beforeTime,
boundingBox,
collectionToFilterOut,
forCollection,
isFulfilled,
order,
search,
Expand Down Expand Up @@ -457,23 +482,55 @@ export default function makeModels (userId, isAdmin, apiClient) {
CustomView: {
model: CustomView,
attributes: [
'active_posts_only',
'collection_id',
'default_sort',
'default_view_mode',
'external_link',
'group_id',
'is_active',
'search_text',
'icon',
'is_active',
'name',
'external_link',
'view_mode',
'active_posts_only',
'order',
'post_types',
'order'
'type',
'search_text',
],
relations: [
'collection',
'group',
{ tags: { alias: 'topics' } }
]
},

Collection: {
model: Collection,
attributes: [
'created_at',
'name',
'updated_at'
],
relations: [
'group',
{ linkedPosts: {querySet: true} },
{ posts: {querySet: true} },
'user'
]
},

CollectionsPost: {
model: CollectionsPost,
attributes: [
'created_at',
'order',
'updated_at'
],
relations: [
'post',
'user'
]
},

Invitation: {
model: Invitation,
attributes: [
Expand Down
73 changes: 73 additions & 0 deletions api/graphql/mutations/collection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { isEmpty, mapKeys, pick, snakeCase } from 'lodash'
const { GraphQLYogaError } = require('@graphql-yoga/node')

export async function addPostToCollection(userId, collectionId, postId) {
const collection = await Collection.findValidCollectionForUser(userId, collectionId)

// TODO: Validate that the post can be added to the collection
const post = await Post.find(postId)

if (!post) {
throw new GraphQLYogaError('Not a valid post')
}

const order = await CollectionsPost.query(q => {
q.select(bookshelf.knex.raw('max("order") as max_order'))
q.where({ collection_id: collectionId })
})
.fetch()
.then(result => result.get('max_order'))

await new CollectionsPost({ user_id: userId, collection_id: collectionId, post_id: post.id, order: order ? order + 1 : 0 }).save()

return { success: true }
}

export function createCollection(userId, data) {
const whitelist = mapKeys(pick(data, ['name', 'groupId']), (v, k) => snakeCase(k))
if (isEmpty(whitelist)) return Promise.resolve(null)
return Collection.create({ userId, ...data })
}

export async function removePostFromCollection(userId, collectionId, postId) {
const collection = await Collection.findValidCollectionForUser(userId, collectionId)

const linkedPost = await CollectionsPost.query(q => q.where({ collection_id: collectionId, post_id: postId })).fetch()

if (!linkedPost) {
throw new GraphQLYogaError('Not a valid post')
}

await linkedPost.destroy()

return { success: true }
}

export async function reorderPostInCollection(userId, collectionId, postId, newOrderIndex) {
const collection = await Collection.findValidCollectionForUser(userId, collectionId)
const linkedPost = await CollectionsPost.query(q => q.where({ collection_id: collectionId, post_id: postId })).fetch()

if (!linkedPost) {
throw new GraphQLYogaError('Not a valid post')
}

const oldOrder = linkedPost.get('order')

if (oldOrder > newOrderIndex) {
await CollectionsPost.query()
.where({ collection_id: collectionId })
.andWhere('order', '>=', newOrderIndex)
.andWhere('order', '<', oldOrder)
.update({ order: bookshelf.knex.raw('?? + 1', ['order']) })
} else if (oldOrder < newOrderIndex) {
await CollectionsPost.query()
.where({ collection_id: collectionId })
.andWhere('order', '<=', newOrderIndex)
.andWhere('order', '>', oldOrder)
.update({ order: bookshelf.knex.raw('?? - 1', ['order']) })
}

await linkedPost.save({ order: newOrderIndex })

return { success: true }
}
6 changes: 6 additions & 0 deletions api/graphql/mutations/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ export {
createAffiliation,
deleteAffiliation
} from './affiliation'
export {
createCollection,
addPostToCollection,
reorderPostInCollection,
removePostFromCollection
} from './collection'
export {
createComment,
createMessage,
Expand Down
Loading

0 comments on commit e71b55c

Please sign in to comment.