refactor: rename forecast -> question (see #40)
This commit is contained in:
parent
2ee82cdd15
commit
6543a729f3
|
@ -13,7 +13,7 @@
|
|||
# React
|
||||
|
||||
- create one file per one component (tiny helper components in the same file are fine)
|
||||
- name file identically to the component it describes (e.g. `const DisplayForecasts: React.FC<Props> = ...` in `DisplayForecasts.ts`)
|
||||
- name file identically to the component it describes (e.g. `const DisplayQuestions: React.FC<Props> = ...` in `DisplayQuestions.ts`)
|
||||
- use named export instead of default export for all React components
|
||||
- it's better for refactoring
|
||||
- and it plays well with `React.FC` typing
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { Pool, PoolClient } from "pg";
|
||||
|
||||
import { Forecast } from "../platforms";
|
||||
import { Question } from "../platforms";
|
||||
import { hash } from "../utils/hash";
|
||||
import { measureTime } from "../utils/measureTime";
|
||||
import { roughSizeOfObject } from "../utils/roughSize";
|
||||
|
||||
const forecastTableNames = ["questions", "history"];
|
||||
const questionTableNames = ["questions", "history"];
|
||||
|
||||
const allTableNames = [...forecastTableNames, "dashboards", "frontpage"];
|
||||
const allTableNames = [...questionTableNames, "dashboards", "frontpage"];
|
||||
|
||||
/* Postgres database connection code */
|
||||
const databaseURL = process.env.DIGITALOCEAN_POSTGRES;
|
||||
|
@ -51,11 +51,11 @@ export async function pgBulkInsert({
|
|||
tableName,
|
||||
client,
|
||||
}: {
|
||||
data: Forecast[];
|
||||
data: Question[];
|
||||
tableName: string;
|
||||
client: PoolClient;
|
||||
}) {
|
||||
if (!forecastTableNames.includes(tableName)) {
|
||||
if (!questionTableNames.includes(tableName)) {
|
||||
throw Error(
|
||||
`Table ${tableName} not in whitelist; stopping to avoid tricky sql injections`
|
||||
);
|
||||
|
@ -171,11 +171,11 @@ export async function pgUpsert({
|
|||
tableName,
|
||||
replacePlatform,
|
||||
}: {
|
||||
contents: Forecast[];
|
||||
contents: Question[];
|
||||
tableName: string;
|
||||
replacePlatform?: string;
|
||||
}) {
|
||||
if (!forecastTableNames.includes(tableName)) {
|
||||
if (!questionTableNames.includes(tableName)) {
|
||||
throw Error(
|
||||
`Table ${tableName} not in whitelist; stopping to avoid tricky sql injections`
|
||||
);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { pgRead, pool } from "./database/pg-wrapper";
|
||||
import { Forecast } from "./platforms";
|
||||
import { Question } from "./platforms";
|
||||
|
||||
export async function getFrontpage(): Promise<Forecast[]> {
|
||||
export async function getFrontpage(): Promise<Question[]> {
|
||||
const res = await pool.query(
|
||||
"SELECT frontpage_sliced FROM frontpage ORDER BY id DESC LIMIT 1"
|
||||
);
|
||||
|
@ -9,7 +9,7 @@ export async function getFrontpage(): Promise<Forecast[]> {
|
|||
return res.rows[0].frontpage_sliced;
|
||||
}
|
||||
|
||||
export async function getFrontpageFull(): Promise<Forecast[]> {
|
||||
export async function getFrontpageFull(): Promise<Question[]> {
|
||||
const res = await pool.query(
|
||||
"SELECT frontpage_full FROM frontpage ORDER BY id DESC LIMIT 1"
|
||||
);
|
||||
|
|
|
@ -3,7 +3,7 @@ import axios from "axios";
|
|||
import https from "https";
|
||||
|
||||
import { calculateStars } from "../utils/stars";
|
||||
import { Forecast, Platform } from "./";
|
||||
import { Platform, Question } from "./";
|
||||
|
||||
const platformName = "betfair";
|
||||
|
||||
|
@ -80,7 +80,7 @@ async function whipIntoShape(data) {
|
|||
async function processPredictions(data) {
|
||||
let predictions = await whipIntoShape(data);
|
||||
// console.log(JSON.stringify(predictions, null, 4))
|
||||
let results: Forecast[] = predictions.map((prediction) => {
|
||||
let results: Question[] = predictions.map((prediction) => {
|
||||
/* if(Math.floor(Math.random() * 10) % 20 ==0){
|
||||
console.log(JSON.stringify(prediction, null, 4))
|
||||
} */
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import axios from "axios";
|
||||
|
||||
import { calculateStars } from "../utils/stars";
|
||||
import { Forecast, Platform } from "./";
|
||||
import { Platform, Question } from "./";
|
||||
|
||||
const platformName = "fantasyscotus";
|
||||
|
||||
|
@ -67,7 +67,7 @@ async function processData(data) {
|
|||
let historicalPercentageCorrect = data.stats.pcnt_correct;
|
||||
let historicalProbabilityCorrect =
|
||||
Number(historicalPercentageCorrect.replace("%", "")) / 100;
|
||||
let results: Forecast[] = [];
|
||||
let results: Question[] = [];
|
||||
for (let event of events) {
|
||||
if (event.accuracy == "") {
|
||||
let id = `${platformName}-${event.id}`;
|
||||
|
@ -75,7 +75,7 @@ async function processData(data) {
|
|||
let predictionData = await getPredictionsData(event.docket_url);
|
||||
let pAffirm = predictionData.proportionAffirm;
|
||||
//let trackRecord = event.prediction.includes("Affirm") ? historicalProbabilityCorrect : 1-historicalProbabilityCorrect
|
||||
let eventObject: Forecast = {
|
||||
let eventObject: Question = {
|
||||
id: id,
|
||||
title: `In ${event.short_name}, the SCOTUS will affirm the lower court's decision`,
|
||||
url: `https://fantasyscotus.net/user-predictions${event.docket_url}`,
|
||||
|
|
|
@ -16,7 +16,7 @@ import { smarkets } from "./smarkets";
|
|||
import { wildeford } from "./wildeford";
|
||||
import { xrisk } from "./xrisk";
|
||||
|
||||
export interface Forecast {
|
||||
export interface Question {
|
||||
id: string;
|
||||
// "fantasyscotus-580"
|
||||
|
||||
|
@ -63,8 +63,8 @@ export interface Forecast {
|
|||
extra?: any;
|
||||
}
|
||||
|
||||
// fetcher should return null if platform failed to fetch forecasts for some reason
|
||||
export type PlatformFetcher = () => Promise<Forecast[] | null>;
|
||||
// fetcher should return null if platform failed to fetch questions for some reason
|
||||
export type PlatformFetcher = () => Promise<Question[] | null>;
|
||||
|
||||
export interface Platform {
|
||||
name: string; // short name for ids and `platform` db column, e.g. "xrisk"
|
||||
|
@ -76,7 +76,7 @@ export interface Platform {
|
|||
// draft for the future callback-based streaming/chunking API:
|
||||
// interface FetchOptions {
|
||||
// since?: string; // some kind of cursor, Date object or opaque string?
|
||||
// save: (forecasts: Forecast[]) => Promise<void>;
|
||||
// save: (questions: Question[]) => Promise<void>;
|
||||
// }
|
||||
|
||||
// export type PlatformFetcher = (options: FetchOptions) => Promise<void>;
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
/* Imports */
|
||||
import axios from "axios";
|
||||
import { Tabletojson } from "tabletojson";
|
||||
|
||||
import { applyIfSecretExists } from "../utils/getSecrets";
|
||||
import { measureTime } from "../utils/measureTime";
|
||||
import { calculateStars } from "../utils/stars";
|
||||
import toMarkdown from "../utils/toMarkdown";
|
||||
import { Forecast, Platform } from "./";
|
||||
import { Platform, Question } from "./";
|
||||
|
||||
/* Definitions */
|
||||
const platformName = "infer";
|
||||
|
@ -78,12 +77,12 @@ async function fetchStats(questionUrl, cookie) {
|
|||
let comments_count = firstEmbeddedJson.question.comments_count;
|
||||
let numforecasters = firstEmbeddedJson.question.predictors_count;
|
||||
let numforecasts = firstEmbeddedJson.question.prediction_sets_count;
|
||||
let forecastType = firstEmbeddedJson.question.type;
|
||||
let questionType = firstEmbeddedJson.question.type;
|
||||
if (
|
||||
forecastType.includes("Binary") ||
|
||||
forecastType.includes("NonExclusiveOpinionPoolQuestion") ||
|
||||
forecastType.includes("Forecast::Question") ||
|
||||
!forecastType.includes("Forecast::MultiTimePeriodQuestion")
|
||||
questionType.includes("Binary") ||
|
||||
questionType.includes("NonExclusiveOpinionPoolQuestion") ||
|
||||
questionType.includes("Forecast::Question") ||
|
||||
!questionType.includes("Forecast::MultiTimePeriodQuestion")
|
||||
) {
|
||||
options = firstEmbeddedJson.question.answers.map((answer) => ({
|
||||
name: answer.name,
|
||||
|
@ -148,7 +147,7 @@ function sleep(ms) {
|
|||
async function infer_inner(cookie: string) {
|
||||
let i = 1;
|
||||
let response = await fetchPage(i, cookie);
|
||||
let results: Forecast[] = [];
|
||||
let results: Question[] = [];
|
||||
|
||||
await measureTime(async () => {
|
||||
// console.log("Downloading... This might take a couple of minutes. Results will be shown.")
|
||||
|
@ -179,7 +178,7 @@ async function infer_inner(cookie: string) {
|
|||
let questionNumRegex = new RegExp("questions/([0-9]+)");
|
||||
let questionNum = url.match(questionNumRegex)[1]; //.split("questions/")[1].split("-")[0];
|
||||
let id = `${platformName}-${questionNum}`;
|
||||
let question: Forecast = {
|
||||
let question: Question = {
|
||||
id: id,
|
||||
title: title,
|
||||
description: moreinfo.description,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import axios from "axios";
|
||||
|
||||
import { calculateStars } from "../utils/stars";
|
||||
import { Forecast, Platform } from "./";
|
||||
import { Platform, Question } from "./";
|
||||
|
||||
/* Definitions */
|
||||
const platformName = "manifold";
|
||||
|
@ -23,7 +23,7 @@ async function fetchData() {
|
|||
return response;
|
||||
}
|
||||
|
||||
function showStatistics(results: Forecast[]) {
|
||||
function showStatistics(results: Question[]) {
|
||||
console.log(`Num unresolved markets: ${results.length}`);
|
||||
let sum = (arr) => arr.reduce((tally, a) => tally + a, 0);
|
||||
let num2StarsOrMore = results.filter(
|
||||
|
@ -44,7 +44,7 @@ function showStatistics(results: Forecast[]) {
|
|||
}
|
||||
|
||||
async function processPredictions(predictions) {
|
||||
let results: Forecast[] = await predictions.map((prediction) => {
|
||||
let results: Question[] = await predictions.map((prediction) => {
|
||||
let id = `${platformName}-${prediction.id}`; // oops, doesn't match platform name
|
||||
let probability = prediction.probability;
|
||||
let options = [
|
||||
|
@ -59,7 +59,7 @@ async function processPredictions(predictions) {
|
|||
type: "PROBABILITY",
|
||||
},
|
||||
];
|
||||
const result: Forecast = {
|
||||
const result: Question = {
|
||||
id: id,
|
||||
title: prediction.question,
|
||||
url: prediction.url,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import axios from "axios";
|
||||
|
||||
import { calculateStars } from "../utils/stars";
|
||||
import { Forecast, Platform } from "./";
|
||||
import { Platform, Question } from "./";
|
||||
|
||||
/* Definitions */
|
||||
const platformName = "polymarket";
|
||||
|
@ -68,7 +68,7 @@ export const polymarket: Platform = {
|
|||
label: "PolyMarket",
|
||||
color: "#00314e",
|
||||
async fetcher() {
|
||||
let results: Forecast[] = [];
|
||||
let results: Question[] = [];
|
||||
let webpageEndpointData = await fetchAllContractInfo();
|
||||
for (let marketInfo of webpageEndpointData) {
|
||||
let address = marketInfo.marketMakerAddress;
|
||||
|
@ -102,7 +102,7 @@ export const polymarket: Platform = {
|
|||
});
|
||||
}
|
||||
|
||||
let result: Forecast = {
|
||||
let result: Question = {
|
||||
id: id,
|
||||
title: marketInfo.question,
|
||||
url: "https://polymarket.com/market/" + marketInfo.slug,
|
||||
|
|
|
@ -3,7 +3,7 @@ import { JSDOM } from "jsdom";
|
|||
|
||||
import { calculateStars } from "../utils/stars";
|
||||
import toMarkdown from "../utils/toMarkdown";
|
||||
import { Forecast, Platform } from "./";
|
||||
import { Platform, Question } from "./";
|
||||
|
||||
const platformName = "rootclaim";
|
||||
const jsonEndpoint =
|
||||
|
@ -50,7 +50,7 @@ export const rootclaim: Platform = {
|
|||
color: "#0d1624",
|
||||
async fetcher() {
|
||||
const claims = await fetchAllRootclaims();
|
||||
const results: Forecast[] = [];
|
||||
const results: Question[] = [];
|
||||
|
||||
for (const claim of claims) {
|
||||
const id = `${platformName}-${claim.slug.toLowerCase()}`;
|
||||
|
@ -71,7 +71,7 @@ export const rootclaim: Platform = {
|
|||
|
||||
const description = await fetchDescription(url, claim.isclaim);
|
||||
|
||||
let obj: Forecast = {
|
||||
let obj: Question = {
|
||||
id,
|
||||
title: toMarkdown(claim.question).replace("\n", ""),
|
||||
url,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import axios from "axios";
|
||||
|
||||
import { calculateStars } from "../utils/stars";
|
||||
import { Forecast, Platform } from "./";
|
||||
import { Platform, Question } from "./";
|
||||
|
||||
/* Definitions */
|
||||
const platformName = "smarkets";
|
||||
|
@ -159,7 +159,7 @@ export const smarkets: Platform = {
|
|||
name = name+ (contractName=="Yes"?'':` (${contracts["contracts"][0].name})`)
|
||||
}
|
||||
*/
|
||||
let result: Forecast = {
|
||||
let result: Question = {
|
||||
id: id,
|
||||
title: name,
|
||||
url: "https://smarkets.com/event/" + market.event_id + market.slug,
|
||||
|
|
|
@ -8,14 +8,14 @@ import { pgRead } from "../../database/pg-wrapper";
|
|||
/* Utilities */
|
||||
|
||||
/* Support functions */
|
||||
let getQualityIndicators = (forecast) =>
|
||||
Object.entries(forecast.qualityindicators)
|
||||
const getQualityIndicators = (question) =>
|
||||
Object.entries(question.qualityindicators)
|
||||
.map((entry) => `${entry[0]}: ${entry[1]}`)
|
||||
.join("; ");
|
||||
|
||||
/* Body */
|
||||
|
||||
let main = async () => {
|
||||
const main = async () => {
|
||||
let highQualityPlatforms = [
|
||||
"CSET-foretell",
|
||||
"Foretold",
|
||||
|
@ -24,21 +24,21 @@ let main = async () => {
|
|||
"PredictIt",
|
||||
"Rootclaim",
|
||||
];
|
||||
let json = await pgRead({ tableName: "questions" });
|
||||
const json = await pgRead({ tableName: "questions" });
|
||||
console.log(json.length);
|
||||
//let uniquePlatforms = [...new Set(json.map(forecast => forecast.platform))]
|
||||
//console.log(uniquePlatforms)
|
||||
|
||||
let forecastsFromGoodPlatforms = json.filter((forecast) =>
|
||||
highQualityPlatforms.includes(forecast.platform)
|
||||
const questionsFromGoodPlatforms = json.filter((question) =>
|
||||
highQualityPlatforms.includes(question.platform)
|
||||
);
|
||||
let tsv =
|
||||
const tsv =
|
||||
"index\ttitle\turl\tqualityindicators\n" +
|
||||
forecastsFromGoodPlatforms
|
||||
.map((forecast, index) => {
|
||||
let row = `${index}\t${forecast.title}\t${
|
||||
forecast.url
|
||||
}\t${getQualityIndicators(forecast)}`;
|
||||
questionsFromGoodPlatforms
|
||||
.map((question, index) => {
|
||||
let row = `${index}\t${question.title}\t${
|
||||
question.url
|
||||
}\t${getQualityIndicators(question)}`;
|
||||
console.log(row);
|
||||
return row;
|
||||
})
|
||||
|
|
|
@ -8,8 +8,8 @@ import { pgRead } from "../../database/pg-wrapper";
|
|||
/* Utilities */
|
||||
|
||||
/* Support functions */
|
||||
let getQualityIndicators = (forecast) =>
|
||||
Object.entries(forecast.qualityindicators)
|
||||
let getQualityIndicators = (question) =>
|
||||
Object.entries(question.qualityindicators)
|
||||
.map((entry) => `${entry[0]}: ${entry[1]}`)
|
||||
.join("; ");
|
||||
|
||||
|
@ -28,22 +28,22 @@ let main = async () => {
|
|||
let highQualityPlatforms = ["Metaculus"]; // ['CSET-foretell', 'Foretold', 'Good Judgment Open', 'Metaculus', 'PredictIt', 'Rootclaim']
|
||||
let json = await pgRead({ tableName: "questions" });
|
||||
console.log(json.length);
|
||||
//let uniquePlatforms = [...new Set(json.map(forecast => forecast.platform))]
|
||||
//let uniquePlatforms = [...new Set(json.map(question => question.platform))]
|
||||
//console.log(uniquePlatforms)
|
||||
|
||||
let forecastsFromGoodPlatforms = json.filter((forecast) =>
|
||||
highQualityPlatforms.includes(forecast.platform)
|
||||
let questionsFromGoodPlatforms = json.filter((question) =>
|
||||
highQualityPlatforms.includes(question.platform)
|
||||
);
|
||||
let forecastsFromGoodPlatformsShuffled = shuffleArray(
|
||||
forecastsFromGoodPlatforms
|
||||
let questionsFromGoodPlatformsShuffled = shuffleArray(
|
||||
questionsFromGoodPlatforms
|
||||
);
|
||||
let tsv =
|
||||
"index\ttitle\turl\tqualityindicators\n" +
|
||||
forecastsFromGoodPlatforms
|
||||
.map((forecast, index) => {
|
||||
let row = `${index}\t${forecast.title}\t${
|
||||
forecast.url
|
||||
}\t${getQualityIndicators(forecast)}`;
|
||||
questionsFromGoodPlatforms
|
||||
.map((question, index) => {
|
||||
let row = `${index}\t${question.title}\t${
|
||||
question.url
|
||||
}\t${getQualityIndicators(question)}`;
|
||||
console.log(row);
|
||||
return row;
|
||||
})
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { NextPage } from "next";
|
||||
import React from "react";
|
||||
|
||||
import { displayForecastsWrapperForCapture } from "../web/display/displayForecastsWrappers";
|
||||
import { displayQuestionsWrapperForCapture } from "../web/display/displayQuestionsWrappers";
|
||||
import { Layout } from "../web/display/Layout";
|
||||
import { Props } from "../web/search/anySearchPage";
|
||||
import CommonDisplay from "../web/search/CommonDisplay";
|
||||
|
@ -18,7 +18,7 @@ const CapturePage: NextPage<Props> = (props) => {
|
|||
hasAdvancedOptions={false}
|
||||
placeholder={"Get best title match..."}
|
||||
displaySeeMoreHint={false}
|
||||
displayForecastsWrapper={displayForecastsWrapperForCapture}
|
||||
displayQuestionsWrapper={displayQuestionsWrapperForCapture}
|
||||
/>
|
||||
</Layout>
|
||||
);
|
||||
|
|
|
@ -2,13 +2,13 @@ import { GetServerSideProps, NextPage } from "next";
|
|||
import Error from "next/error";
|
||||
|
||||
import { DashboardItem } from "../../../backend/dashboards";
|
||||
import { DisplayForecasts } from "../../../web/display/DisplayForecasts";
|
||||
import { FrontendForecast } from "../../../web/platforms";
|
||||
import { getDashboardForecastsByDashboardId } from "../../../web/worker/getDashboardForecasts";
|
||||
import { DisplayQuestions } from "../../../web/display/DisplayQuestions";
|
||||
import { FrontendQuestion } from "../../../web/platforms";
|
||||
import { reqToBasePath } from "../../../web/utils";
|
||||
import { getDashboardQuestionsByDashboardId } from "../../../web/worker/getDashboardQuestions";
|
||||
|
||||
interface Props {
|
||||
dashboardForecasts: FrontendForecast[];
|
||||
dashboardQuestions: FrontendQuestion[];
|
||||
dashboardItem: DashboardItem;
|
||||
numCols?: number;
|
||||
}
|
||||
|
@ -19,8 +19,8 @@ export const getServerSideProps: GetServerSideProps<Props> = async (
|
|||
const dashboardId = context.query.id as string;
|
||||
const numCols = Number(context.query.numCols);
|
||||
|
||||
const { dashboardItem, dashboardForecasts } =
|
||||
await getDashboardForecastsByDashboardId({
|
||||
const { dashboardItem, dashboardQuestions } =
|
||||
await getDashboardQuestionsByDashboardId({
|
||||
dashboardId,
|
||||
basePath: reqToBasePath(context.req), // required on server side to find the API endpoint
|
||||
});
|
||||
|
@ -31,7 +31,7 @@ export const getServerSideProps: GetServerSideProps<Props> = async (
|
|||
|
||||
return {
|
||||
props: {
|
||||
dashboardForecasts,
|
||||
dashboardQuestions,
|
||||
dashboardItem,
|
||||
numCols: !numCols ? null : numCols < 5 ? numCols : 4,
|
||||
},
|
||||
|
@ -39,7 +39,7 @@ export const getServerSideProps: GetServerSideProps<Props> = async (
|
|||
};
|
||||
|
||||
const EmbedDashboardPage: NextPage<Props> = ({
|
||||
dashboardForecasts,
|
||||
dashboardQuestions,
|
||||
dashboardItem,
|
||||
numCols,
|
||||
}) => {
|
||||
|
@ -57,9 +57,9 @@ const EmbedDashboardPage: NextPage<Props> = ({
|
|||
numCols || 3
|
||||
} gap-4 mb-6`}
|
||||
>
|
||||
<DisplayForecasts
|
||||
results={dashboardForecasts}
|
||||
numDisplay={dashboardForecasts.length}
|
||||
<DisplayQuestions
|
||||
results={dashboardQuestions}
|
||||
numDisplay={dashboardQuestions.length}
|
||||
showIdToggle={false}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -3,16 +3,16 @@ import Error from "next/error";
|
|||
import Link from "next/link";
|
||||
|
||||
import { DashboardItem } from "../../../backend/dashboards";
|
||||
import { DisplayForecasts } from "../../../web/display/DisplayForecasts";
|
||||
import { DisplayQuestions } from "../../../web/display/DisplayQuestions";
|
||||
import { InfoBox } from "../../../web/display/InfoBox";
|
||||
import { Layout } from "../../../web/display/Layout";
|
||||
import { LineHeader } from "../../../web/display/LineHeader";
|
||||
import { FrontendForecast } from "../../../web/platforms";
|
||||
import { FrontendQuestion } from "../../../web/platforms";
|
||||
import { reqToBasePath } from "../../../web/utils";
|
||||
import { getDashboardForecastsByDashboardId } from "../../../web/worker/getDashboardForecasts";
|
||||
import { getDashboardQuestionsByDashboardId } from "../../../web/worker/getDashboardQuestions";
|
||||
|
||||
interface Props {
|
||||
dashboardForecasts: FrontendForecast[];
|
||||
dashboardQuestions: FrontendQuestion[];
|
||||
dashboardItem: DashboardItem;
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,8 @@ export const getServerSideProps: GetServerSideProps<Props> = async (
|
|||
) => {
|
||||
const dashboardId = context.query.id as string;
|
||||
|
||||
const { dashboardForecasts, dashboardItem } =
|
||||
await getDashboardForecastsByDashboardId({
|
||||
const { dashboardQuestions, dashboardItem } =
|
||||
await getDashboardQuestionsByDashboardId({
|
||||
dashboardId,
|
||||
basePath: reqToBasePath(context.req), // required on server side to find the API endpoint
|
||||
});
|
||||
|
@ -33,7 +33,7 @@ export const getServerSideProps: GetServerSideProps<Props> = async (
|
|||
|
||||
return {
|
||||
props: {
|
||||
dashboardForecasts,
|
||||
dashboardQuestions,
|
||||
dashboardItem,
|
||||
},
|
||||
};
|
||||
|
@ -78,7 +78,7 @@ const DashboardMetadata: React.FC<{ dashboardItem: DashboardItem }> = ({
|
|||
|
||||
/* Body */
|
||||
const ViewDashboardPage: NextPage<Props> = ({
|
||||
dashboardForecasts,
|
||||
dashboardQuestions,
|
||||
dashboardItem,
|
||||
}) => {
|
||||
return (
|
||||
|
@ -91,9 +91,9 @@ const ViewDashboardPage: NextPage<Props> = ({
|
|||
)}
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
<DisplayForecasts
|
||||
results={dashboardForecasts}
|
||||
numDisplay={dashboardForecasts.length}
|
||||
<DisplayQuestions
|
||||
results={dashboardQuestions}
|
||||
numDisplay={dashboardQuestions.length}
|
||||
showIdToggle={false}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { NextPage } from "next";
|
||||
import React from "react";
|
||||
|
||||
import { displayForecastsWrapperForSearch } from "../web/display/displayForecastsWrappers";
|
||||
import { displayQuestionsWrapperForSearch } from "../web/display/displayQuestionsWrappers";
|
||||
import { Layout } from "../web/display/Layout";
|
||||
import { Props } from "../web/search/anySearchPage";
|
||||
import CommonDisplay from "../web/search/CommonDisplay";
|
||||
|
@ -18,7 +18,7 @@ const IndexPage: NextPage<Props> = (props) => {
|
|||
hasAdvancedOptions={true}
|
||||
placeholder={"Find forecasts about..."}
|
||||
displaySeeMoreHint={true}
|
||||
displayForecastsWrapper={displayForecastsWrapperForSearch}
|
||||
displayQuestionsWrapper={displayQuestionsWrapperForSearch}
|
||||
/>
|
||||
</Layout>
|
||||
);
|
||||
|
|
|
@ -4,12 +4,12 @@ import { GetServerSideProps, NextPage } from "next";
|
|||
import React from "react";
|
||||
|
||||
import { platforms } from "../backend/platforms";
|
||||
import { DisplayForecast } from "../web/display/DisplayForecast";
|
||||
import { FrontendForecast } from "../web/platforms";
|
||||
import { DisplayQuestion } from "../web/display/DisplayQuestion";
|
||||
import { FrontendQuestion } from "../web/platforms";
|
||||
import searchAccordingToQueryData from "../web/worker/searchAccordingToQueryData";
|
||||
|
||||
interface Props {
|
||||
results: FrontendForecast[];
|
||||
results: FrontendQuestion[];
|
||||
}
|
||||
|
||||
export const getServerSideProps: GetServerSideProps<Props> = async (
|
||||
|
@ -25,7 +25,7 @@ export const getServerSideProps: GetServerSideProps<Props> = async (
|
|||
...urlQuery,
|
||||
};
|
||||
|
||||
let results: FrontendForecast[] = [];
|
||||
let results: FrontendQuestion[] = [];
|
||||
if (initialQueryParameters.query != "") {
|
||||
results = await searchAccordingToQueryData(initialQueryParameters, 1);
|
||||
}
|
||||
|
@ -46,8 +46,8 @@ const SecretEmbedPage: NextPage<Props> = ({ results }) => {
|
|||
<div>
|
||||
<div id="secretEmbed">
|
||||
{result ? (
|
||||
<DisplayForecast
|
||||
forecast={result}
|
||||
<DisplayQuestion
|
||||
question={result}
|
||||
showTimeStamp={true}
|
||||
expandFooterToFullWidth={true}
|
||||
/>
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
import React from "react";
|
||||
|
||||
import { FrontendForecast } from "../platforms";
|
||||
import { DisplayForecast } from "./DisplayForecast";
|
||||
|
||||
interface Props {
|
||||
results: FrontendForecast[];
|
||||
numDisplay: number;
|
||||
showIdToggle: boolean;
|
||||
}
|
||||
|
||||
export const DisplayForecasts: React.FC<Props> = ({
|
||||
results,
|
||||
numDisplay,
|
||||
showIdToggle,
|
||||
}) => {
|
||||
if (!results) {
|
||||
return <></>;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{results.slice(0, numDisplay).map((result) => (
|
||||
/*let displayWithMetaculusCapture =
|
||||
fuseSearchResult.item.platform == "Metaculus"
|
||||
? metaculusEmbed(fuseSearchResult.item)
|
||||
: displayForecast({ ...fuseSearchResult.item });
|
||||
*/
|
||||
<DisplayForecast
|
||||
key={result.id}
|
||||
forecast={result}
|
||||
showTimeStamp={false}
|
||||
expandFooterToFullWidth={false}
|
||||
showIdToggle={showIdToggle}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -2,16 +2,16 @@ import domtoimage from "dom-to-image"; // https://github.com/tsayen/dom-to-image
|
|||
import { useEffect, useRef, useState } from "react";
|
||||
import { CopyToClipboard } from "react-copy-to-clipboard";
|
||||
|
||||
import { FrontendForecast } from "../platforms";
|
||||
import { FrontendQuestion } from "../platforms";
|
||||
import { uploadToImgur } from "../worker/uploadToImgur";
|
||||
import { DisplayForecast } from "./DisplayForecast";
|
||||
import { DisplayQuestion } from "./DisplayQuestion";
|
||||
|
||||
function displayOneForecastInner(result: FrontendForecast, containerRef) {
|
||||
function displayOneQuestionInner(result: FrontendQuestion, containerRef) {
|
||||
return (
|
||||
<div ref={containerRef}>
|
||||
{result ? (
|
||||
<DisplayForecast
|
||||
forecast={result}
|
||||
<DisplayQuestion
|
||||
question={result}
|
||||
showTimeStamp={true}
|
||||
expandFooterToFullWidth={true}
|
||||
/>
|
||||
|
@ -168,10 +168,10 @@ let generateMetaculusSource = (result, hasDisplayBeenCaptured) => {
|
|||
};
|
||||
|
||||
interface Props {
|
||||
result: FrontendForecast;
|
||||
result: FrontendQuestion;
|
||||
}
|
||||
|
||||
export const DisplayOneForecastForCapture: React.FC<Props> = ({ result }) => {
|
||||
export const DisplayOneQuestionForCapture: React.FC<Props> = ({ result }) => {
|
||||
const [hasDisplayBeenCaptured, setHasDisplayBeenCaptured] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -226,7 +226,7 @@ export const DisplayOneForecastForCapture: React.FC<Props> = ({ result }) => {
|
|||
return (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 w-full justify-center">
|
||||
<div className="flex col-span-1 items-center justify-center">
|
||||
{displayOneForecastInner(result, containerRef)}
|
||||
{displayOneQuestionInner(result, containerRef)}
|
||||
</div>
|
||||
<div className="flex col-span-1 items-center justify-center">
|
||||
{generateCaptureButton(result, onCaptureButtonClick)}
|
|
@ -243,7 +243,7 @@ interface Props {
|
|||
expandFooterToFullWidth: boolean;
|
||||
}
|
||||
|
||||
export const ForecastFooter: React.FC<Props> = ({
|
||||
export const QuestionFooter: React.FC<Props> = ({
|
||||
stars,
|
||||
platform,
|
||||
platformLabel,
|
|
@ -1,9 +1,9 @@
|
|||
import { FaRegClipboard } from "react-icons/fa";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
|
||||
import { FrontendForecast } from "../../platforms";
|
||||
import { FrontendQuestion } from "../../platforms";
|
||||
import { Card } from "../Card";
|
||||
import { ForecastFooter } from "./ForecastFooter";
|
||||
import { QuestionFooter } from "./QuestionFooter";
|
||||
|
||||
const truncateText = (length: number, text: string): string => {
|
||||
if (!text) {
|
||||
|
@ -268,14 +268,14 @@ const LastUpdated: React.FC<{ timestamp: string }> = ({ timestamp }) => (
|
|||
// Main component
|
||||
|
||||
interface Props {
|
||||
forecast: FrontendForecast;
|
||||
question: FrontendQuestion;
|
||||
showTimeStamp: boolean;
|
||||
expandFooterToFullWidth: boolean;
|
||||
showIdToggle?: boolean;
|
||||
}
|
||||
|
||||
export const DisplayForecast: React.FC<Props> = ({
|
||||
forecast: {
|
||||
export const DisplayQuestion: React.FC<Props> = ({
|
||||
question: {
|
||||
id,
|
||||
title,
|
||||
url,
|
||||
|
@ -372,7 +372,7 @@ export const DisplayForecast: React.FC<Props> = ({
|
|||
<LastUpdated timestamp={timestamp} />
|
||||
</div>
|
||||
<div className="w-full">
|
||||
<ForecastFooter
|
||||
<QuestionFooter
|
||||
stars={qualityindicators.stars}
|
||||
platform={platform}
|
||||
platformLabel={platformLabel || platform} // author || platformLabel,
|
33
src/web/display/DisplayQuestions.tsx
Normal file
33
src/web/display/DisplayQuestions.tsx
Normal file
|
@ -0,0 +1,33 @@
|
|||
import React from "react";
|
||||
|
||||
import { FrontendQuestion } from "../platforms";
|
||||
import { DisplayQuestion } from "./DisplayQuestion";
|
||||
|
||||
interface Props {
|
||||
results: FrontendQuestion[];
|
||||
numDisplay: number;
|
||||
showIdToggle: boolean;
|
||||
}
|
||||
|
||||
export const DisplayQuestions: React.FC<Props> = ({
|
||||
results,
|
||||
numDisplay,
|
||||
showIdToggle,
|
||||
}) => {
|
||||
if (!results) {
|
||||
return <></>;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{results.slice(0, numDisplay).map((result) => (
|
||||
<DisplayQuestion
|
||||
key={result.id}
|
||||
question={result}
|
||||
showTimeStamp={false}
|
||||
expandFooterToFullWidth={false}
|
||||
showIdToggle={showIdToggle}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -1,14 +1,14 @@
|
|||
import { DisplayForecasts } from "./DisplayForecasts";
|
||||
import { DisplayOneForecastForCapture } from "./DisplayOneForecastForCapture";
|
||||
import { DisplayOneQuestionForCapture } from "./DisplayOneQuestionForCapture";
|
||||
import { DisplayQuestions } from "./DisplayQuestions";
|
||||
|
||||
export function displayForecastsWrapperForSearch({
|
||||
export function displayQuestionsWrapperForSearch({
|
||||
results,
|
||||
numDisplay,
|
||||
showIdToggle,
|
||||
}) {
|
||||
return (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
<DisplayForecasts
|
||||
<DisplayQuestions
|
||||
results={results || []}
|
||||
numDisplay={numDisplay}
|
||||
showIdToggle={showIdToggle}
|
||||
|
@ -17,13 +17,13 @@ export function displayForecastsWrapperForSearch({
|
|||
);
|
||||
}
|
||||
|
||||
export function displayForecastsWrapperForCapture({
|
||||
export function displayQuestionsWrapperForCapture({
|
||||
results,
|
||||
whichResultToDisplayAndCapture,
|
||||
}) {
|
||||
return (
|
||||
<div className="grid grid-cols-1 w-full justify-center">
|
||||
<DisplayOneForecastForCapture
|
||||
<DisplayOneQuestionForCapture
|
||||
result={results[whichResultToDisplayAndCapture]}
|
||||
/>
|
||||
</div>
|
|
@ -1,20 +1,20 @@
|
|||
import { Forecast, PlatformConfig } from "../backend/platforms";
|
||||
import { PlatformConfig, Question } from "../backend/platforms";
|
||||
|
||||
export type FrontendForecast = Forecast & {
|
||||
export type FrontendQuestion = Question & {
|
||||
platformLabel: string;
|
||||
visualization?: any;
|
||||
};
|
||||
|
||||
// ok on client side
|
||||
export const addLabelsToForecasts = (
|
||||
forecasts: Forecast[],
|
||||
export const addLabelsToQuestions = (
|
||||
questions: Question[],
|
||||
platformsConfig: PlatformConfig[]
|
||||
): FrontendForecast[] => {
|
||||
): FrontendQuestion[] => {
|
||||
const platformNameToLabel = Object.fromEntries(
|
||||
platformsConfig.map((platform) => [platform.name, platform.label])
|
||||
);
|
||||
|
||||
return forecasts.map((result) => ({
|
||||
return questions.map((result) => ({
|
||||
...result,
|
||||
platformLabel: platformNameToLabel[result.platform] || result.platform,
|
||||
}));
|
||||
|
|
|
@ -6,7 +6,7 @@ import { MultiSelectPlatform } from "../display/MultiSelectPlatform";
|
|||
import { QueryForm } from "../display/QueryForm";
|
||||
import { SliderElement } from "../display/SliderElement";
|
||||
import { useNoInitialEffect } from "../hooks";
|
||||
import { FrontendForecast } from "../platforms";
|
||||
import { FrontendQuestion } from "../platforms";
|
||||
import searchAccordingToQueryData from "../worker/searchAccordingToQueryData";
|
||||
import { Props as AnySearchPageProps, QueryParameters } from "./anySearchPage";
|
||||
|
||||
|
@ -16,8 +16,8 @@ interface Props extends AnySearchPageProps {
|
|||
hasAdvancedOptions: boolean;
|
||||
placeholder: string;
|
||||
displaySeeMoreHint: boolean;
|
||||
displayForecastsWrapper: (opts: {
|
||||
results: FrontendForecast[];
|
||||
displayQuestionsWrapper: (opts: {
|
||||
results: FrontendQuestion[];
|
||||
numDisplay: number;
|
||||
whichResultToDisplayAndCapture: number;
|
||||
showIdToggle: boolean;
|
||||
|
@ -38,7 +38,7 @@ const CommonDisplay: React.FC<Props> = ({
|
|||
hasAdvancedOptions,
|
||||
placeholder,
|
||||
displaySeeMoreHint,
|
||||
displayForecastsWrapper,
|
||||
displayQuestionsWrapper,
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
/* States */
|
||||
|
@ -68,7 +68,7 @@ const CommonDisplay: React.FC<Props> = ({
|
|||
|
||||
const filterManually = (
|
||||
queryData: QueryParameters,
|
||||
results: FrontendForecast[]
|
||||
results: FrontendQuestion[]
|
||||
) => {
|
||||
if (
|
||||
queryData.forecastingPlatforms &&
|
||||
|
@ -99,13 +99,13 @@ const CommonDisplay: React.FC<Props> = ({
|
|||
setResults(results);
|
||||
}
|
||||
|
||||
// I don't want the function which display forecasts (displayForecasts) to change with a change in queryParameters. But I want it to have access to the queryParameters, and in particular access to queryParameters.numDisplay. Hence why this function lives inside Home.
|
||||
const getInfoToDisplayForecastsFunction = () => {
|
||||
// I don't want the component which display questions (DisplayQuestions) to change with a change in queryParameters. But I want it to have access to the queryParameters, and in particular access to queryParameters.numDisplay. Hence why this function lives inside Home.
|
||||
const getInfoToDisplayQuestionsFunction = () => {
|
||||
const numDisplayRounded =
|
||||
numDisplay % 3 != 0
|
||||
? numDisplay + (3 - (Math.round(numDisplay) % 3))
|
||||
: numDisplay;
|
||||
return displayForecastsWrapper({
|
||||
return displayQuestionsWrapper({
|
||||
results,
|
||||
numDisplay: numDisplayRounded,
|
||||
whichResultToDisplayAndCapture,
|
||||
|
@ -307,7 +307,7 @@ const CommonDisplay: React.FC<Props> = ({
|
|||
</div>
|
||||
) : null}
|
||||
|
||||
<div>{getInfoToDisplayForecastsFunction()}</div>
|
||||
<div>{getInfoToDisplayQuestionsFunction()}</div>
|
||||
|
||||
{displaySeeMoreHint &&
|
||||
(!results || (results.length != 0 && numDisplay < results.length)) ? (
|
||||
|
|
|
@ -2,7 +2,7 @@ import { GetServerSideProps } from "next";
|
|||
|
||||
import { getFrontpage } from "../../backend/frontpage";
|
||||
import { getPlatformsConfig, PlatformConfig, platforms } from "../../backend/platforms";
|
||||
import { addLabelsToForecasts, FrontendForecast } from "../platforms";
|
||||
import { addLabelsToQuestions, FrontendQuestion } from "../platforms";
|
||||
import searchAccordingToQueryData from "../worker/searchAccordingToQueryData";
|
||||
|
||||
/* Common code for / and /capture */
|
||||
|
@ -15,8 +15,8 @@ export interface QueryParameters {
|
|||
}
|
||||
|
||||
export interface Props {
|
||||
defaultResults: FrontendForecast[];
|
||||
initialResults: FrontendForecast[];
|
||||
defaultResults: FrontendQuestion[];
|
||||
initialResults: FrontendQuestion[];
|
||||
initialQueryParameters: QueryParameters;
|
||||
defaultQueryParameters: QueryParameters;
|
||||
initialNumDisplay: number;
|
||||
|
@ -61,7 +61,7 @@ export const getServerSideProps: GetServerSideProps<Props> = async (
|
|||
const defaultNumDisplay = 21;
|
||||
const initialNumDisplay = Number(urlQuery.numDisplay) || defaultNumDisplay;
|
||||
|
||||
const defaultResults = addLabelsToForecasts(
|
||||
const defaultResults = addLabelsToQuestions(
|
||||
await getFrontpage(),
|
||||
platformsConfig
|
||||
);
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
import axios from "axios";
|
||||
|
||||
import { DashboardItem } from "../../backend/dashboards";
|
||||
import { Forecast, getPlatformsConfig } from "../../backend/platforms";
|
||||
import { addLabelsToForecasts, FrontendForecast } from "../platforms";
|
||||
import { getPlatformsConfig, Question } from "../../backend/platforms";
|
||||
import { addLabelsToQuestions, FrontendQuestion } from "../platforms";
|
||||
|
||||
export async function getDashboardForecastsByDashboardId({
|
||||
export async function getDashboardQuestionsByDashboardId({
|
||||
dashboardId,
|
||||
basePath,
|
||||
}: {
|
||||
dashboardId: string;
|
||||
basePath?: string;
|
||||
}): Promise<{
|
||||
dashboardForecasts: FrontendForecast[];
|
||||
dashboardQuestions: FrontendQuestion[];
|
||||
dashboardItem: DashboardItem;
|
||||
}> {
|
||||
console.log("getDashboardForecastsByDashboardId: ");
|
||||
console.log("getDashboardQuestionsByDashboardId: ");
|
||||
if (typeof window === undefined && !basePath) {
|
||||
throw new Error("`basePath` option is required on server side");
|
||||
}
|
||||
|
||||
let dashboardForecasts: Forecast[] = [];
|
||||
let dashboardQuestions: Question[] = [];
|
||||
let dashboardItem: DashboardItem | null = null;
|
||||
try {
|
||||
let { data } = await axios({
|
||||
|
@ -31,18 +31,18 @@ export async function getDashboardForecastsByDashboardId({
|
|||
});
|
||||
console.log(data);
|
||||
|
||||
dashboardForecasts = data.dashboardContents;
|
||||
dashboardQuestions = data.dashboardContents;
|
||||
dashboardItem = data.dashboardItem as DashboardItem;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
const labeledDashboardForecasts = addLabelsToForecasts(
|
||||
dashboardForecasts,
|
||||
const labeledDashboardQuestions = addLabelsToQuestions(
|
||||
dashboardQuestions,
|
||||
getPlatformsConfig({ withGuesstimate: false })
|
||||
);
|
||||
|
||||
return {
|
||||
dashboardForecasts: labeledDashboardForecasts,
|
||||
dashboardQuestions: labeledDashboardQuestions,
|
||||
dashboardItem,
|
||||
};
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import { FrontendForecast } from "../platforms";
|
||||
import { FrontendQuestion } from "../platforms";
|
||||
import { QueryParameters } from "../search/anySearchPage";
|
||||
import searchGuesstimate from "./searchGuesstimate";
|
||||
import searchWithAlgolia from "./searchWithAlgolia";
|
||||
|
@ -6,8 +6,8 @@ import searchWithAlgolia from "./searchWithAlgolia";
|
|||
export default async function searchAccordingToQueryData(
|
||||
queryData: QueryParameters,
|
||||
limit: number
|
||||
): Promise<FrontendForecast[]> {
|
||||
let results: FrontendForecast[] = [];
|
||||
): Promise<FrontendQuestion[]> {
|
||||
let results: FrontendQuestion[] = [];
|
||||
|
||||
try {
|
||||
// defs
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* Imports */
|
||||
import axios from "axios";
|
||||
|
||||
import { FrontendForecast } from "../platforms";
|
||||
import { FrontendQuestion } from "../platforms";
|
||||
|
||||
/* Definitions */
|
||||
let urlEndPoint =
|
||||
|
@ -11,7 +11,7 @@ let urlEndPoint =
|
|||
|
||||
export default async function searchGuesstimate(
|
||||
query
|
||||
): Promise<FrontendForecast[]> {
|
||||
): Promise<FrontendQuestion[]> {
|
||||
let response = await axios({
|
||||
url: urlEndPoint,
|
||||
// credentials: "omit",
|
||||
|
@ -31,7 +31,7 @@ export default async function searchGuesstimate(
|
|||
});
|
||||
|
||||
const models: any[] = response.data.hits;
|
||||
const mappedModels: FrontendForecast[] = models.map((model, index) => {
|
||||
const mappedModels: FrontendQuestion[] = models.map((model, index) => {
|
||||
let description = model.description
|
||||
? model.description.replace(/\n/g, " ").replace(/ /g, " ")
|
||||
: "";
|
||||
|
@ -57,7 +57,7 @@ export default async function searchGuesstimate(
|
|||
|
||||
// filter for duplicates. Surprisingly common.
|
||||
let uniqueTitles = [];
|
||||
let uniqueModels: FrontendForecast[] = [];
|
||||
let uniqueModels: FrontendQuestion[] = [];
|
||||
for (let model of mappedModels) {
|
||||
if (!uniqueTitles.includes(model.title) && !model.title.includes("copy")) {
|
||||
uniqueModels.push(model);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import algoliasearch from "algoliasearch";
|
||||
|
||||
import { FrontendForecast } from "../platforms";
|
||||
import { FrontendQuestion } from "../platforms";
|
||||
|
||||
const client = algoliasearch(
|
||||
process.env.NEXT_PUBLIC_ALGOLIA_APP_ID,
|
||||
|
@ -82,8 +82,8 @@ export default async function searchWithAlgolia({
|
|||
starsThreshold,
|
||||
filterByPlatforms,
|
||||
forecastsThreshold,
|
||||
}): Promise<FrontendForecast[]> {
|
||||
let response = await index.search<FrontendForecast>(queryString, {
|
||||
}): Promise<FrontendQuestion[]> {
|
||||
let response = await index.search<FrontendQuestion>(queryString, {
|
||||
hitsPerPage,
|
||||
filters: buildFilter({
|
||||
starsThreshold,
|
||||
|
@ -93,7 +93,7 @@ export default async function searchWithAlgolia({
|
|||
//facetFilters: buildFacetFilter({filterByPlatforms}),
|
||||
getRankingInfo: true,
|
||||
});
|
||||
let results: FrontendForecast[] = response.hits;
|
||||
let results: FrontendQuestion[] = response.hits;
|
||||
|
||||
let recursionError = ["metaforecast", "metaforecasts", "metaforecasting"];
|
||||
if (
|
||||
|
|
Loading…
Reference in New Issue
Block a user