draft2shout

This commit is contained in:
tonyrewin 2023-02-17 17:30:38 +03:00
parent 542f9e4250
commit 2b91f5a529
4 changed files with 109 additions and 44 deletions

View File

@ -13,6 +13,7 @@ class DraftTopic(Base):
id = None # type: ignore
collab = Column(ForeignKey("draft_collab.id"), primary_key=True)
topic = Column(ForeignKey("topic.id"), primary_key=True)
main = Column(Boolean, default=False)
class DraftAuthor(Base):

View File

@ -15,6 +15,7 @@ class ShoutTopic(Base):
id = None # type: ignore
shout = Column(ForeignKey("shout.id"), primary_key=True, index=True)
topic = Column(ForeignKey("topic.id"), primary_key=True, index=True)
main = Column(Boolean, default=False)
class ShoutReactionsFollower(Base):
@ -42,28 +43,33 @@ class ShoutAuthor(Base):
class Shout(Base):
__tablename__ = "shout"
slug = Column(String, unique=True)
community = Column(ForeignKey("community.id"), default=1)
lang = Column(String, nullable=False, default='ru', comment="Language")
body = Column(String, nullable=False, comment="Body")
title = Column(String, nullable=True)
subtitle = Column(String, nullable=True)
layout = Column(String, nullable=True)
mainTopic = Column(ForeignKey("topic.slug"), 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)
visibility = Column(String, nullable=True) # owner authors community public
versionOf = Column(ForeignKey("shout.id"), nullable=True)
oid = Column(String, nullable=True)
media = Column(JSON, nullable=True)
# timestamps
createdAt = Column(DateTime, nullable=False, default=datetime.now, comment="Created at")
updatedAt = Column(DateTime, nullable=True, comment="Updated at")
publishedAt = Column(DateTime, nullable=True)
deletedAt = Column(DateTime, nullable=True)
# same with Draft
slug = Column(String, unique=True)
cover = Column(String, nullable=True, comment="Cover")
body = Column(String, nullable=False, comment="Body")
title = Column(String, nullable=True)
subtitle = Column(String, nullable=True)
layout = Column(String, nullable=True)
media = Column(JSON, nullable=True)
authors = relationship(lambda: User, secondary=ShoutAuthor.__tablename__)
topics = relationship(lambda: Topic, secondary=ShoutTopic.__tablename__)
reactions = relationship(lambda: Reaction)
# TODO: these field should be used or modified
community = Column(ForeignKey("community.id"), default=1)
lang = Column(String, nullable=False, default='ru', comment="Language")
mainTopic = Column(ForeignKey("topic.slug"), nullable=True)
visibility = Column(String, nullable=True) # owner authors community public
versionOf = Column(ForeignKey("shout.id"), nullable=True)
oid = Column(String, nullable=True)
@staticmethod
def init_table():
with local_session() as session:

View File

@ -6,7 +6,7 @@ from urllib.parse import quote_plus
from graphql.type import GraphQLResolveInfo
from starlette.responses import RedirectResponse
from transliterate import translit
import re
from auth.authenticate import login_required
from auth.credentials import AuthCredentials
from auth.email import send_auth_email
@ -92,6 +92,7 @@ def create_user(user_dict):
def generate_unique_slug(src):
print('[resolvers.auth] generating slug from: ' + src)
slug = translit(src, "ru", reversed=True).replace(".", "-").lower()
slug = re.sub('[^0-9a-zA-Z]+', '-', slug)
if slug != src:
print('[resolvers.auth] translited name: ' + slug)
c = 1

View File

@ -2,10 +2,13 @@ from auth.authenticate import login_required
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.draft import DraftCollab, DraftAuthor, DraftTopic
from orm.draft import DraftCollab, DraftAuthor
from orm.shout import Shout
from orm.topic import Topic
from orm.user import User
from datetime import datetime, timezone
from transliterate import translit
import re
@query.field("loadDrafts")
@ -22,7 +25,7 @@ async def load_drafts(_, info):
@login_required
async def create_draft(_, info, draft_input):
auth: AuthCredentials = info.context["request"].auth
draft_input['createdBy'] = auth.user_id
with local_session() as session:
collab = DraftCollab.create(**draft_input)
session.add(collab)
@ -32,24 +35,23 @@ async def create_draft(_, info, draft_input):
return {}
@mutation.field("deleteDraft") # TODO
@mutation.field("deleteDraft")
@login_required
async def delete_draft(_, info, draft: int = 0):
auth: AuthCredentials = info.context["request"].auth
with local_session() as session:
collab = session.query(DraftCollab).where(DraftCollab.id == draft_input.id).one()
if auth.user_id not in s.authors:
d = session.query(DraftCollab).where(DraftCollab.id == draft).one()
if auth.user_id not in d.authors:
# raise BaseHttpException("only owner can remove coauthors")
return {
"error": "Only authors can update a draft"
}
elif not collab:
elif not d:
return {
"error": "There is no draft with this id"
}
else:
session.delete(collab)
session.delete(d)
session.commit()
return {}
@ -60,24 +62,29 @@ async def update_draft(_, info, draft_input):
auth: AuthCredentials = info.context["request"].auth
with local_session() as session:
collab = session.query(DraftCollab).where(DraftCollab.id == draft_input.id).one() # raises Error when not found
if auth.user_id not in s.authors:
d = session.query(
DraftCollab
).where(
DraftCollab.id == draft_input.id
).one() # raises Error when not found
if auth.user_id not in d.authors:
# raise BaseHttpException("only owner can remove coauthors")
return {
"error": "Only authors can update draft"
}
elif not s:
elif not d:
return {
"error": "There is no draft with this id"
}
else:
draft_input["updatedAt"] = datetime.now(tz=timezone.utc)
collab.update(draft_input)
d.update(draft_input)
session.commit()
# TODO: email notify
return {}
@mutation.field("inviteAuthor")
@login_required
async def invite_coauthor(_, info, author: int = 0, draft: int = 0):
@ -108,20 +115,32 @@ async def invite_coauthor(_, info, author: int = 0, draft: int = 0):
return {}
def get_slug(src):
slug = translit(src, "ru", reversed=True).replace(".", "-").lower()
slug = re.sub('[^0-9a-zA-Z]+', '-', slug)
return slug
@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()
a = session.query(DraftAuthor).where(DraftAuthor.collab == draft).filter(DraftAuthor.author == auth.user_id).one()
d = session.query(DraftCollab).where(DraftCollab.id == draft).one()
if not d:
return {
"error": "Draft id was not found"
}
else:
a = session.query(DraftAuthor).where(DraftAuthor.collab == draft).filter(
DraftAuthor.author == auth.user_id).one()
if not a.accepted:
a.accepted = True
session.commit()
# TODO: email notify
return {}
elif a.accepted == True:
elif a.accepted:
return {
"error": "You have accepted invite before"
}
@ -130,3 +149,41 @@ async def accept_coauthor(_, info, draft: int):
return {
"error": "You don't have an invitation yet"
}
@mutation.field("draftToShout")
@login_required
async def draft_to_shout(_, info, draft: int = 0):
auth: AuthCredentials = info.context["request"].auth
with local_session() as session:
d = session.query(DraftCollab).where(DraftCollab.id == draft).one()
if auth.user_id not in d.authors:
# raise BaseHttpException("you are not in authors list")
return {
"error": "You are not in authors list"
}
elif d.id:
draft_authors = [a.author for a in d.authors]
draft_topics = [t.topic for t in d.topics]
authors = session.query(User).where(User.id._in(draft_authors)).all()
topics = session.query(Topic).where(Topic.id._in(draft_topics)).all()
new_shout = Shout.create({
"authors": authors,
"body": d.body,
"title": d.title,
"subtitle": d.subtitle or "",
"topics": topics,
"media": d.media,
"slug": d.slug or get_slug(d.title),
"layout": d.layout or "article"
})
session.add(new_shout)
session.commit()
else:
return {
"error": "Draft is not found"
}
# TODO: email notify
return {}