diff --git a/api/graphql/index.js b/api/graphql/index.js index a89e8a52a..0cedc6b1f 100644 --- a/api/graphql/index.js +++ b/api/graphql/index.js @@ -165,6 +165,7 @@ export function makeAuthenticatedQueries (userId, fetchOne, fetchMany) { groupTopic: (root, { topicName, groupSlug }) => GroupTag.findByTagAndGroup(topicName, groupSlug), groupTopics: (root, args) => fetchMany('GroupTopic', args), + groupTemplates: (root, args) => GroupTemplate.fetchAll(), groups: (root, args) => fetchMany('Group', args), joinRequests: (root, args) => fetchMany('JoinRequest', args), me: () => fetchOne('Me', userId), diff --git a/api/graphql/makeModels.js b/api/graphql/makeModels.js index 53a69f00c..47f7163c7 100644 --- a/api/graphql/makeModels.js +++ b/api/graphql/makeModels.js @@ -339,6 +339,19 @@ export default async function makeModels (userId, isAdmin) { }) }, + GroupTemplate: { + model: GroupTemplate, + attributes: [ + 'name', + 'display_name' + ], + relations: [ + 'groups', + 'defaultTopics' + ], + fetchMany: () => GroupTemplate + }, + GroupJoinQuestion: { model: GroupJoinQuestion, attributes: [ diff --git a/api/graphql/schema.graphql b/api/graphql/schema.graphql index df1d192bc..ac65a05e4 100644 --- a/api/graphql/schema.graphql +++ b/api/graphql/schema.graphql @@ -54,6 +54,19 @@ type UserSettings { streamPostType: String } +type GroupTemplate { + id: ID + name: String + displayName: String + groups: GroupQuerySet + groupsTotal: Int + defaultTopics: [Topic] + defaultTopicsTotal: Int + newPostCount: Int + updatedAt: String + createdAt: String +} + type GroupTopicQuerySet { total: Int hasMore: Boolean @@ -608,6 +621,7 @@ type Query { sortBy: String, visibility: Int ): GroupQuerySet + groupTemplates: [GroupTemplate] joinRequests(groupId: ID, status: Int): JoinRequestQuerySet messageThread(id: ID): MessageThread post(id: ID): Post @@ -804,6 +818,7 @@ input GroupInput { avatarUrl: String bannerUrl: String description: String + groupTemplateId: ID groupToGroupJoinQuestions: [QuestionInput] joinQuestions: [QuestionInput] location: String diff --git a/api/models/Community.js b/api/models/Community.js index 713d8a6c4..39a32a73f 100644 --- a/api/models/Community.js +++ b/api/models/Community.js @@ -304,7 +304,7 @@ module.exports = bookshelf.Model.extend(merge({ async create (userId, data) { var attrs = defaults( pick(data, - 'name', 'description', 'slug', 'category', + 'name', 'description', 'slug', 'category', 'community_template_id', 'beta_access_code', 'banner_url', 'avatar_url', 'location_id', 'location', 'network_id'), {'banner_url': DEFAULT_BANNER, 'avatar_url': DEFAULT_AVATAR}) @@ -322,6 +322,18 @@ module.exports = bookshelf.Model.extend(merge({ const memberships = await bookshelf.transaction(async trx => { await community.save(null, {transacting: trx}) await community.createStarterPosts(trx) + if (data.default_topics) { + data.default_topics.forEach(async name => { + const topic = await Tag.findOrCreate(name, {transacting: trx}) + await Tag.addToCommunity({ + community_id: community.id, + tag_id: topic.id, + user_id: userId, + is_default: true, + isSubscribing: true + }, {transacting: trx}) + }) + } return community.addGroupMembers([userId], {role: GroupMembership.Role.MODERATOR}, {transacting: trx}) }) diff --git a/api/models/CommunityTemplate.js b/api/models/CommunityTemplate.js new file mode 100644 index 000000000..6abf7ae53 --- /dev/null +++ b/api/models/CommunityTemplate.js @@ -0,0 +1,18 @@ +import { includes } from 'lodash' + +var knex = bookshelf.knex + +module.exports = bookshelf.Model.extend({ + tableName: 'community_templates', + + communities: function () { + return this.hasMany(Community).query({where: {'communities.active': true}}) + }, + + defaultTopics: function () { + return this.belongsToMany(Tag, 'community_template_default_topics', 'community_template_id', 'tag_id') + }, + +}, { + +}) diff --git a/api/models/Tag.js b/api/models/Tag.js index 658bc45ad..9833bbfe8 100644 --- a/api/models/Tag.js +++ b/api/models/Tag.js @@ -88,6 +88,10 @@ module.exports = bookshelf.Model.extend({ return this.hasMany(GroupTag) }, + groupTemplates: function () { + return this.belongsToMany(GroupTemplate, 'group_templates_default_tags', 'tag_id', 'group_template_id') + }, + posts: function () { return this.belongsToMany(Post).through(PostTag).withPivot('selected') }, diff --git a/migrations/20200722214505_add_community_templates_table.js b/migrations/20200722214505_add_community_templates_table.js new file mode 100644 index 000000000..2776dd950 --- /dev/null +++ b/migrations/20200722214505_add_community_templates_table.js @@ -0,0 +1,36 @@ +exports.up = async function(knex, Promise) { + await knex.schema.createTable('community_templates', table => { + table.increments().primary() + + table.string('name') + table.string('display_name') + table.index(['name']) + + table.timestamp('created_at') + table.timestamp('updated_at') + }) + + await knex.schema.createTable('community_template_default_topics', table => { + table.increments().primary() + + table.bigInteger('community_template_id').references('id').inTable('community_templates') + table.bigInteger('tag_id').references('id').inTable('tags') + table.index(['community_template_id']) + + table.timestamp('created_at') + table.timestamp('updated_at') + }) + + return knex.schema.table('communities', table => { + table.bigInteger('community_template_id').references('id').inTable('community_templates') + }) +}; + +exports.down = async function(knex, Promise) { + await knex.schema.dropTable('community_templates') + await knex.schema.dropTable('community_template_default_topics') + + return knex.schema.table('communities', table => { + table.dropColumn('community_template_id') + }) +}; \ No newline at end of file diff --git a/package.json b/package.json index ef62ff2b6..01b77314e 100644 --- a/package.json +++ b/package.json @@ -186,6 +186,7 @@ "GroupRelationship", "GroupRelationshipInvite", "GroupTag", + "GroupTemplate", "Invitation", "JoinRequest", "LinkedAccount",