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
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ import { getPostDrivenTime } from "@/utils/questions/helpers";
import ContinuousAggregationChart from "./continuous_aggregations_chart";
import HistogramDrawer from "./histogram_drawer";
import { AGGREGATION_EXPLORER_OPTIONS } from "../constants";
import { AggregationQuestionWithBots } from "../types";
import { AggregationExtraQuestion } from "../types";

type Props = {
aggregationData: AggregationQuestionWithBots | null;
aggregationData: AggregationExtraQuestion | null;
activeTab: string;
selectedSubQuestionOption: number | string | null;
postId: number;
Expand All @@ -42,7 +42,6 @@ const AggregationsTab: FC<Props> = ({

const {
aggregations,
bot_aggregations,
actual_close_time,
resolution,
unit,
Expand All @@ -54,11 +53,8 @@ const AggregationsTab: FC<Props> = ({
AGGREGATION_EXPLORER_OPTIONS[0];

const activeAggregation = useMemo(
() =>
tabData?.includeBots
? bot_aggregations?.[tabData.value]
: aggregations?.[tabData.value],
[aggregations, bot_aggregations, tabData]
() => aggregations?.[tabData.id],
[aggregations, tabData]
);

let aggregationIndex: number | undefined;
Expand Down Expand Up @@ -124,7 +120,7 @@ const AggregationsTab: FC<Props> = ({
return null;
}

const renderAggregation = (questionData: AggregationQuestionWithBots) => {
const renderAggregation = (questionData: AggregationExtraQuestion) => {
switch (questionData.type) {
case QuestionType.Binary:
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,25 @@ import ChoiceCheckbox from "@/components/choice_checkbox";
import Button from "@/components/ui/button";
import LoadingIndicator from "@/components/ui/loading_indicator";
import { ChoiceItem } from "@/types/choices";
import { AggregationMethod } from "@/types/question";
import { ThemeColor } from "@/types/theme";
import { logError } from "@/utils/core/errors";

import { AggregationMethodWithBots } from "../types";
import { AggregationExtraMethod } from "../types";

type Props = {
valueLabel: string;
tooltips: {
aggregationMethod: AggregationMethod;
choice: AggregationMethodWithBots;
aggregationMethod: string;
choice: AggregationExtraMethod;
label: string;
includeBots: boolean;
color: ThemeColor;
};
onFetchData: (
aggregationOptionId: AggregationMethodWithBots
) => Promise<void>;
onFetchData: (aggregationOptionId: AggregationExtraMethod) => Promise<void>;
onChoiceChange: (choice: string, checked: boolean) => void;
onChoiceHighlight: (choice: string, highlighted: boolean) => void;
choiceItems: ChoiceItem[];
onTabChange: (activeTab: AggregationMethodWithBots) => void;
onTabChange: (activeTab: AggregationExtraMethod) => void;
};

const AggregationTooltip: FC<Props> = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,14 @@ import { logError } from "@/utils/core/errors";
import AggregationsTab from "./aggregation_tab";
import AggregationsDrawer from "./aggregations_drawer";
import { AGGREGATION_EXPLORER_OPTIONS } from "../constants";
import {
AggregationMethodWithBots,
AggregationQuestionWithBots,
} from "../types";
import { AggregationExtraMethod, AggregationExtraQuestion } from "../types";

type Props = {
activeTab: AggregationMethodWithBots | null;
onTabChange: (activeTab: AggregationMethodWithBots) => void;
activeTab: AggregationExtraMethod | null;
onTabChange: (activeTab: AggregationExtraMethod) => void;
data: QuestionWithForecasts | PostWithForecasts;
selectedSubQuestionOption: number | string | null;
joinedBeforeDate?: string;
additionalParams?: {
userIds?: number[]; // Array of user IDs as a comma-separated string
};
Expand All @@ -28,22 +26,27 @@ export const AggregationWrapper: FC<Props> = ({
onTabChange,
selectedSubQuestionOption,
data,
joinedBeforeDate,
additionalParams = {},
}) => {
const postId = "post_id" in data ? data.post_id : data.id;
const [selectedAggregationMethods, setSelectedAggregationMethods] = useState<
AggregationMethodWithBots[]
AggregationExtraMethod[]
>([]);
const [aggregationData, setAggregationData] =
useState<AggregationQuestionWithBots | null>(null);
useState<AggregationExtraQuestion | null>(null);

const handleFetchAggregations = useCallback(
async (aggregationOptionId: AggregationMethodWithBots) => {
async (aggregationOptionId: AggregationExtraMethod) => {
const aggregationOption =
AGGREGATION_EXPLORER_OPTIONS.find(
(option) => option.id === aggregationOptionId
) ?? AGGREGATION_EXPLORER_OPTIONS[0];
const { value: aggregationMethod, includeBots } = aggregationOption;
const {
value: methodName,
id: methodID,
includeBots,
} = aggregationOption;

if (selectedAggregationMethods.includes(aggregationOptionId)) {
return;
Expand All @@ -60,46 +63,23 @@ export const AggregationWrapper: FC<Props> = ({
postId,
questionId: adjustedQuestionId,
includeBots,
aggregationMethods: aggregationMethod,
aggregationMethods: methodName,
joinedBeforeDate,
...additionalParams,
});

const fetchedAggregationData = response.aggregations[aggregationMethod];
const fetchedAggregationData = response.aggregations[methodName];
if (fetchedAggregationData !== undefined) {
setAggregationData((prev) =>
prev
? ({
...prev,
...(includeBots
? {
bot_aggregations: {
...prev.bot_aggregations,
[aggregationMethod]: fetchedAggregationData,
},
}
: {
aggregations: {
...prev.aggregations,
[aggregationMethod]: fetchedAggregationData,
},
}),
} as AggregationQuestionWithBots)
: ({
...response,
...(includeBots
? {
bot_aggregations: {
[aggregationMethod]: fetchedAggregationData,
},
aggregations: {},
}
: {
aggregations: {
[aggregationMethod]: fetchedAggregationData,
},
}),
} as AggregationQuestionWithBots)
);
setAggregationData((prev) => {
const base = prev ?? response;
return {
...base,
aggregations: {
...base.aggregations,
[methodID]: fetchedAggregationData,
},
} as AggregationExtraQuestion;
});
}
setSelectedAggregationMethods((prev) => [...prev, aggregationOptionId]);
} catch (err) {
Expand All @@ -110,6 +90,7 @@ export const AggregationWrapper: FC<Props> = ({
selectedAggregationMethods,
selectedSubQuestionOption,
postId,
joinedBeforeDate,
additionalParams,
]
);
Expand All @@ -129,6 +110,7 @@ export const AggregationWrapper: FC<Props> = ({
onFetchData={handleFetchAggregations}
aggregationData={aggregationData}
selectedSubQuestionOption={selectedSubQuestionOption}
joinedBeforeDate={joinedBeforeDate}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,22 @@ import {
generateAggregationTooltips,
generateChoiceItemsFromAggregations,
} from "../helpers";
import {
AggregationMethodWithBots,
AggregationQuestionWithBots,
} from "../types";
import { AggregationExtraMethod, AggregationExtraQuestion } from "../types";

type Props = {
onTabChange: (activeTab: AggregationMethodWithBots) => void;
onFetchData: (
aggregationOptionId: AggregationMethodWithBots
) => Promise<void>;
aggregationData: AggregationQuestionWithBots | null;
onTabChange: (activeTab: AggregationExtraMethod) => void;
onFetchData: (aggregationOptionId: AggregationExtraMethod) => Promise<void>;
aggregationData: AggregationExtraQuestion | null;
selectedSubQuestionOption: number | string | null;
joinedBeforeDate?: string;
};

const AggregationsDrawer: FC<Props> = ({
onTabChange,
onFetchData,
aggregationData,
selectedSubQuestionOption,
joinedBeforeDate,
}) => {
const { user } = useAuth();
const { actual_close_time, scaling, type, actual_resolve_time } =
Expand All @@ -54,7 +51,10 @@ const AggregationsDrawer: FC<Props> = ({
() => getPostDrivenTime(actual_close_time),
[actual_close_time]
);
const tooltips = useMemo(() => generateAggregationTooltips(user), [user]);
const tooltips = useMemo(
() => generateAggregationTooltips(user, joinedBeforeDate),
[joinedBeforeDate, user]
);
const [choiceItems, setChoiceItems] = useState(
aggregationData
? generateChoiceItemsFromAggregations({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ import {
import { cdfToPmf } from "@/utils/math";
import { formatValueUnit } from "@/utils/questions/units";

import { AggregationQuestionWithBots } from "../types";
import { AggregationExtraQuestion } from "../types";

type Props = {
questionData: AggregationQuestionWithBots;
questionData: AggregationExtraQuestion;
activeAggregation: AggregateForecastHistory;
selectedTimestamp: number | null;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { logError } from "@/utils/core/errors";
import { parseQuestionId } from "@/utils/questions/helpers";

import { AggregationWrapper } from "./aggregation_wrapper";
import { AggregationMethodWithBots } from "../types";
import { AggregationExtraMethod } from "../types";

function sanitizeUserIds(input: string): number[] {
if (!input) return [];
Expand Down Expand Up @@ -59,7 +59,7 @@ const Explorer: FC<Props> = ({ searchParams }) => {
string | number | null
>(parseSubQuestionOption(question_id, option));

const [activeTab, setActiveTab] = useState<AggregationMethodWithBots | null>(
const [activeTab, setActiveTab] = useState<AggregationExtraMethod | null>(
null
);
const [postInputText, setPostInputText] = useState<string>(
Expand All @@ -75,6 +75,11 @@ const Explorer: FC<Props> = ({ searchParams }) => {
: searchParams.user_ids
)?.toString() || ""
);
const [joinedBeforeDate, setJoinedBeforeDate] = useState<string>(
(Array.isArray(searchParams.joined_before_date)
? searchParams.joined_before_date[0]
: searchParams.joined_before_date) || ""
);

// clear subquestion options when post id input changes
useEffect(() => {
Expand Down Expand Up @@ -170,6 +175,10 @@ const Explorer: FC<Props> = ({ searchParams }) => {
params.set("user_ids", cleanedIds.join(","));
}

if (joinedBeforeDate.trim()) {
params.set("joined_before_date", joinedBeforeDate);
}

router.push(`/aggregation-explorer?${params.toString()}`);
};

Expand Down Expand Up @@ -213,6 +222,7 @@ const Explorer: FC<Props> = ({ searchParams }) => {
onTabChange={setActiveTab}
data={data}
selectedSubQuestionOption={selectedSubQuestionOption}
joinedBeforeDate={joinedBeforeDate || undefined}
additionalParams={{ userIds: sanitizeUserIds(userIdsText) }}
/>
</>
Expand Down Expand Up @@ -291,34 +301,50 @@ const Explorer: FC<Props> = ({ searchParams }) => {
value={selectedSubQuestionOption}
onChange={handleSubQuestionSelectChange}
/>
{user?.is_staff && (
{
// TODO: move "include bots" to here instead of in each tab
// user ids should only be avilable to staff or whitelisted users
// copy logic and parameters from the download data modal
<div className="mt-3">
<SectionToggle
title="Advanced options"
variant="light"
defaultOpen={!!userIdsText}
defaultOpen={!!userIdsText || !!joinedBeforeDate}
>
<div className="space-y-3">
{user?.is_staff && (
<div>
<label className="mb-1 block text-sm">
User Ids (comma-separated integers). Will act as if
these are the only participants.
</label>
<Input
name="user_ids"
type="text"
value={userIdsText}
onChange={(e) => setUserIdsText(e.target.value)}
className="w-full cursor-default overflow-hidden rounded border border-gray-500 bg-white p-2 text-left text-sm leading-5 text-gray-900 focus:outline-none focus:ring-0 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 dark:bg-blue-950 dark:text-gray-200 sm:text-sm"
/>
</div>
)}

<div>
<label className="mb-1 block text-sm">
User Ids (comma-separated integers). Will act as if these
are the only participants.
Filter for users who joined before date. Only effects
Joined Before aggregation.
</label>
<Input
name="user_ids"
type="text"
value={userIdsText}
onChange={(e) => setUserIdsText(e.target.value)}
name="joined_before_date"
type="date"
value={joinedBeforeDate}
onChange={(e) => setJoinedBeforeDate(e.target.value)}
className="w-full cursor-default overflow-hidden rounded border border-gray-500 bg-white p-2 text-left text-sm leading-5 text-gray-900 focus:outline-none focus:ring-0 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 dark:bg-blue-950 dark:text-gray-200 sm:text-sm"
/>
</div>
</div>
</SectionToggle>
</div>
)}
}
<Button
variant="primary"
type="submit"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { FC, memo } from "react";
import Histogram from "@/components/charts/histogram";
import { AggregateForecastHistory, QuestionType } from "@/types/question";

import { AggregationQuestionWithBots } from "../types";
import { AggregationExtraQuestion } from "../types";

type Props = {
questionData: AggregationQuestionWithBots;
questionData: AggregationExtraQuestion;
activeAggregation: AggregateForecastHistory;
selectedTimestamp: number | null;
aggregationIndex?: number;
Expand Down
Loading