diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 9b298dc2..b9497962 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -7,6 +7,9 @@ - reaction filter by kinds - reaction sort enum added - community follower roles enum added +- invite status enum added +- topic parents ids added +- community CUDL resolvers added [0.4.4] - followers_stat removed for shout diff --git a/orm/community.py b/orm/community.py index 8f645eb1..3554715b 100644 --- a/orm/community.py +++ b/orm/community.py @@ -1,11 +1,12 @@ import enum import time -from sqlalchemy import ARRAY, Column, ForeignKey, Integer, String, func +from sqlalchemy import ARRAY, Column, ForeignKey, Integer, String, distinct, func from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.orm import relationship from orm.author import Author +from orm.shout import Shout from services.db import Base @@ -45,8 +46,7 @@ class Community(Base): desc = Column(String, nullable=False, default="") pic = Column(String, nullable=False, default="") created_at = Column(Integer, nullable=False, default=lambda: int(time.time())) - - authors = relationship(Author, secondary="community_author") + created_by = Column(ForeignKey("author.id"), nullable=False) @hybrid_property def stat(self): @@ -74,3 +74,15 @@ class CommunityStats: .filter(CommunityFollower.community == self.community.id) .scalar() ) + + @property + def authors(self): + # author has a shout with community id and featured_at is not null + return ( + self.community.session.query(func.count(distinct(Author.id))) + .join(Shout) + .filter( + Shout.community_id == self.community.id, Shout.featured_at.is_not(None), Author.id.in_(Shout.authors) + ) + .scalar() + ) diff --git a/resolvers/community.py b/resolvers/community.py index 6d633ec1..faeaa2dc 100644 --- a/resolvers/community.py +++ b/resolvers/community.py @@ -1,7 +1,7 @@ from orm.author import Author from orm.community import Community, CommunityFollower from services.db import local_session -from services.schema import query +from services.schema import mutation, query @query.field("get_communities_all") @@ -29,3 +29,69 @@ async def get_communities_by_author(_, _info, slug="", user="", author_id=0): q = q.where(CommunityFollower.author == author_id) return q.all() return [] + + +@mutation.field("join_community") +async def join_community(_, info, slug: str): + author_dict = info.context.get("author", {}) + author_id = author_dict.get("id") + with local_session() as session: + community = session.query(Community).where(Community.slug == slug).first() + if not community: + return {"ok": False, "error": "Community not found"} + session.add(CommunityFollower(community=community.id, author=author_id)) + session.commit() + return {"ok": True} + + +@mutation.field("leave_community") +async def leave_community(_, info, slug: str): + author_dict = info.context.get("author", {}) + author_id = author_dict.get("id") + with local_session() as session: + session.query(CommunityFollower).where( + CommunityFollower.author == author_id, CommunityFollower.community == slug + ).delete() + session.commit() + return {"ok": True} + + +@mutation.field("create_community") +async def create_community(_, info, community_data): + author_dict = info.context.get("author", {}) + author_id = author_dict.get("id") + with local_session() as session: + session.add(Community(author=author_id, **community_data)) + session.commit() + return {"ok": True} + + +@mutation.field("update_community") +async def update_community(_, info, community_data): + author_dict = info.context.get("author", {}) + author_id = author_dict.get("id") + slug = community_data.get("slug") + if slug: + with local_session() as session: + try: + session.query(Community).where(Community.created_by == author_id, Community.slug == slug).update( + community_data + ) + session.commit() + except Exception as e: + return {"ok": False, "error": str(e)} + return {"ok": True} + return {"ok": False, "error": "Please, set community slug in input"} + + +@mutation.field("delete_community") +async def delete_community(_, info, slug: str): + author_dict = info.context.get("author", {}) + author_id = author_dict.get("id") + with local_session() as session: + try: + session.query(Community).where(Community.slug == slug, Community.created_by == author_id).delete() + session.commit() + return {"ok": True} + except Exception as e: + return {"ok": False, "error": str(e)} diff --git a/schema/input.graphql b/schema/input.graphql index a794969d..34ae1399 100644 --- a/schema/input.graphql +++ b/schema/input.graphql @@ -85,3 +85,10 @@ input NotificationSeenInput { notifications: [Int] thread: Int } + +input CommunityInput { + slug: String + name: String + desc: String + pic: String +} diff --git a/schema/mutation.graphql b/schema/mutation.graphql index 4bb05c15..ed32f89b 100644 --- a/schema/mutation.graphql +++ b/schema/mutation.graphql @@ -36,4 +36,11 @@ type Mutation { notification_mark_seen(notification_id: Int!, seen: Boolean): CommonResult! notifications_seen_after(after: Int!, seen: Boolean): CommonResult! notifications_seen_thread(thread_id: String!, seen: Boolean): CommonResult! + + # community + join_community(slug: String!): CommonResult! + leave_community(slug: String!): CommonResult! + create_community(input: CommunityInput!): CommonResult! + update_community(input: CommunityInput!): CommonResult! + delete_community(slug: String!): CommonResult! } diff --git a/schema/type.graphql b/schema/type.graphql index 5bb56531..a8c75723 100644 --- a/schema/type.graphql +++ b/schema/type.graphql @@ -99,6 +99,12 @@ type Stat { last_reacted_at: Int } +type CommunityStat { + shouts: Int! + followers: Int! + authors: Int! +} + type Community { id: Int! slug: String! @@ -107,6 +113,7 @@ type Community { pic: String! created_at: Int! created_by: Author! + stat: CommunityStat } type Collection {