{copyMenu}
diff --git a/front_end/src/components/forecast_maker/continuous_input/index.tsx b/front_end/src/components/forecast_maker/continuous_input/index.tsx
index bf69309977..4d4a70e88e 100644
--- a/front_end/src/components/forecast_maker/continuous_input/index.tsx
+++ b/front_end/src/components/forecast_maker/continuous_input/index.tsx
@@ -23,7 +23,9 @@ import {
} from "@/utils/forecasts/switch_forecast_type";
import { computeQuartilesFromCDF, getCdfBounds } from "@/utils/math";
-import ContinuousInputContainer from "./continuous_input_container";
+import ContinuousInputContainer, {
+ ContinuousInputContainerProps,
+} from "./continuous_input_container";
import ContinuousPredictionChart from "./continuous_prediction_chart";
import ContinuousSlider from "./continuous_slider";
import { validateAllQuantileInputs } from "../helpers";
@@ -55,6 +57,7 @@ type Props = {
predictionMessage?: ReactNode;
menu?: ReactNode;
copyMenu?: ReactNode;
+ clipboardData?: ContinuousInputContainerProps["clipboardData"];
userPreviousLabel?: string;
userPreviousRowClassName?: string;
hideCurrentUserRow?: boolean;
@@ -83,6 +86,7 @@ const ContinuousInput: FC
= ({
predictionMessage,
menu,
copyMenu,
+ clipboardData,
userPreviousLabel,
userPreviousRowClassName,
hideCurrentUserRow,
@@ -143,6 +147,7 @@ const ContinuousInput: FC = ({
previousForecast={previousForecast}
menu={menu}
copyMenu={copyMenu}
+ clipboardData={clipboardData}
disabled={disabled || disableInputModeSwitch}
questionType={question.type}
>
diff --git a/front_end/src/components/forecast_maker/forecast_maker_group/continuous_input_wrapper.tsx b/front_end/src/components/forecast_maker/forecast_maker_group/continuous_input_wrapper.tsx
index a6fb868aa4..e8439df375 100644
--- a/front_end/src/components/forecast_maker/forecast_maker_group/continuous_input_wrapper.tsx
+++ b/front_end/src/components/forecast_maker/forecast_maker_group/continuous_input_wrapper.tsx
@@ -21,6 +21,7 @@ import {
DistributionQuantileComponent,
DistributionSlider,
DistributionSliderComponent,
+ QuantileValue,
} from "@/types/question";
import { TranslationKey } from "@/types/translations";
import cn from "@/utils/core/cn";
@@ -261,6 +262,30 @@ const ContinuousInputWrapper: FC> = ({
handleForecastExpiration(option.id, modalSavedState.forecastExpiration);
}, [handleForecastExpiration, option.id, modalSavedState.forecastExpiration]);
+ const handleClipboardPaste = useCallback(
+ (
+ type: ContinuousForecastInputType,
+ components: DistributionSliderComponent[] | DistributionQuantileComponent
+ ) => {
+ if (type === ContinuousForecastInputType.Slider) {
+ handleChange(option.id, {
+ type: ContinuousForecastInputType.Slider,
+ components: components as DistributionSliderComponent[],
+ });
+ } else {
+ handleChange(option.id, {
+ type: ContinuousForecastInputType.Quantile,
+ components: (components as QuantileValue[]).map((c) => ({
+ ...c,
+ isDirty: true,
+ })),
+ });
+ }
+ setForecastInputMode(type);
+ },
+ [handleChange, option.id, setForecastInputMode]
+ );
+
let SubmitControls: ReactNode = null;
const predictButtonIsDirty =
@@ -418,6 +443,11 @@ const ContinuousInputWrapper: FC> = ({
}
menu={option.menu}
copyMenu={copyMenu}
+ clipboardData={{
+ sliderComponents: option.userSliderForecast,
+ quantileComponents: option.userQuantileForecast,
+ onPaste: handleClipboardPaste,
+ }}
userPreviousLabel={showWithdrawnRow ? "(Withdrawn)" : undefined}
userPreviousRowClassName={showWithdrawnRow ? "text-xs" : undefined}
hideCurrentUserRow={showWithdrawnRow}
diff --git a/front_end/src/components/forecast_maker/forecast_maker_question/forecast_maker_continuous.tsx b/front_end/src/components/forecast_maker/forecast_maker_question/forecast_maker_continuous.tsx
index bb07cdd392..1fd2b27736 100644
--- a/front_end/src/components/forecast_maker/forecast_maker_question/forecast_maker_continuous.tsx
+++ b/front_end/src/components/forecast_maker/forecast_maker_question/forecast_maker_continuous.tsx
@@ -2,7 +2,7 @@
import { isNil } from "lodash";
import { usePathname, useRouter } from "next/navigation";
import { useTranslations } from "next-intl";
-import React, { FC, ReactNode, useEffect, useMemo, useState } from "react";
+import React, { FC, ReactNode, useCallback, useEffect, useMemo, useState } from "react";
import {
createForecasts,
@@ -22,6 +22,7 @@ import {
DistributionQuantileComponent,
DistributionSlider,
DistributionSliderComponent,
+ QuantileValue,
QuestionWithNumericForecasts,
} from "@/types/question";
import { sendPredictEvent } from "@/utils/analytics";
@@ -451,6 +452,27 @@ const ForecastMakerContinuous: FC = ({
);
}
+ const handleClipboardPaste = useCallback(
+ (
+ type: ContinuousForecastInputType,
+ components: DistributionSliderComponent[] | DistributionQuantileComponent
+ ) => {
+ if (type === ContinuousForecastInputType.Slider) {
+ setSliderDistributionComponents(
+ components as DistributionSliderComponent[]
+ );
+ } else {
+ setQuantileDistributionComponents(
+ (components as QuantileValue[]).map((c) => ({ ...c, isDirty: true }))
+ );
+ }
+ setForecastInputMode(type);
+ setIsDirty(true);
+ setShowSuccessBox(false);
+ },
+ []
+ );
+
return (
<>
= ({
submitControls={SubmitControls}
disabled={!canPredict}
predictionMessage={predictionMessage}
+ clipboardData={{
+ sliderComponents: sliderDistributionComponents,
+ quantileComponents: quantileDistributionComponents,
+ onPaste: handleClipboardPaste,
+ }}
/>
>
);