Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 49 additions & 4 deletions coherence/serializers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from collections import Counter
from collections import Counter, defaultdict
from typing import Iterable

import numpy as np
from django.db.models import Q
from multidict import MultiDict
from rest_framework import serializers

Expand Down Expand Up @@ -72,8 +73,8 @@ def serialize_coherence_link_many(
links: Iterable[CoherenceLink], serialize_questions: bool = True
):
ids = [link.pk for link in links]
qs = CoherenceLink.objects.filter(pk__in=[c.pk for c in links]).select_related(
"question1", "question2"
qs = CoherenceLink.objects.filter(pk__in=[c.pk for c in links]).prefetch_related(
"question1__related_posts", "question2__related_posts"
)

objects = list(qs.all())
Expand Down Expand Up @@ -136,7 +137,7 @@ def serialize_aggregate_coherence_link_many(
ids = [link.pk for link in links]
qs = AggregateCoherenceLink.objects.filter(
pk__in=[c.pk for c in links]
).select_related("question1", "question2")
).prefetch_related("question1__related_posts", "question2__related_posts")

if current_user:
qs = qs.annotate_user_vote(current_user)
Expand Down Expand Up @@ -172,6 +173,50 @@ def serialize_aggregate_coherence_link_many(
]


def serialize_aggregate_coherence_links_questions_map(
questions: Iterable[Question], current_user: User = None
) -> dict[int, list[dict]]:
qs = AggregateCoherenceLink.objects.filter(
Q(question1__in=questions) | Q(question2__in=questions)
)
questions_map = {q.id: q for q in questions}

serialized_data = serialize_aggregate_coherence_link_many(
qs, current_user=current_user
)
links_map = defaultdict(list)

for link in serialized_data:
for alias in ("question1_id", "question2_id"):
question = questions_map.get(link[alias])

if question:
links_map[question].append(link)

return links_map


def serialize_coherence_links_questions_map(
questions: Iterable[Question], current_user: User
) -> dict[int, list[dict]]:
qs = CoherenceLink.objects.filter(
Q(question1__in=questions) | Q(question2__in=questions), user=current_user
)
questions_map = {q.id: q for q in questions}

serialized_data = serialize_coherence_link_many(qs)
links_map = defaultdict(list)

for link in serialized_data:
for alias in ("question1_id", "question2_id"):
question = questions_map.get(link[alias])

if question:
links_map[question].append(link)

return links_map


def serialize_aggregate_coherence_link_vote(
vote_scores: list[AggregateCoherenceLinkVote],
user_vote: int = None,
Expand Down
34 changes: 23 additions & 11 deletions front_end/src/app/(main)/components/coherence_links_provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,34 @@ export const CoherenceLinksProvider: FC<
const { user } = useAuth();
const isLoggedIn = !isNil(user);

const fetchLinks = async () => {
if (!isLoggedIn || !post.question) {
useEffect(() => {
if (
!isLoggedIn ||
!post.question ||
!post.question.coherence_links?.length ||
!post.question.coherence_link_aggregations?.length
) {
setCoherenceLinks({ data: [] });
setAggregateCoherenceLinks({ data: [] });
return;
}

setCoherenceLinks({ data: post.question.coherence_links });
setAggregateCoherenceLinks({
data: post.question.coherence_link_aggregations,
});
}, [
isLoggedIn,
post.question,
post.question?.coherence_links,
post.question?.coherence_link_aggregations,
]);

const updateCoherenceLinks = async () => {
if (!isLoggedIn || !post.question) {
return;
}

try {
const [links, aggregate] = await Promise.all([
ClientCoherenceLinksApi.getCoherenceLinksForPost(post.question),
Expand All @@ -72,15 +93,6 @@ export const CoherenceLinksProvider: FC<
}
};

useEffect(() => {
void fetchLinks();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isLoggedIn, post.question?.id]);

const updateCoherenceLinks = async () => {
await fetchLinks();
};

const getOtherQuestions = () => {
const questionData = new Map<number, Question>();
const questionID = post.question?.id;
Expand Down
6 changes: 6 additions & 0 deletions front_end/src/types/question.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { ContinuousQuestionTypes } from "@/constants/questions";
import {
FetchedAggregateCoherenceLinks,
FetchedCoherenceLinks,
} from "@/types/coherence";
import { QuestionStatus, Resolution } from "@/types/post";
import { Category } from "@/types/projects";

Expand Down Expand Up @@ -268,6 +272,8 @@ export type Question = {
movement: null | CPMovement;
};
average_coverage?: number | null;
coherence_links?: FetchedCoherenceLinks["data"];
coherence_link_aggregations?: FetchedAggregateCoherenceLinks["data"];
};

export enum MovementDirection {
Expand Down
23 changes: 23 additions & 0 deletions posts/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
from rest_framework import serializers
from rest_framework.exceptions import ValidationError

from coherence.serializers import (
serialize_coherence_links_questions_map,
serialize_aggregate_coherence_links_questions_map,
)
from comments.models import KeyFactor
from comments.serializers.key_factors import serialize_key_factors_many
from misc.models import ITNArticle
Expand Down Expand Up @@ -341,13 +345,17 @@ def serialize_post(
include_descriptions: bool = False,
question_movements: dict[Question, QuestionMovement | None] = None,
question_average_coverages: dict[Question, float] = None,
coherence_links: dict[Question, list[dict]] = None,
coherence_link_aggregations: dict[Question, list[dict]] = None,
) -> dict:
current_user = (
current_user if current_user and not current_user.is_anonymous else None
)
serialized_data = PostReadSerializer(post).data
question_movements = question_movements or {}
question_average_coverages = question_average_coverages or {}
coherence_links = coherence_links or {}
coherence_link_aggregations = coherence_link_aggregations or {}

# Appending projects
projects = projects or []
Expand All @@ -367,6 +375,8 @@ def serialize_post(
include_descriptions=include_descriptions,
question_movement=question_movements.get(post.question),
question_average_coverage=question_average_coverages.get(post.question),
coherence_links=coherence_links.get(post.question),
coherence_link_aggregations=coherence_link_aggregations.get(post.question),
)

if post.conditional:
Expand Down Expand Up @@ -516,6 +526,8 @@ def serialize_post_many(
)

comment_key_factors_map = {}
coherence_links_map = {}
coherence_link_aggs_map = {}

if with_key_factors:
comment_key_factors_map = generate_map_from_list(
Expand All @@ -528,6 +540,15 @@ def serialize_post_many(
key=lambda x: x["post"]["id"],
)

if current_user:
coherence_links_map = serialize_coherence_links_questions_map(
questions, current_user
)

coherence_link_aggs_map = serialize_aggregate_coherence_links_questions_map(
questions
)

question_movements = {}
if include_movements:
question_movements = calculate_movement_for_questions(questions)
Expand Down Expand Up @@ -559,6 +580,8 @@ def serialize_post_many(
include_descriptions=include_descriptions,
question_movements=question_movements,
question_average_coverages=question_average_coverages,
coherence_links=coherence_links_map,
coherence_link_aggregations=coherence_link_aggs_map,
)
for post in posts
]
Expand Down
9 changes: 9 additions & 0 deletions questions/serializers/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,13 +585,22 @@ def serialize_question(
include_descriptions: bool = False,
question_movement: QuestionMovement | None = None,
question_average_coverage: float = None,
coherence_links: list[dict] = None,
coherence_link_aggregations: list[dict] = None,
):
"""
Serializes question object
"""

serialized_data = QuestionSerializer(question).data

serialized_data.update(
{
"coherence_links": coherence_links,
"coherence_link_aggregations": coherence_link_aggregations,
}
)

if include_descriptions:
serialized_data.update(
{
Expand Down