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
4 changes: 2 additions & 2 deletions src/components/ClaimReview/ClaimReviewHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ const ClaimReviewHeader = ({
/>
{showTopicInput && (
<TopicDisplay
contentModel={target.contentModel}
data_hash={content.data_hash}
reviewTaskType={reviewTaskType}
topics={content?.topics || []}
reviewTaskType={reviewTaskType}
contentModel={target.contentModel}
/>
)}
</Grid>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,25 @@
import * as React from "react";
import { useEffect, useState} from "react";
import React, { useState, useEffect } from "react";
import MultiSelectAutocomplete from "../../topics/TopicOrImpactSelect";
import { IImpactAreaSelect, ManualTopic } from "../../../types/Topic";


interface ImpactAreaSelectProps {
onChange: (value: string) => void;
placeholder?: string;
}

const ImpactAreaSelect: React.FC<ImpactAreaSelectProps> = ({
const ImpactAreaSelect = ({
onChange,
placeholder,
}) => {
const [value, setValue] = useState("");
}: IImpactAreaSelect) => {
const [value, setValue] = useState<ManualTopic[]>([]);
const [isLoading, setIsLoading] = useState(false);

useEffect(() => {
onChange(value || undefined);
onChange(value);
}, []);

return (
<MultiSelectAutocomplete
placeholder={placeholder}
onChange={onChange}
setIsLoading={setIsLoading}
isLoading={isLoading}
setInputValue={setValue}
setSelectedTags={setValue}
isMultiple={false}
/>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -460,12 +460,12 @@ const VerificationRequestDetailDrawer: React.FC<VerificationRequestDetailDrawerP
>
<TopicDisplay
data_hash={currentRequest.data_hash}
reviewTaskType={
ReviewTaskTypeEnum.VerificationRequest
}
topics={
currentRequest?.topics || []
}
reviewTaskType={
ReviewTaskTypeEnum.VerificationRequest
}
/>
</Box>

Expand Down
9 changes: 2 additions & 7 deletions src/components/topics/TagDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,7 @@ import TagsList from "./TagsList";
import { useAtom } from "jotai";
import { isUserLoggedIn } from "../../atoms/currentUser";
import TagDisplayStyled from "./TagDisplay.style";

interface ITagDisplay {
handleClose: (removedTopicValue: any) => Promise<void>;
tags: any[];
setShowTopicsForm: (topicsForm: any) => void;
}
import { ITagDisplay } from "../../types/Topic";

const TagDisplay = ({ handleClose, tags, setShowTopicsForm }: ITagDisplay) => {
const [isLoggedIn] = useAtom(isUserLoggedIn);
Expand All @@ -31,7 +26,7 @@ const TagDisplay = ({ handleClose, tags, setShowTopicsForm }: ITagDisplay) => {
color: colors.primary,
}}
>
{tags.length ? <Edit fontSize="small"/> : <AddOutlined fontSize="small"/>}
{tags.length ? <Edit fontSize="small" /> : <AddOutlined fontSize="small" />}
</IconButton>
)}
</TagDisplayStyled>
Expand Down
42 changes: 24 additions & 18 deletions src/components/topics/TopicDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,51 +7,57 @@ import TagDisplay from "./TagDisplay";
import SentenceApi from "../../api/sentenceApi";
import verificationRequestApi from "../../api/verificationRequestApi";
import { ReviewTaskTypeEnum } from "../../machines/reviewTask/enums";
import { ITopicDisplay } from "../../types/Topic";

const TopicDisplay = ({
data_hash,
topics,
reviewTaskType,
contentModel = null,
}) => {
}: ITopicDisplay) => {
const [showTopicsForm, setShowTopicsForm] = useState<boolean>(false);
const [topicsArray, setTopicsArray] = useState<any[]>(topics);
const [inputValue, setInputValue] = useState<any[]>([]);
const [selectedTags, setSelectedTags] = useState<any[]>([]);
const [tags, setTags] = useState<any[]>([]);
const { t } = useTranslation();

useEffect(() => {
const inputValueFormatted = inputValue.map((inputValue) =>
inputValue?.value
const formattedSelectedTags = selectedTags.map((selectedTag) =>
selectedTag?.value
? {
label: inputValue?.label,
value: inputValue?.value,
aliases: inputValue?.aliases || [],
matchedAlias: inputValue?.matchedAlias || null,
label: selectedTag?.label,
value: selectedTag?.value,
aliases: selectedTag?.aliases || [],
matchedAlias: selectedTag?.matchedAlias || null,
}
: inputValue
: selectedTag
);

const filterValues = inputValueFormatted.filter(
(inputValue) =>
const filterSelectedTags = formattedSelectedTags.filter(
(selectedTag) =>
!topicsArray.some(
(topic) =>
(topic?.value || topic) ===
(inputValue?.value || inputValue)
(selectedTag?.value || selectedTag)
)
);
setTags(topicsArray?.concat(filterValues) || []);
}, [inputValue, topicsArray]);
setTags(topicsArray?.concat(filterSelectedTags) || []);
}, [selectedTags, topicsArray]);

console.log(topicsArray,selectedTags)

const handleClose = async (removedTopicValue: any) => {
// NOTE: Filtering logic differs due to inconsistent data structures across collections:
// 1. topicsArray: May contain persisted topics from VerificationRequest, requiring 'wikidataId' as an identifier.
// 2. selectedTags: Follows the 'ManualTopic' UI schema, which consistently uses 'value'.
const newTopicsArray = topicsArray.filter(
(topic) => (topic?.value || topic) !== removedTopicValue
(topic) => (topic?.value || topic?.wikidataId || topic) !== removedTopicValue
);
const newInputValue = inputValue.filter(
const newSelectedTag = selectedTags.filter(
(topic) => (topic?.value || topic) !== removedTopicValue
);
setTopicsArray(newTopicsArray);
setInputValue(newInputValue);
setSelectedTags(newSelectedTag);

if (reviewTaskType === ReviewTaskTypeEnum.VerificationRequest) {
return await verificationRequestApi.deleteVerificationRequestTopic(
Expand Down Expand Up @@ -84,7 +90,7 @@ const TopicDisplay = ({
data_hash={data_hash}
topicsArray={topicsArray}
setTopicsArray={setTopicsArray}
setInputValue={setInputValue}
setSelectedTags={setSelectedTags}
tags={tags}
reviewTaskType={reviewTaskType}
/>
Expand Down
16 changes: 3 additions & 13 deletions src/components/topics/TopicForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,16 @@ import AletheiaButton from "../Button";
import TopicInputErrorMessages from "./TopicInputErrorMessages";
import { useTranslation } from "next-i18next";
import TopicsApi from "../../api/topicsApi";
import { ContentModelEnum } from "../../types/enums";
import MultiSelectAutocomplete from "./TopicOrImpactSelect";
import verificationRequestApi from "../../api/verificationRequestApi";

interface ITopicForm {
contentModel: ContentModelEnum;
data_hash: string;
topicsArray: any[];
setTopicsArray: (topicsArray) => void;
setInputValue: (inputValue) => void;
tags: any[];
reviewTaskType: string;
}
import { ITopicForm } from "../../types/Topic";

const TopicForm = ({
contentModel,
data_hash,
topicsArray,
setTopicsArray,
setInputValue,
setSelectedTags,
tags,
reviewTaskType,
}: ITopicForm) => {
Expand Down Expand Up @@ -92,7 +82,7 @@ const TopicForm = ({
onChange={onChange}
setIsLoading={setIsLoading}
isLoading={isLoading}
setInputValue={setInputValue}
setSelectedTags={setSelectedTags}
/>
)}
/>
Expand Down
11 changes: 6 additions & 5 deletions src/components/topics/TopicOrImpactSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ import {
import { useDispatch } from "react-redux";
import TopicsApi from "../../api/topicsApi";
import { useTranslation } from "react-i18next";
import { IMultiSelectAutocomplete } from "../../types/Topic";

const MultiSelectAutocomplete = ({
isMultiple = true,
onChange,
isLoading,
placeholder,
setInputValue,
setSelectedTags,
setIsLoading,
}) => {
}: IMultiSelectAutocomplete) => {
const { t } = useTranslation();
const [options, setOptions] = useState([]);
const dispatch = useDispatch();
Expand Down Expand Up @@ -77,9 +78,9 @@ const MultiSelectAutocomplete = ({
size="small"
options={options}
onInputChange={(_, value) => fetchOptions(value)}
onChange={(_, selectedValues) => {
onChange(selectedValues);
setInputValue(selectedValues);
onChange={(_, inputTag) => {
onChange(inputTag);
setSelectedTags(inputTag);
}}
getOptionLabel={(option) =>
option.displayLabel || option.label || ""
Expand Down
50 changes: 50 additions & 0 deletions src/types/Topic.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,57 @@
import React from "react";
import { ReviewTaskTypeEnum } from "../machines/reviewTask/enums";
import { ContentModelEnum } from "./enums";
export interface Topic {
_id: string;
name: string;
wikidataId: string;
slug: string;
language: string;
}

export interface ManualTopic {
id?: string;
aliases?: string[];
displayLabel?: string;
label: string;
matchedAlias?: string | null;
value: string;
}

export type UnifiedTopic = Topic | ManualTopic;
export interface ITagDisplay {
handleClose: (removedTopicValue: string) => Promise<void>;
tags: ManualTopic[];
setShowTopicsForm: React.Dispatch<React.SetStateAction<boolean>>;
}

export interface ITopicForm {
contentModel: ContentModelEnum;
data_hash: string;
topicsArray: UnifiedTopic[];
setTopicsArray: React.Dispatch<React.SetStateAction<UnifiedTopic[]>>;
setSelectedTags: React.Dispatch<React.SetStateAction<ManualTopic[]>>;
tags: ManualTopic[];
reviewTaskType: ReviewTaskTypeEnum;
}

export interface ITopicDisplay {
data_hash: string;
topics: UnifiedTopic[];
reviewTaskType: ReviewTaskTypeEnum;
contentModel?: ContentModelEnum | null;
}

export interface IImpactAreaSelect {
onChange: (value: ManualTopic[]) => void;
placeholder?: string;
}

export interface IMultiSelectAutocomplete {
isMultiple?: boolean;
onChange: (value: ManualTopic[]) => void;
isLoading: boolean;
placeholder: string;
setSelectedTags: React.Dispatch<React.SetStateAction<ManualTopic[]>>;
setIsLoading: React.Dispatch<React.SetStateAction<boolean>>;
}
Loading