Merge branch 'drafts' into following
This commit is contained in:
commit
c50aa27cf0
|
@ -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):
|
||||
|
|
40
orm/shout.py
40
orm/shout.py
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
@ -18,11 +21,11 @@ async def load_drafts(_, info):
|
|||
return drafts
|
||||
|
||||
|
||||
@mutation.field("createDraft") # TODO
|
||||
@mutation.field("createDraft") # TODO
|
||||
@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,52 +35,56 @@ 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 {}
|
||||
|
||||
|
||||
@mutation.field("updateDraft") # TODO: draft input type
|
||||
@mutation.field("updateDraft") # TODO: draft input type
|
||||
@login_required
|
||||
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,25 +115,75 @@ 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()
|
||||
if not a.accepted:
|
||||
a.accepted = True
|
||||
session.commit()
|
||||
# TODO: email notify
|
||||
return {}
|
||||
elif a.accepted == True:
|
||||
d = session.query(DraftCollab).where(DraftCollab.id == draft).one()
|
||||
if not d:
|
||||
return {
|
||||
"error": "You have accepted invite before"
|
||||
"error": "Draft id was not found"
|
||||
}
|
||||
else:
|
||||
# raise BaseHttpException("only invited can accept")
|
||||
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:
|
||||
return {
|
||||
"error": "You have accepted invite before"
|
||||
}
|
||||
else:
|
||||
# raise BaseHttpException("only invited can accept")
|
||||
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 don't have an invitation yet"
|
||||
"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 {}
|
|
@ -145,8 +145,14 @@ def topic_unfollow(user_id, slug):
|
|||
@query.field("topicsRandom")
|
||||
async def topics_random(_, info, amount=12):
|
||||
q = select(Topic)
|
||||
q = add_topic_stat_columns(q)
|
||||
q = q.join(ShoutTopic)
|
||||
q = q.group_by(Topic.id)
|
||||
q = q.having(func.count(distinct(ShoutTopic.shout)) > 2)
|
||||
q = q.order_by(func.random()).limit(amount)
|
||||
|
||||
return get_topics_from_query(q)
|
||||
topics = []
|
||||
with local_session() as session:
|
||||
for [topic] in session.execute(q):
|
||||
topics.append(topic)
|
||||
|
||||
return topics
|
||||
|
|
Loading…
Reference in New Issue
Block a user