diff --git a/resolvers/zine/load.py b/resolvers/zine/load.py index c5f04d6e..2cbe20d6 100644 --- a/resolvers/zine/load.py +++ b/resolvers/zine/load.py @@ -22,6 +22,7 @@ from orm import TopicFollower from orm.reaction import Reaction, ReactionKind from orm.shout import Shout, ShoutAuthor, ShoutTopic from orm.user import AuthorFollower +from resolvers.zine.topics import get_random_topic def get_shouts_from_query(q): @@ -79,7 +80,8 @@ def add_stat_columns(q): return q -def apply_filters(q, filters, user_id=None): # noqa: C901 +# use_published_date is a quick fix, will be reworked as a part of tech debt +def apply_filters(q, filters, user_id=None, use_published_date=False): # noqa: C901 if filters.get("reacted") and user_id: q.join(Reaction, Reaction.createdBy == user_id) @@ -100,12 +102,17 @@ def apply_filters(q, filters, user_id=None): # noqa: C901 if filters.get("fromDate"): # fromDate: '2022-12-31 date_from = datetime.strptime(filters.get("fromDate"), "%Y-%m-%d") - q = q.filter(Shout.createdAt >= date_from) + if use_published_date: + q = q.filter(Shout.publishedAt >= date_from) + else: + q = q.filter(Shout.createdAt >= date_from) if filters.get("toDate"): # toDate: '2023-12-31' date_to = datetime.strptime(filters.get("toDate"), "%Y-%m-%d") - q = q.filter(Shout.createdAt < (date_to + timedelta(days=1))) - + if use_published_date: + q = q.filter(Shout.publishedAt < (date_to + timedelta(days=1))) + else: + q = q.filter(Shout.createdAt < (date_to + timedelta(days=1))) return q @@ -228,7 +235,8 @@ async def load_random_top_shouts(_, info, params): .where(and_(Shout.deletedAt.is_(None), Shout.layout.is_not(None))) ) - subquery = apply_filters(subquery, params.get("filters", {})) + subquery = apply_filters(subquery, params.get("filters", {}), use_published_date=True) + subquery = subquery.group_by(Shout.id).order_by(desc(get_rating_func(aliased_reaction))) from_random_count = params.get("fromRandomCount") @@ -254,6 +262,29 @@ async def load_random_top_shouts(_, info, params): return get_shouts_from_query(q) +@query.field("loadRandomTopicShouts") +async def load_random_topic_shouts(_, info, limit): + topic = get_random_topic() + + q = ( + select(Shout) + .options( + joinedload(Shout.authors), + joinedload(Shout.topics), + ) + .join(ShoutTopic, and_(Shout.id == ShoutTopic.shout, ShoutTopic.topic == topic.id)) + .where(and_(Shout.deletedAt.is_(None), Shout.layout.is_not(None))) + ) + + q = add_stat_columns(q) + + q = q.group_by(Shout.id).order_by(desc(Shout.createdAt)).limit(limit) + + shouts = get_shouts_from_query(q) + + return {"topic": topic, "shouts": shouts} + + @query.field("loadUnratedShouts") async def load_unrated_shouts(_, info, limit): auth: AuthCredentials = info.context["request"].auth diff --git a/resolvers/zine/topics.py b/resolvers/zine/topics.py index ad4f59fc..c9c9aae0 100644 --- a/resolvers/zine/topics.py +++ b/resolvers/zine/topics.py @@ -12,11 +12,12 @@ from orm.topic import Topic, TopicFollower def add_topic_stat_columns(q): aliased_shout_author = aliased(ShoutAuthor) aliased_topic_follower = aliased(TopicFollower) + aliased_shout_topic = aliased(ShoutTopic) q = ( - q.outerjoin(ShoutTopic, Topic.id == ShoutTopic.topic) - .add_columns(func.count(distinct(ShoutTopic.shout)).label("shouts_stat")) - .outerjoin(aliased_shout_author, ShoutTopic.shout == aliased_shout_author.shout) + q.outerjoin(aliased_shout_topic, Topic.id == aliased_shout_topic.topic) + .add_columns(func.count(distinct(aliased_shout_topic.shout)).label("shouts_stat")) + .outerjoin(aliased_shout_author, aliased_shout_topic.shout == aliased_shout_author.shout) .add_columns(func.count(distinct(aliased_shout_author.user)).label("authors_stat")) .outerjoin(aliased_topic_follower) .add_columns(func.count(distinct(aliased_topic_follower.follower)).label("followers_stat")) @@ -146,6 +147,18 @@ def topic_unfollow(user_id, slug): return False +def get_random_topic(): + q = select(Topic) + q = q.join(ShoutTopic) + q = q.group_by(Topic.id) + q = q.having(func.count(distinct(ShoutTopic.shout)) > 10) + q = q.order_by(func.random()).limit(1) + + with local_session() as session: + [topic] = session.execute(q).first() + return topic + + @query.field("topicsRandom") async def topics_random(_, info, amount=12): q = select(Topic) diff --git a/schema.graphql b/schema.graphql index 56517191..92560991 100644 --- a/schema.graphql +++ b/schema.graphql @@ -264,6 +264,11 @@ type MySubscriptionsQueryResult { authors: [Author]! } +type RandomTopicShoutsQueryResult { + topic: Topic! + shouts: [Shout]! +} + type Query { # inbox loadChats( limit: Int, offset: Int): Result! # your chats @@ -282,6 +287,7 @@ type Query { loadShout(slug: String, shout_id: Int): Shout loadShouts(options: LoadShoutsOptions): [Shout]! loadRandomTopShouts(params: LoadRandomTopShoutsParams): [Shout]! + loadRandomTopicShouts(limit: Int!): RandomTopicShoutsQueryResult! loadUnratedShouts(limit: Int!): [Shout]! loadDrafts: [Shout]! loadReactionsBy(by: ReactionBy!, limit: Int, offset: Int): [Reaction]!