feat: chats (merge code from #63)

This commit is contained in:
Vyacheslav Matyukhin 2022-04-27 23:51:00 +04:00
parent 692dee183e
commit 55b320c528
No known key found for this signature in database
GPG Key ID: 3D2A774C5489F96C
20 changed files with 1305 additions and 73 deletions

1001
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -89,7 +89,8 @@
"ts-node": "^10.7.0", "ts-node": "^10.7.0",
"tunnel": "^0.0.6", "tunnel": "^0.0.6",
"urql": "^2.2.0", "urql": "^2.2.0",
"urql-custom-scalars-exchange": "^0.1.5" "urql-custom-scalars-exchange": "^0.1.5",
"victory": "^36.3.2"
}, },
"devDependencies": { "devDependencies": {
"@graphql-codegen/cli": "^2.6.2", "@graphql-codegen/cli": "^2.6.2",

View File

@ -5,7 +5,8 @@ import React from "react";
import { platforms } from "../backend/platforms"; import { platforms } from "../backend/platforms";
import { DisplayQuestion } from "../web/display/DisplayQuestion"; import { DisplayQuestion } from "../web/display/DisplayQuestion";
import { QuestionFragment, SearchDocument } from "../web/search/queries.generated"; import { QuestionFragment } from "../web/fragments.generated";
import { SearchDocument } from "../web/search/queries.generated";
import { ssrUrql } from "../web/urql"; import { ssrUrql } from "../web/urql";
interface Props { interface Props {

View File

@ -1,7 +1,7 @@
import * as Types from '../../graphql/types.generated'; import * as Types from '../../graphql/types.generated';
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
import { QuestionFragmentDoc } from '../search/queries.generated'; import { QuestionFragmentDoc } from '../fragments.generated';
export type DashboardFragment = { __typename?: 'Dashboard', id: string, title: string, description: string, creator: string, questions: Array<{ __typename?: 'Question', id: string, url: string, title: string, description: string, timestamp: number, visualization?: string | null, options: Array<{ __typename?: 'ProbabilityOption', name?: string | null, probability?: number | null }>, platform: { __typename?: 'Platform', id: string, label: string }, qualityIndicators: { __typename?: 'QualityIndicators', stars: number, numForecasts?: number | null, numForecasters?: number | null, volume?: number | null, spread?: number | null, sharesVolume?: number | null, openInterest?: number | null, liquidity?: number | null, tradeVolume?: number | null } }> }; export type DashboardFragment = { __typename?: 'Dashboard', id: string, title: string, description: string, creator: string, questions: Array<{ __typename?: 'Question', id: string, url: string, title: string, description: string, timestamp: number, visualization?: string | null, options: Array<{ __typename?: 'ProbabilityOption', name?: string | null, probability?: number | null }>, platform: { __typename?: 'Platform', id: string, label: string }, qualityIndicators: { __typename?: 'QualityIndicators', stars: number, numForecasts?: number | null, numForecasters?: number | null, volume?: number | null, spread?: number | null, sharesVolume?: number | null, openInterest?: number | null, liquidity?: number | null, tradeVolume?: number | null } }> };
export type DashboardByIdQueryVariables = Types.Exact<{ export type DashboardByIdQueryVariables = Types.Exact<{

View File

@ -2,7 +2,7 @@ import domtoimage from "dom-to-image"; // https://github.com/tsayen/dom-to-image
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { CopyToClipboard } from "react-copy-to-clipboard"; import { CopyToClipboard } from "react-copy-to-clipboard";
import { QuestionFragment } from "../search/queries.generated"; import { QuestionFragment } from "../fragments.generated";
import { uploadToImgur } from "../worker/uploadToImgur"; import { uploadToImgur } from "../worker/uploadToImgur";
import { DisplayQuestion } from "./DisplayQuestion"; import { DisplayQuestion } from "./DisplayQuestion";

View File

@ -1,4 +1,4 @@
import { QuestionFragment } from "../../search/queries.generated"; import { QuestionFragment } from "../../fragments.generated";
type QualityIndicator = QuestionFragment["qualityIndicators"]; type QualityIndicator = QuestionFragment["qualityIndicators"];
type IndicatorName = keyof QualityIndicator; type IndicatorName = keyof QualityIndicator;

View File

@ -3,8 +3,9 @@ import { FaExpand } from "react-icons/fa";
import ReactMarkdown from "react-markdown"; import ReactMarkdown from "react-markdown";
import { CopyText } from "../../common/CopyText"; import { CopyText } from "../../common/CopyText";
import { QuestionFragment } from "../../fragments.generated";
import { QuestionOptions } from "../../questions/components/QuestionOptions"; import { QuestionOptions } from "../../questions/components/QuestionOptions";
import { QuestionFragment } from "../../search/queries.generated"; import { cleanText } from "../../utils";
import { Card } from "../Card"; import { Card } from "../Card";
import { QuestionFooter } from "./QuestionFooter"; import { QuestionFooter } from "./QuestionFooter";
@ -68,24 +69,6 @@ if (!String.prototype.replaceAll) {
}; };
} }
const cleanText = (text: string): string => {
// Note: should no longer be necessary
let textString = !!text ? text : "";
textString = textString
.replaceAll("] (", "](")
.replaceAll(") )", "))")
.replaceAll("( [", "([")
.replaceAll(") ,", "),")
.replaceAll("==", "") // Denotes a title in markdown
.replaceAll("Background\n", "")
.replaceAll("Context\n", "")
.replaceAll("--- \n", "- ")
.replaceAll(/\[(.*?)\]\(.*?\)/g, "$1");
textString = textString.slice(0, 1) == "=" ? textString.slice(1) : textString;
//console.log(textString)
return textString;
};
// Auxiliary components // Auxiliary components
const DisplayMarkdown: React.FC<{ description: string }> = ({ const DisplayMarkdown: React.FC<{ description: string }> = ({

View File

@ -1,6 +1,6 @@
import React from "react"; import React from "react";
import { QuestionFragment } from "../search/queries.generated"; import { QuestionFragment } from "../fragments.generated";
import { DisplayQuestion } from "./DisplayQuestion"; import { DisplayQuestion } from "./DisplayQuestion";
interface Props { interface Props {

View File

@ -0,0 +1,9 @@
import * as Types from '../graphql/types.generated';
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
export type QuestionFragment = { __typename?: 'Question', id: string, url: string, title: string, description: string, timestamp: number, visualization?: string | null, options: Array<{ __typename?: 'ProbabilityOption', name?: string | null, probability?: number | null }>, platform: { __typename?: 'Platform', id: string, label: string }, qualityIndicators: { __typename?: 'QualityIndicators', stars: number, numForecasts?: number | null, numForecasters?: number | null, volume?: number | null, spread?: number | null, sharesVolume?: number | null, openInterest?: number | null, liquidity?: number | null, tradeVolume?: number | null } };
export type QuestionWithHistoryFragment = { __typename?: 'Question', id: string, url: string, title: string, description: string, timestamp: number, visualization?: string | null, history: Array<{ __typename?: 'History', timestamp: number, options: Array<{ __typename?: 'ProbabilityOption', name?: string | null, probability?: number | null }> }>, options: Array<{ __typename?: 'ProbabilityOption', name?: string | null, probability?: number | null }>, platform: { __typename?: 'Platform', id: string, label: string }, qualityIndicators: { __typename?: 'QualityIndicators', stars: number, numForecasts?: number | null, numForecasters?: number | null, volume?: number | null, spread?: number | null, sharesVolume?: number | null, openInterest?: number | null, liquidity?: number | null, tradeVolume?: number | null } };
export const QuestionFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Question"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Question"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"url"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"timestamp"}},{"kind":"Field","name":{"kind":"Name","value":"options"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"probability"}}]}},{"kind":"Field","name":{"kind":"Name","value":"platform"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"label"}}]}},{"kind":"Field","name":{"kind":"Name","value":"qualityIndicators"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"stars"}},{"kind":"Field","name":{"kind":"Name","value":"numForecasts"}},{"kind":"Field","name":{"kind":"Name","value":"numForecasters"}},{"kind":"Field","name":{"kind":"Name","value":"volume"}},{"kind":"Field","name":{"kind":"Name","value":"spread"}},{"kind":"Field","name":{"kind":"Name","value":"sharesVolume"}},{"kind":"Field","name":{"kind":"Name","value":"openInterest"}},{"kind":"Field","name":{"kind":"Name","value":"liquidity"}},{"kind":"Field","name":{"kind":"Name","value":"tradeVolume"}}]}},{"kind":"Field","name":{"kind":"Name","value":"visualization"}}]}}]} as unknown as DocumentNode<QuestionFragment, unknown>;
export const QuestionWithHistoryFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"QuestionWithHistory"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Question"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Question"}},{"kind":"Field","name":{"kind":"Name","value":"history"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"timestamp"}},{"kind":"Field","name":{"kind":"Name","value":"options"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"probability"}}]}}]}}]}},...QuestionFragmentDoc.definitions]} as unknown as DocumentNode<QuestionWithHistoryFragment, unknown>;

38
src/web/fragments.graphql Normal file
View File

@ -0,0 +1,38 @@
fragment Question on Question {
id
url
title
description
timestamp
options {
name
probability
}
platform {
id
label
}
qualityIndicators {
stars
numForecasts
numForecasters
volume
spread
sharesVolume
openInterest
liquidity
tradeVolume
}
visualization
}
fragment QuestionWithHistory on Question {
...Question
history {
timestamp
options {
name
probability
}
}
}

View File

@ -0,0 +1,207 @@
import React from "react";
import {
VictoryAxis, VictoryChart, VictoryGroup, VictoryLabel, VictoryLegend, VictoryScatter,
VictoryTheme, VictoryTooltip, VictoryVoronoiContainer
} from "victory";
import { QuestionWithHistoryFragment } from "../../fragments.generated";
interface Props {
question: QuestionWithHistoryFragment;
}
const buildDataset = (n, fn) => {
return Array.from(Array(n).keys()).map((x) => ({
date: x,
probability: fn(x),
}));
};
let getDate0 = (x) => {
// for fake data
let date = new Date(x);
return date.toISOString().slice(5, 10).replaceAll("-", "/");
};
let timestampToString = (x) => {
// for real timestamps
console.log(x);
let date = new Date(Date.parse(x));
let dayOfMonth = date.getDate();
let month = date.getMonth() + 1;
let year = date.getFullYear();
let dateString = `${("0" + dayOfMonth).slice(-2)}/${("0" + month).slice(
-2
)}/${year.toString().slice(-2)}`;
console.log(dateString);
return dateString;
};
let dataAsXy = (data) =>
data.map((datum) => ({
x: timestampToString(datum.date), //getDate(datum.date * (1000 * 60 * 60 * 24)),
y: datum.probability,
}));
const colors = ["dodgerblue", "crimson", "seagreen", "darkviolet", "turquoise"];
const getVictoryGroup = (data, i) => {
return (
<VictoryGroup color={colors[i] || "darkgray"} data={dataAsXy(data)}>
<VictoryScatter
//style={{ labels: { display: "none" } }}
size={({ active }) => (active ? 3.75 : 3)}
//labels={() => null}
//labelComponent={<span></span>}
/>
{/* Doesn't work well with tooltips
<VictoryLine
name={`line${i}`}
//style={{ labels: { display: "none" } }}
//labels={() => null}
//labelComponent={<span></span>}
/>
*/}
</VictoryGroup>
);
};
export const HistoryChart: React.FC<Props> = ({ question }) => {
let height = 400;
let width = 500;
let padding = { top: 20, bottom: 50, left: 50, right: 100 };
// let dataSetsNames = ["Yes", "No", "Maybe", "Perhaps", "Possibly"];
let dataSetsNames = [];
question.history.forEach((item) => {
let optionNames = item.options.map((option) => option.name);
dataSetsNames.push(...optionNames);
});
dataSetsNames = [...new Set(dataSetsNames)].slice(0, 5); // take the first 5
let dataSets = [];
dataSetsNames.forEach((name) => {
let newDataset = [];
question.history.forEach((item) => {
let relevantItemsArray = item.options.filter((x) => x.name == name);
let date = new Date(item.timestamp * 1000);
if (relevantItemsArray.length == 1) {
let relevantItem = relevantItemsArray[0];
// if (relevantItem.type == "PROBABILITY") {
let result = {
date,
probability: relevantItem.probability,
};
newDataset.push(result);
// }
}
});
dataSets.push(newDataset);
});
let dataSetsLength = dataSets.length;
return (
<div className="grid grid-rows-1 bg-white p-10">
<a
className="textinherit no-underline"
href={question.url}
target="_blank"
>
<h1 className="text-3xl font-normal text-center mt-5">
{question.title}
</h1>
</a>
<VictoryChart
domainPadding={20}
padding={padding}
theme={VictoryTheme.material}
height={height}
width={width}
containerComponent={
<VictoryVoronoiContainer
labels={({ datum }) => `${datum.x}: ${Math.round(datum.y * 100)}%`}
labelComponent={
<VictoryTooltip
pointerLength={0}
dy={-12}
style={{
fontSize: 10,
fill: "black",
strokeWidth: 0.05,
}}
flyoutStyle={{
stroke: "black",
fill: "white",
}}
flyoutWidth={80}
cornerRadius={0}
flyoutPadding={7}
/>
}
voronoiBlacklist={
["line0", "line1", "line2", "line3", "line4"]
//Array.from(Array(5).keys()).map((x, i) => `line${i}`)
// see: https://github.com/FormidableLabs/victory/issues/545
}
/>
}
domain={{
y: [0, 1],
}}
>
<VictoryLegend
x={width - 100}
y={height / 2 - 18 - (dataSetsLength - 1) * 13}
orientation="vertical"
gutter={20}
style={{ border: { stroke: "black" }, title: { fontSize: 20 } }}
data={
Array.from(Array(dataSetsLength).keys()).map((i) => ({
name: dataSetsNames[i],
symbol: { fill: colors[i] },
}))
/*[
{ name: "One", symbol: { fill: "tomato", type: "star" } },
{ name: "Two", symbol: { fill: "orange" } },
{ name: "Three", symbol: { fill: "gold" } },
]*/
}
/>
{dataSets.slice(0, 5).map((dataset, i) => getVictoryGroup(dataset, i))}
<VictoryAxis
// tickValues specifies both the number of ticks and where
// they are placed on the axis
// tickValues={dataAsXy.map((datum) => datum.x)}
// tickFormat={dataAsXy.map((datum) => datum.x)}
tickCount={7}
style={{
grid: { stroke: null, strokeWidth: 0.5 },
}}
//axisLabelComponent={
// <VictoryLabel dy={40} style={{ fontSize: 10, fill: "gray" }} />
//}
// label="Date (dd/mm/yy)"
tickLabelComponent={
<VictoryLabel
dy={0}
angle={-30}
style={{ fontSize: 10, fill: "gray" }}
/>
}
/>
<VictoryAxis
dependentAxis
// tickFormat specifies how ticks should be displayed
tickFormat={(x) => `${x * 100}%`}
style={{
grid: { stroke: "#D3D3D3", strokeWidth: 0.5 },
}}
tickLabelComponent={
<VictoryLabel dy={0} style={{ fontSize: 10, fill: "gray" }} />
}
/>
</VictoryChart>
</div>
);
};

View File

@ -1,4 +1,4 @@
import { QuestionFragment } from "../../search/queries.generated"; import { QuestionFragment } from "../../fragments.generated";
import { formatProbability } from "../utils"; import { formatProbability } from "../utils";
type Option = QuestionFragment["options"][0]; type Option = QuestionFragment["options"][0];

View File

@ -5,10 +5,11 @@ import { Query } from "../../common/Query";
import { Card } from "../../display/Card"; import { Card } from "../../display/Card";
import { QuestionFooter } from "../../display/DisplayQuestion/QuestionFooter"; import { QuestionFooter } from "../../display/DisplayQuestion/QuestionFooter";
import { Layout } from "../../display/Layout"; import { Layout } from "../../display/Layout";
import { QuestionFragment } from "../../search/queries.generated"; import { QuestionWithHistoryFragment } from "../../fragments.generated";
import { ssrUrql } from "../../urql"; import { ssrUrql } from "../../urql";
import { HistoryChart } from "../components/HistoryChart";
import { QuestionOptions } from "../components/QuestionOptions"; import { QuestionOptions } from "../components/QuestionOptions";
import { QuestionByIdDocument } from "../queries.generated"; import { QuestionPageDocument } from "../queries.generated";
interface Props { interface Props {
id: string; id: string;
@ -21,7 +22,7 @@ export const getServerSideProps: GetServerSideProps<Props> = async (
const id = context.query.id as string; const id = context.query.id as string;
const question = const question =
(await client.query(QuestionByIdDocument, { id }).toPromise()).data (await client.query(QuestionPageDocument, { id }).toPromise()).data
?.result || null; ?.result || null;
if (!question) { if (!question) {
@ -36,9 +37,9 @@ export const getServerSideProps: GetServerSideProps<Props> = async (
}; };
}; };
const QuestionCardContents: React.FC<{ question: QuestionFragment }> = ({ const QuestionCardContents: React.FC<{
question, question: QuestionWithHistoryFragment;
}) => ( }> = ({ question }) => (
<div className="space-y-4"> <div className="space-y-4">
<h1> <h1>
<a <a
@ -55,6 +56,8 @@ const QuestionCardContents: React.FC<{ question: QuestionFragment }> = ({
<ReactMarkdown linkTarget="_blank" className="font-normal"> <ReactMarkdown linkTarget="_blank" className="font-normal">
{question.description} {question.description}
</ReactMarkdown> </ReactMarkdown>
<HistoryChart question={question} />
</div> </div>
); );
@ -63,7 +66,7 @@ const QuestionPage: NextPage<Props> = ({ id }) => {
<Layout page="question"> <Layout page="question">
<div className="max-w-2xl mx-auto"> <div className="max-w-2xl mx-auto">
<Card highlightOnHover={false}> <Card highlightOnHover={false}>
<Query document={QuestionByIdDocument} variables={{ id }}> <Query document={QuestionPageDocument} variables={{ id }}>
{({ data }) => <QuestionCardContents question={data.result} />} {({ data }) => <QuestionCardContents question={data.result} />}
</Query> </Query>
</Card> </Card>

View File

@ -1,13 +1,13 @@
import * as Types from '../../graphql/types.generated'; import * as Types from '../../graphql/types.generated';
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
import { QuestionFragmentDoc } from '../search/queries.generated'; import { QuestionWithHistoryFragmentDoc } from '../fragments.generated';
export type QuestionByIdQueryVariables = Types.Exact<{ export type QuestionPageQueryVariables = Types.Exact<{
id: Types.Scalars['ID']; id: Types.Scalars['ID'];
}>; }>;
export type QuestionByIdQuery = { __typename?: 'Query', result: { __typename?: 'Question', id: string, url: string, title: string, description: string, timestamp: number, visualization?: string | null, options: Array<{ __typename?: 'ProbabilityOption', name?: string | null, probability?: number | null }>, platform: { __typename?: 'Platform', id: string, label: string }, qualityIndicators: { __typename?: 'QualityIndicators', stars: number, numForecasts?: number | null, numForecasters?: number | null, volume?: number | null, spread?: number | null, sharesVolume?: number | null, openInterest?: number | null, liquidity?: number | null, tradeVolume?: number | null } } }; export type QuestionPageQuery = { __typename?: 'Query', result: { __typename?: 'Question', id: string, url: string, title: string, description: string, timestamp: number, visualization?: string | null, history: Array<{ __typename?: 'History', timestamp: number, options: Array<{ __typename?: 'ProbabilityOption', name?: string | null, probability?: number | null }> }>, options: Array<{ __typename?: 'ProbabilityOption', name?: string | null, probability?: number | null }>, platform: { __typename?: 'Platform', id: string, label: string }, qualityIndicators: { __typename?: 'QualityIndicators', stars: number, numForecasts?: number | null, numForecasters?: number | null, volume?: number | null, spread?: number | null, sharesVolume?: number | null, openInterest?: number | null, liquidity?: number | null, tradeVolume?: number | null } } };
export const QuestionByIdDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"QuestionById"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"result"},"name":{"kind":"Name","value":"question"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Question"}}]}}]}},...QuestionFragmentDoc.definitions]} as unknown as DocumentNode<QuestionByIdQuery, QuestionByIdQueryVariables>; export const QuestionPageDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"QuestionPage"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"result"},"name":{"kind":"Name","value":"question"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"QuestionWithHistory"}}]}}]}},...QuestionWithHistoryFragmentDoc.definitions]} as unknown as DocumentNode<QuestionPageQuery, QuestionPageQueryVariables>;

View File

@ -1,5 +1,5 @@
query QuestionById($id: ID!) { query QuestionPage($id: ID!) {
result: question(id: $id) { result: question(id: $id) {
...Question ...QuestionWithHistory
} }
} }

View File

@ -6,9 +6,10 @@ import { ButtonsForStars } from "../display/ButtonsForStars";
import { MultiSelectPlatform } from "../display/MultiSelectPlatform"; import { MultiSelectPlatform } from "../display/MultiSelectPlatform";
import { QueryForm } from "../display/QueryForm"; import { QueryForm } from "../display/QueryForm";
import { SliderElement } from "../display/SliderElement"; import { SliderElement } from "../display/SliderElement";
import { QuestionFragment } from "../fragments.generated";
import { useIsFirstRender, useNoInitialEffect } from "../hooks"; import { useIsFirstRender, useNoInitialEffect } from "../hooks";
import { Props as AnySearchPageProps, QueryParameters } from "./anySearchPage"; import { Props as AnySearchPageProps, QueryParameters } from "./anySearchPage";
import { QuestionFragment, SearchDocument } from "./queries.generated"; import { SearchDocument } from "./queries.generated";
interface Props extends AnySearchPageProps { interface Props extends AnySearchPageProps {
hasSearchbar: boolean; hasSearchbar: boolean;

View File

@ -1,8 +1,9 @@
import { GetServerSideProps } from "next"; import { GetServerSideProps } from "next";
import { getPlatformsConfig, PlatformConfig, platforms } from "../../backend/platforms"; import { getPlatformsConfig, PlatformConfig, platforms } from "../../backend/platforms";
import { QuestionFragment } from "../fragments.generated";
import { ssrUrql } from "../urql"; import { ssrUrql } from "../urql";
import { FrontpageDocument, QuestionFragment, SearchDocument } from "./queries.generated"; import { FrontpageDocument, SearchDocument } from "./queries.generated";
/* Common code for / and /capture */ /* Common code for / and /capture */

View File

@ -1,8 +1,7 @@
import * as Types from '../../graphql/types.generated'; import * as Types from '../../graphql/types.generated';
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
export type QuestionFragment = { __typename?: 'Question', id: string, url: string, title: string, description: string, timestamp: number, visualization?: string | null, options: Array<{ __typename?: 'ProbabilityOption', name?: string | null, probability?: number | null }>, platform: { __typename?: 'Platform', id: string, label: string }, qualityIndicators: { __typename?: 'QualityIndicators', stars: number, numForecasts?: number | null, numForecasters?: number | null, volume?: number | null, spread?: number | null, sharesVolume?: number | null, openInterest?: number | null, liquidity?: number | null, tradeVolume?: number | null } }; import { QuestionFragmentDoc } from '../fragments.generated';
export type FrontpageQueryVariables = Types.Exact<{ [key: string]: never; }>; export type FrontpageQueryVariables = Types.Exact<{ [key: string]: never; }>;
@ -15,6 +14,6 @@ export type SearchQueryVariables = Types.Exact<{
export type SearchQuery = { __typename?: 'Query', result: Array<{ __typename?: 'Question', id: string, url: string, title: string, description: string, timestamp: number, visualization?: string | null, options: Array<{ __typename?: 'ProbabilityOption', name?: string | null, probability?: number | null }>, platform: { __typename?: 'Platform', id: string, label: string }, qualityIndicators: { __typename?: 'QualityIndicators', stars: number, numForecasts?: number | null, numForecasters?: number | null, volume?: number | null, spread?: number | null, sharesVolume?: number | null, openInterest?: number | null, liquidity?: number | null, tradeVolume?: number | null } }> }; export type SearchQuery = { __typename?: 'Query', result: Array<{ __typename?: 'Question', id: string, url: string, title: string, description: string, timestamp: number, visualization?: string | null, options: Array<{ __typename?: 'ProbabilityOption', name?: string | null, probability?: number | null }>, platform: { __typename?: 'Platform', id: string, label: string }, qualityIndicators: { __typename?: 'QualityIndicators', stars: number, numForecasts?: number | null, numForecasters?: number | null, volume?: number | null, spread?: number | null, sharesVolume?: number | null, openInterest?: number | null, liquidity?: number | null, tradeVolume?: number | null } }> };
export const QuestionFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"Question"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Question"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"url"}},{"kind":"Field","name":{"kind":"Name","value":"title"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"timestamp"}},{"kind":"Field","name":{"kind":"Name","value":"options"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"probability"}}]}},{"kind":"Field","name":{"kind":"Name","value":"platform"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"label"}}]}},{"kind":"Field","name":{"kind":"Name","value":"qualityIndicators"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"stars"}},{"kind":"Field","name":{"kind":"Name","value":"numForecasts"}},{"kind":"Field","name":{"kind":"Name","value":"numForecasters"}},{"kind":"Field","name":{"kind":"Name","value":"volume"}},{"kind":"Field","name":{"kind":"Name","value":"spread"}},{"kind":"Field","name":{"kind":"Name","value":"sharesVolume"}},{"kind":"Field","name":{"kind":"Name","value":"openInterest"}},{"kind":"Field","name":{"kind":"Name","value":"liquidity"}},{"kind":"Field","name":{"kind":"Name","value":"tradeVolume"}}]}},{"kind":"Field","name":{"kind":"Name","value":"visualization"}}]}}]} as unknown as DocumentNode<QuestionFragment, unknown>;
export const FrontpageDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Frontpage"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"result"},"name":{"kind":"Name","value":"frontpage"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Question"}}]}}]}},...QuestionFragmentDoc.definitions]} as unknown as DocumentNode<FrontpageQuery, FrontpageQueryVariables>; export const FrontpageDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Frontpage"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"result"},"name":{"kind":"Name","value":"frontpage"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Question"}}]}}]}},...QuestionFragmentDoc.definitions]} as unknown as DocumentNode<FrontpageQuery, FrontpageQueryVariables>;
export const SearchDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Search"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SearchInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"result"},"name":{"kind":"Name","value":"searchQuestions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Question"}}]}}]}},...QuestionFragmentDoc.definitions]} as unknown as DocumentNode<SearchQuery, SearchQueryVariables>; export const SearchDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Search"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"SearchInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","alias":{"kind":"Name","value":"result"},"name":{"kind":"Name","value":"searchQuestions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"Question"}}]}}]}},...QuestionFragmentDoc.definitions]} as unknown as DocumentNode<SearchQuery, SearchQueryVariables>;

View File

@ -1,31 +1,3 @@
fragment Question on Question {
id
url
title
description
timestamp
options {
name
probability
}
platform {
id
label
}
qualityIndicators {
stars
numForecasts
numForecasters
volume
spread
sharesVolume
openInterest
liquidity
tradeVolume
}
visualization
}
query Frontpage { query Frontpage {
result: frontpage { result: frontpage {
...Question ...Question

View File

@ -10,3 +10,21 @@ export const getBasePath = () => {
return "http://localhost:3000"; return "http://localhost:3000";
}; };
export const cleanText = (text: string): string => {
// Note: should no longer be necessary
let textString = !!text ? text : "";
textString = textString
.replaceAll("] (", "](")
.replaceAll(") )", "))")
.replaceAll("( [", "([")
.replaceAll(") ,", "),")
.replaceAll("==", "") // Denotes a title in markdown
.replaceAll("Background\n", "")
.replaceAll("Context\n", "")
.replaceAll("--- \n", "- ")
.replaceAll(/\[(.*?)\]\(.*?\)/g, "$1");
textString = textString.slice(0, 1) == "=" ? textString.slice(1) : textString;
//console.log(textString)
return textString;
};