refactor: some typescript improvements

This commit is contained in:
Vyacheslav Matyukhin 2022-05-09 21:37:28 +04:00
parent 44fbd0cd2b
commit 439a9045da
No known key found for this signature in database
GPG Key ID: 3D2A774C5489F96C
12 changed files with 79 additions and 74 deletions

View File

@ -2,7 +2,7 @@ import axios from "axios";
import { applyIfSecretExists } from "../utils/getSecrets";
async function rebuildNetlifySiteWithNewData_inner(cookie) {
async function rebuildNetlifySiteWithNewData_inner(cookie: string) {
let payload = {};
let response = await axios.post(cookie, payload);
let data = response.data;
@ -10,6 +10,6 @@ async function rebuildNetlifySiteWithNewData_inner(cookie) {
}
export async function rebuildNetlifySiteWithNewData() {
let cookie = process.env.REBUIDNETLIFYHOOKURL;
const cookie = process.env.REBUIDNETLIFYHOOKURL || "";
await applyIfSecretExists(cookie, rebuildNetlifySiteWithNewData_inner);
}

View File

@ -8,10 +8,10 @@ import { FetchedQuestion, Platform } from "./";
const platformName = "betfair";
/* Definitions */
let endpoint = process.env.SECRET_BETFAIR_ENDPOINT;
const endpoint = process.env.SECRET_BETFAIR_ENDPOINT;
/* Utilities */
let arraysEqual = (a, b) => {
const arraysEqual = (a: string[], b: string[]) => {
if (a === b) return true;
if (a == null || b == null) return false;
if (a.length !== b.length) return false;
@ -26,7 +26,8 @@ let arraysEqual = (a, b) => {
}
return true;
};
let mergeRunners = (runnerCatalog, runnerBook) => {
const mergeRunners = (runnerCatalog, runnerBook) => {
let keys = Object.keys(runnerCatalog);
let result = [];
for (let key of keys) {

View File

@ -8,8 +8,8 @@ import { Platform } from "./";
const platformName = "givewellopenphil";
/* Support functions */
async function fetchPage(url: string) {
let response = await axios({
async function fetchPage(url: string): Promise<string> {
const response = await axios({
url: url,
method: "GET",
headers: {

View File

@ -5,13 +5,14 @@ import { Question } from "@prisma/client";
import { prisma } from "../database/prisma";
import { platforms } from "../platforms";
let cookie = process.env.ALGOLIA_MASTER_API_KEY;
const algoliaAppId = process.env.NEXT_PUBLIC_ALGOLIA_APP_ID;
let cookie = process.env.ALGOLIA_MASTER_API_KEY || "";
const algoliaAppId = process.env.NEXT_PUBLIC_ALGOLIA_APP_ID || "";
const client = algoliasearch(algoliaAppId, cookie);
const index = client.initIndex("metaforecast");
export type AlgoliaQuestion = Omit<Question, "timestamp"> & {
timestamp: string;
optionsstringforsearch?: string;
};
const getoptionsstringforsearch = (record: Question): string => {

View File

@ -1,4 +1,4 @@
import React, { EventHandler, SyntheticEvent, useState } from "react";
import React, { ChangeEvent, EventHandler, SyntheticEvent, useState } from "react";
import { Button } from "../common/Button";
import { InfoBox } from "../common/InfoBox";
@ -18,7 +18,7 @@ export const DashboardCreator: React.FC<Props> = ({ handleSubmit }) => {
const [value, setValue] = useState(exampleInput);
const [acting, setActing] = useState(false);
const handleChange = (event) => {
const handleChange = (event: ChangeEvent<HTMLTextAreaElement>) => {
setValue(event.target.value);
};

View File

@ -1,6 +1,7 @@
/* Imports */
import React from "react";
import { Handles, Rail, Slider, Tracks } from "react-compound-slider";
import {
GetHandleProps, GetTrackProps, Handles, Rail, Slider, SliderItem, Tracks
} from "react-compound-slider";
// https://sghall.github.io/react-compound-slider/#/getting-started/tutorial
@ -24,12 +25,11 @@ const railStyle = {
};
/* Support functions */
function Handle({
handle: { id, value, percent },
getHandleProps,
displayFunction,
handleWidth,
}) {
const Handle: React.FC<{
handle: SliderItem;
getHandleProps: GetHandleProps;
displayFunction: (value: number) => string;
}> = ({ handle: { id, value, percent }, getHandleProps, displayFunction }) => {
return (
<>
<div className="justify-center text-center text-gray-600 text-xs">
@ -53,9 +53,13 @@ function Handle({
></div>
</>
);
}
};
function Track({ source, target, getTrackProps }) {
const Track: React.FC<{
source: SliderItem;
target: SliderItem;
getTrackProps: GetTrackProps;
}> = ({ source, target, getTrackProps }) => {
return (
<div
style={{
@ -74,16 +78,15 @@ function Track({ source, target, getTrackProps }) {
}
/>
);
}
};
interface Props {
value: number;
onChange: (event: any) => void;
onChange: (value: number) => void;
displayFunction: (value: number) => string;
}
/* Body */
// Two functions, essentially identical.
export const SliderElement: React.FC<Props> = ({
onChange,
value,
@ -96,21 +99,20 @@ export const SliderElement: React.FC<Props> = ({
}
domain={[0, 200]}
values={[value]}
onChange={onChange}
onChange={(values) => onChange(values[0])}
>
<Rail>
{({ getRailProps }) => <div style={railStyle} {...getRailProps()} />}
</Rail>
<Handles>
{({ handles, getHandleProps }) => (
<div className="slider-handles">
<div>
{handles.map((handle) => (
<Handle
key={handle.id}
handle={handle}
getHandleProps={getHandleProps}
displayFunction={displayFunction}
handleWidth={"15em"}
/>
))}
</div>
@ -118,7 +120,7 @@ export const SliderElement: React.FC<Props> = ({
</Handles>
<Tracks right={false}>
{({ tracks, getTrackProps }) => (
<div className="slider-tracks">
<div>
{tracks.map(({ id, source, target }) => (
<Track
key={id}

View File

@ -173,7 +173,7 @@ export const QuestionCard: React.FC<Props> = ({
</div>
)}
{question.platform.id === "guesstimate" && (
{question.platform.id === "guesstimate" && question.visualization && (
<img
className="rounded-sm"
src={question.visualization}

View File

@ -74,7 +74,7 @@ const LargeQuestionCard: React.FC<{
</div>
<div className="mb-8">
{question.platform.id === "guesstimate" ? (
{question.platform.id === "guesstimate" && question.visualization ? (
<a className="no-underline" href={question.url} target="_blank">
<img
className="rounded-sm"

View File

@ -1,3 +1,5 @@
import { ChangeEvent } from "react";
interface Props {
value: string;
onChange: (v: string) => void;
@ -9,7 +11,7 @@ export const QueryForm: React.FC<Props> = ({
onChange,
placeholder,
}) => {
const handleInputChange = (event) => {
const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
event.preventDefault();
onChange(event.target.value); // In this case, the query, e.g. "COVID.19"
};

View File

@ -1,5 +1,5 @@
import { useRouter } from "next/router";
import React, { Fragment, useMemo, useState } from "react";
import React, { useMemo, useState } from "react";
import { useQuery } from "urql";
import { PlatformConfig } from "../../../backend/platforms";
@ -126,7 +126,8 @@ export const SearchScreen: React.FC<Props> = ({
};
const updateRoute = () => {
const stringify = (key: string, value: any) => {
const stringify = (key: string, obj: { [k: string]: any }) => {
const value = obj[key];
if (key === "forecastingPlatforms") {
return value.join("|");
} else {
@ -134,15 +135,16 @@ export const SearchScreen: React.FC<Props> = ({
}
};
const query = {};
const query: { [k: string]: string } = {};
for (const key of Object.keys(defaultQueryParameters)) {
const value = stringify(key, queryParameters[key]);
const defaultValue = stringify(key, defaultQueryParameters[key]);
const value = stringify(key, queryParameters);
const defaultValue = stringify(key, defaultQueryParameters);
if (value === defaultValue) continue;
query[key] = value;
}
if (numDisplay !== defaultNumDisplay) query["numDisplay"] = numDisplay;
if (numDisplay !== defaultNumDisplay)
query["numDisplay"] = String(numDisplay);
router.replace(
{
@ -191,8 +193,8 @@ export const SearchScreen: React.FC<Props> = ({
(Math.round(value) === 1 ? "" : "s")
);
};
const onChangeSliderForNumDisplay = (event) => {
setNumDisplay(Math.round(event[0]));
const onChangeSliderForNumDisplay = (value: number) => {
setNumDisplay(Math.round(value));
setForceSearch(forceSearch + 1); // FIXME - force new search iff numDisplay is greater than last search limit
};
@ -200,10 +202,10 @@ export const SearchScreen: React.FC<Props> = ({
const displayFunctionNumForecasts = (value: number) => {
return "# Forecasts > " + Math.round(value);
};
const onChangeSliderForNumForecasts = (event) => {
const onChangeSliderForNumForecasts = (value: number) => {
setQueryParameters({
...queryParameters,
forecastsThreshold: Math.round(event[0]),
forecastsThreshold: Math.round(value),
});
};
@ -230,7 +232,7 @@ export const SearchScreen: React.FC<Props> = ({
/* Final return */
return (
<Fragment>
<>
<label className="mb-4 mt-4 flex flex-row justify-center items-center">
<div className="w-10/12 mb-2">
<QueryForm
@ -317,6 +319,6 @@ export const SearchScreen: React.FC<Props> = ({
</p>
</div>
) : null}
</Fragment>
</>
);
};

View File

@ -36,5 +36,8 @@ export const getUrqlClientOptions = (ssr: SSRExchange) => ({
export const ssrUrql = () => {
const ssrCache = ssrExchange({ isClient: false });
const client = initUrqlClient(getUrqlClientOptions(ssrCache), false);
if (!client) {
throw new Error("Expected non-null client instance from initUrqlClient");
}
return [ssrCache, client] as const;
};

View File

@ -1,18 +1,31 @@
import algoliasearch from "algoliasearch";
import { Hit } from "@algolia/client-search";
import { AlgoliaQuestion } from "../../backend/utils/algolia";
const client = algoliasearch(
process.env.NEXT_PUBLIC_ALGOLIA_APP_ID,
process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY
process.env.NEXT_PUBLIC_ALGOLIA_APP_ID || "",
process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY || ""
);
const index = client.initIndex("metaforecast");
let buildFilter = ({
interface SearchOpts {
queryString: string;
hitsPerPage?: number;
starsThreshold: number;
filterByPlatforms: string[];
forecastsThreshold: number;
}
const buildFilter = ({
starsThreshold,
filterByPlatforms,
forecastsThreshold,
}) => {
}: Pick<
SearchOpts,
"starsThreshold" | "filterByPlatforms" | "forecastsThreshold"
>) => {
const starsFilter = starsThreshold
? `qualityindicators.stars >= ${starsThreshold}`
: null;
@ -35,26 +48,15 @@ let buildFilter = ({
return finalFilter;
};
let buildFacetFilter = ({ filterByPlatforms }) => {
let platformsFilter = [];
if (filterByPlatforms.length > 0) {
platformsFilter = [
[filterByPlatforms.map((platform) => `platform:${platform}`)],
];
}
console.log(platformsFilter);
console.log(
"searchWithAlgolia.js/searchWithAlgolia/buildFacetFilter",
platformsFilter
);
return platformsFilter;
};
let noExactMatch = (queryString, result) => {
const noExactMatch = (queryString: string, result: Hit<AlgoliaQuestion>) => {
queryString = queryString.toLowerCase();
let title = result.title.toLowerCase();
let description = result.description.toLowerCase();
let optionsstringforsearch = result.optionsstringforsearch.toLowerCase();
const title = result.title.toLowerCase();
const description = result.description.toLowerCase();
const optionsstringforsearch = (
result.optionsstringforsearch || ""
).toLowerCase();
return !(
title.includes(queryString) ||
description.includes(queryString) ||
@ -62,14 +64,6 @@ let noExactMatch = (queryString, result) => {
);
};
interface SearchOpts {
queryString: string;
hitsPerPage?: number;
starsThreshold: number;
filterByPlatforms: string[];
forecastsThreshold: number;
}
// only query string
export default async function searchWithAlgolia({
queryString,