diff --git a/orm/collab.py b/orm/collab.py deleted file mode 100644 index aa71004c..00000000 --- a/orm/collab.py +++ /dev/null @@ -1,27 +0,0 @@ -from datetime import datetime - -from sqlalchemy import Column, ForeignKey, DateTime, String -from sqlalchemy.orm import relationship -from base.orm import Base -from orm.user import User - - -class CollabAuthor(Base): - __tablename__ = "collab_author" - - id = None # type: ignore - collab = Column(ForeignKey("collab.id"), primary_key=True) - author = Column(ForeignKey("user.id"), primary_key=True) - # accepted = Column(Boolean, default=False) - - -class Collab(Base): - __tablename__ = "collab" - - title = Column(String, nullable=True, comment="Title") - body = Column(String, nullable=True, comment="Body") - pic = Column(String, nullable=True, comment="Picture") - authors = relationship(lambda: User, secondary=CollabAuthor.__tablename__) - # invites = relationship(lambda: User, secondary=CollabInvited.__tablename__) - createdAt = Column(DateTime, default=datetime.now, comment="Created At") - chat = Column(String, unique=True, nullable=False) diff --git a/orm/draft.py b/orm/draft.py new file mode 100644 index 00000000..87ee3a8a --- /dev/null +++ b/orm/draft.py @@ -0,0 +1,32 @@ +from datetime import datetime + +from sqlalchemy import Column, ForeignKey, DateTime, String +from sqlalchemy.orm import relationship +from base.orm import Base +from orm.user import User + + +class DraftAuthor(Base): + __tablename__ = "collab_author" + + id = None # type: ignore + collab = Column(ForeignKey("collab.id"), primary_key=True) + author = Column(ForeignKey("user.id"), primary_key=True) + # accepted = Column(Boolean, default=False) + + +class DraftCollab(Base): + __tablename__ = "draftcollab" + + slug = Column(String, nullable=True, comment="Slug") + title = Column(String, nullable=True, comment="Title") + subtitle = Column(String, nullable=True, comment="Subtitle") + layout = Column(String, nullable=True, comment="Layout format") + body = Column(String, nullable=True, comment="Body") + cover = Column(String, nullable=True, comment="Cover") + authors = relationship(lambda: User, secondary=DraftAuthor.__tablename__) + topics = relationship(lambda: Topic, secondary=ShoutTopic.__tablename__) + invites = relationship(lambda: User, secondary=CollabInvited.__tablename__) + createdAt = Column(DateTime, default=datetime.now, comment="Created At") + updatedAt = Column(DateTime, default=datetime.now, comment="Updated At") + chat = Column(String, unique=True, nullable=True) diff --git a/orm/shout.py b/orm/shout.py index 55435d5f..04b0102b 100644 --- a/orm/shout.py +++ b/orm/shout.py @@ -50,7 +50,7 @@ class Shout(Base): subtitle = Column(String, nullable=True) layout = Column(String, nullable=True) mainTopic = Column(ForeignKey("topic.slug"), nullable=True) - cover = Column(String, nullable=True) + cover = Column(String, nullable=True, comment="Cover") authors = relationship(lambda: User, secondary=ShoutAuthor.__tablename__) topics = relationship(lambda: Topic, secondary=ShoutTopic.__tablename__) reactions = relationship(lambda: Reaction) diff --git a/resolvers/create/collab.py b/resolvers/create/collab.py index c51c9be2..74356a29 100644 --- a/resolvers/create/collab.py +++ b/resolvers/create/collab.py @@ -3,56 +3,62 @@ from auth.credentials import AuthCredentials from base.orm import local_session from base.resolvers import query, mutation from base.exceptions import ObjectNotExist, BaseHttpException -from orm.collab import Collab, CollabAuthor +from orm.draft import DraftCollab, CollabAuthor from orm.shout import Shout from orm.user import User -@query.field("getCollabs") +# TODO: use updatedAt + + +@query.field("loadDrafts") @login_required -async def get_collabs(_, info): +async def get_drafts(_, info): + auth: AuthCredentials = info.context["request"].auth + drafts = [] + with local_session() as session: + drafts = session.query(DraftCollab).filter(auth.user_id in DraftCollab.authors) + return { + "drafts": drafts + } + + +@mutation.field("createDraft") # TODO +@login_required +async def create_draft(_, info): auth: AuthCredentials = info.context["request"].auth with local_session() as session: - collabs = session.query(Collab).filter(auth.user_id in Collab.authors) - return collabs + pass -@mutation.field("inviteCoauthor") +@mutation.field("deleteDraft") # TODO @login_required -async def invite_coauthor(_, info, author: int = 0, shout: int = 0): +async def delete_draft(_, info, draft: int = 0): auth: AuthCredentials = info.context["request"].auth with local_session() as session: - s = session.query(Shout).where(Shout.id == shout).one() - if not s: - raise ObjectNotExist("invalid shout id") - else: - c = session.query(Collab).where(Collab.shout == shout).one() - if auth.user_id not in c.authors: - raise BaseHttpException("you are not in authors list") - else: - invited_user = session.query(User).where(User.id == author).one() - c.invites.append(invited_user) - session.add(c) - session.commit() + pass - # TODO: email notify - return {} - - -@mutation.field("removeCoauthor") +@mutation.field("updateDraft") # TODO @login_required -async def remove_coauthor(_, info, author: int = 0, shout: int = 0): +async def update_draft(_, info, author: int = 0, draft: int = 0): auth: AuthCredentials = info.context["request"].auth with local_session() as session: - s = session.query(Shout).where(Shout.id == shout).one() # raises Error when not found + s = session.query(DraftCollab).where(DraftCollab.id == draft).one() # raises Error when not found if auth.user_id not in s.authors: - raise BaseHttpException("only owner can remove coauthors") + # raise BaseHttpException("only owner can remove coauthors") + return { + "error": "Only authors can update draft" + } + elif not s: + return { + "error": "There is no draft with this id" + } else: - c = session.query(Collab).where(Collab.shout == shout).one() - ca = session.query(CollabAuthor).join(User).where(c.shout == shout, User.id == author).one() + c = session.query(DraftCollab).where(DraftCollab.id == draft).one() + ca = session.query(CollabAuthor).join(User).where(c.id == draft).filter(User.id == author).one() session.remve(ca) c.invites = filter(lambda x: x.id == author, c.invites) c.authors = filter(lambda x: x.id == author, c.authors) @@ -62,25 +68,43 @@ async def remove_coauthor(_, info, author: int = 0, shout: int = 0): # TODO: email notify return {} - -@mutation.field("acceptCoauthor") +@mutation.field("inviteAuthor") @login_required -async def accept_coauthor(_, info, shout: int): +async def invite_coauthor(_, info, author: int = 0, draft: int = 0): auth: AuthCredentials = info.context["request"].auth with local_session() as session: - s = session.query(Shout).where(Shout.id == shout).one() - if not s: - raise ObjectNotExist("invalid shout id") + c = session.query(DraftCollab).where(DraftCollab.id == draft).one() + if auth.user_id not in c.authors: + # raise BaseHttpException("you are not in authors list") + return { + "error": "You are not in authors list" + } else: - c = session.query(Collab).where(Collab.shout == shout).one() - accepted = filter(lambda x: x.id == auth.user_id, c.invites).pop() - if accepted: - c.authors.append(accepted) - s.authors.append(accepted) - session.add(s) - session.add(c) - session.commit() - return {} - else: - raise BaseHttpException("only invited can accept") + invited_user = session.query(User).where(User.id == author).one() + c.invites.append(invited_user) + session.add(c) + session.commit() + + # TODO: email notify + return {} + + +@mutation.field("inviteAccept") +@login_required +async def accept_coauthor(_, info, draft: int): + auth: AuthCredentials = info.context["request"].auth + + with local_session() as session: + c = session.query(DraftCollab).where(DraftCollab.id == draft).one() + accepted = filter(lambda x: x.id == auth.user_id, c.invites).pop() + if accepted: + c.authors.append(accepted) + session.add(c) + session.commit() + return {} + else: + # raise BaseHttpException("only invited can accept") + return { + "error": "You don't have an invitation yet" + } diff --git a/schema.graphql b/schema.graphql index 015f2b02..8c23a618 100644 --- a/schema.graphql +++ b/schema.graphql @@ -128,6 +128,17 @@ input TopicInput { # parents: [String] } +input DraftInput { + slug: String + topics: [Int] + authors: [Int] + title: String + subtitle: String + body: String + cover: String + +} + input ReactionInput { kind: ReactionKind! shout: Int! @@ -189,10 +200,12 @@ type Mutation { updateReaction(reaction: ReactionInput!): Result! deleteReaction(reaction: Int!): Result! - # collab - inviteCoauthor(author: String!, shout: Int!): Result! - removeCoauthor(author: String!, shout: Int!): Result! - acceptCoauthor(shout: Int!): Result! + # draft / collab + createDraft(draft: DraftInput!): Result! + updateDraft(draft: DraftInput!): Result! + deleteDraft(draft: Int!): Result! + inviteAccept(draft: Int!): Result! + inviteAuthor(draft: Int!, author: Int!): Result! # following follow(what: FollowingEntity!, slug: String!): Result! @@ -289,8 +302,8 @@ type Query { authorsAll: [Author]! getAuthor(slug: String!): User - # collab - getCollabs: [Collab]! + # draft/collab + loadDrafts: [DraftCollab]! # migrate markdownBody(body: String!): String!