diff --git a/resolvers/editor.py b/resolvers/editor.py index f44e6534..4e19cddd 100644 --- a/resolvers/editor.py +++ b/resolvers/editor.py @@ -1,4 +1,4 @@ -import time # For Unix timestamps +import time from sqlalchemy import and_, select from sqlalchemy.orm import joinedload @@ -27,16 +27,13 @@ async def get_shouts_drafts(_, info): q = ( select(Shout) .options( - # joinedload(Shout.created_by, Author.id == Shout.created_by), joinedload(Shout.authors), joinedload(Shout.topics), ) .filter(and_(Shout.deleted_at.is_(None), Shout.created_by == author.id)) + .group_by(Shout.id) ) - q = q.group_by(Shout.id) - shouts = [] - for [shout] in session.execute(q).unique(): - shouts.append(shout) + shouts = [shout for [shout] in session.execute(q).unique()] return shouts @@ -46,7 +43,6 @@ async def create_shout(_, info, inp): user_id = info.context['user_id'] with local_session() as session: author = session.query(Author).filter(Author.user == user_id).first() - shout_dict = None if author: current_time = int(time.time()) slug = inp.get('slug') or f'draft-{current_time}' @@ -85,14 +81,15 @@ async def create_shout(_, info, inp): # notifier await notify_shout(shout_dict, 'create') - return {'shout': shout_dict} + + return {'shout': shout_dict} + + return {'error': 'cant create shout'} @mutation.field('update_shout') @login_required -async def update_shout( # noqa: C901 - _, info, shout_id, shout_input=None, publish=False -): +async def update_shout(_, info, shout_id, shout_input=None, publish=False): user_id = info.context['user_id'] with local_session() as session: author = session.query(Author).filter(Author.user == user_id).first() @@ -102,7 +99,6 @@ async def update_shout( # noqa: C901 shout = ( session.query(Shout) .options( - # joinedload(Shout.created_by, Author.id == Shout.created_by), joinedload(Shout.authors), joinedload(Shout.topics), ) @@ -116,43 +112,40 @@ async def update_shout( # noqa: C901 if shout_input is not None: topics_input = shout_input['topics'] del shout_input['topics'] - new_topics_to_link = [] - new_topics = [topic_input for topic_input in topics_input if topic_input['id'] < 0] - for new_topic in new_topics: - del new_topic['id'] - created_new_topic = Topic(**new_topic) - session.add(created_new_topic) - new_topics_to_link.append(created_new_topic) - if len(new_topics) > 0: + new_topics_to_link = [Topic(**new_topic) for new_topic in topics_input if new_topic['id'] < 0] + if new_topics_to_link: + session.add_all(new_topics_to_link) session.commit() + for new_topic_to_link in new_topics_to_link: created_unlinked_topic = ShoutTopic(shout=shout.id, topic=new_topic_to_link.id) session.add(created_unlinked_topic) + existing_topics_input = [topic_input for topic_input in topics_input if topic_input.get('id', 0) > 0] existing_topic_to_link_ids = [ existing_topic_input['id'] for existing_topic_input in existing_topics_input if existing_topic_input['id'] not in [topic.id for topic in shout.topics] ] + for existing_topic_to_link_id in existing_topic_to_link_ids: created_unlinked_topic = ShoutTopic(shout=shout.id, topic=existing_topic_to_link_id) session.add(created_unlinked_topic) + topic_to_unlink_ids = [ topic.id for topic in shout.topics if topic.id not in [topic_input['id'] for topic_input in existing_topics_input] ] - shout_topics_to_remove = session.query(ShoutTopic).filter( + + session.query(ShoutTopic).filter( and_( ShoutTopic.shout == shout.id, ShoutTopic.topic.in_(topic_to_unlink_ids), ) - ) - for shout_topic_to_remove in shout_topics_to_remove: - session.delete(shout_topic_to_remove) + ).delete(synchronize_session=False) - # Replace datetime with Unix timestamp - shout_input['updated_at'] = current_time # Set updated_at as Unix timestamp + shout_input['updated_at'] = current_time shout_input['published_at'] = current_time if publish else None Shout.update(shout, shout_input) session.add(shout) @@ -161,11 +154,18 @@ async def update_shout( # noqa: C901 if 'main_topic' in shout_input: old_main_topic = ( session.query(ShoutTopic) - .filter(and_(ShoutTopic.shout == shout.id, ShoutTopic.main == True)) + .filter( + and_( + ShoutTopic.shout == shout.id, + ShoutTopic.main == True, + ) + ) .first() ) + main_topic = session.query(Topic).filter(Topic.slug == shout_input['main_topic']).first() - if isinstance(main_topic, Topic): + + if main_topic: new_main_topic = ( session.query(ShoutTopic) .filter( @@ -176,13 +176,11 @@ async def update_shout( # noqa: C901 ) .first() ) - if ( - isinstance(old_main_topic, ShoutTopic) - and isinstance(new_main_topic, ShoutTopic) - and old_main_topic is not new_main_topic - ): + + if old_main_topic and new_main_topic and old_main_topic is not new_main_topic: ShoutTopic.update(old_main_topic, {'main': False}) session.add(old_main_topic) + ShoutTopic.update(new_main_topic, {'main': True}) session.add(new_main_topic) @@ -208,10 +206,10 @@ async def delete_shout(_, info, shout_id): shout = session.query(Shout).filter(Shout.id == shout_id).first() if not shout: return {'error': 'invalid shout id'} - if isinstance(author, Author) and isinstance(shout, Shout): - # TODO: add editor role allowed here + if author and shout: if shout.created_by is not author.id and author.id not in shout.authors: return {'error': 'access denied'} + for author_id in shout.authors: reactions_unfollow(author_id, shout_id) @@ -221,20 +219,27 @@ async def delete_shout(_, info, shout_id): session.add(shout) session.commit() await notify_shout(shout_dict, 'delete') + return {} def handle_proposing(session, r, shout): if is_positive(r.kind): - # Proposal accepting logic - replied_reaction = session.query(Reaction).filter(Reaction.id == r.reply_to).first() + replied_reaction = session.query(Reaction).filter(Reaction.id == r.reply_to, Reaction.shout == r.shout).first() + if replied_reaction and replied_reaction.kind is ReactionKind.PROPOSE.value and replied_reaction.quote: # patch all the proposals' quotes proposals = ( session.query(Reaction) - .filter(and_(Reaction.shout == r.shout, Reaction.kind == ReactionKind.PROPOSE.value)) + .filter( + and_( + Reaction.shout == r.shout, + Reaction.kind == ReactionKind.PROPOSE.value, + ) + ) .all() ) + for proposal in proposals: if proposal.quote: proposal_diff = get_diff(shout.body, proposal.quote)