refactor: move stuff around, simplify / code

This commit is contained in:
Vyacheslav Matyukhin 2022-05-07 22:48:56 +04:00
parent 8c5ed35c0f
commit 066b79fe12
No known key found for this signature in database
GPG Key ID: 3D2A774C5489F96C
26 changed files with 151 additions and 167 deletions

View File

@ -3,8 +3,8 @@ import React from "react";
import ReactMarkdown from "react-markdown"; import ReactMarkdown from "react-markdown";
import gfm from "remark-gfm"; import gfm from "remark-gfm";
import { Card } from "../web/display/Card"; import { Card } from "../web/common/Card";
import { Layout } from "../web/display/Layout"; import { Layout } from "../web/common/Layout";
const readmeMarkdownText = `# About const readmeMarkdownText = `# About

View File

@ -4,7 +4,7 @@ import Error from "next/error";
import { import {
DashboardByIdDocument, DashboardFragment DashboardByIdDocument, DashboardFragment
} from "../../../web/dashboards/queries.generated"; } from "../../../web/dashboards/queries.generated";
import { DisplayQuestions } from "../../../web/display/DisplayQuestions"; import { QuestionCardsList } from "../../../web/questions/components/QuestionCardsList";
import { ssrUrql } from "../../../web/urql"; import { ssrUrql } from "../../../web/urql";
interface Props { interface Props {
@ -52,7 +52,7 @@ const EmbedDashboardPage: NextPage<Props> = ({ dashboard, numCols }) => {
numCols || 3 numCols || 3
} gap-4 mb-6`} } gap-4 mb-6`}
> >
<DisplayQuestions <QuestionCardsList
results={dashboard.questions} results={dashboard.questions}
numDisplay={dashboard.questions.length} numDisplay={dashboard.questions.length}
showIdToggle={false} showIdToggle={false}

View File

@ -2,10 +2,10 @@ import { NextPage } from "next";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { useMutation } from "urql"; import { useMutation } from "urql";
import { Layout } from "../../web/common/Layout";
import { LineHeader } from "../../web/common/LineHeader";
import { CreateDashboardDocument } from "../../web/dashboards/queries.generated"; import { CreateDashboardDocument } from "../../web/dashboards/queries.generated";
import { DashboardCreator } from "../../web/display/DashboardCreator"; import { DashboardCreator } from "../../web/display/DashboardCreator";
import { Layout } from "../../web/display/Layout";
import { LineHeader } from "../../web/display/LineHeader";
const DashboardsPage: NextPage = () => { const DashboardsPage: NextPage = () => {
const router = useRouter(); const router = useRouter();

View File

@ -2,13 +2,13 @@ import { GetServerSideProps, NextPage } from "next";
import Error from "next/error"; import Error from "next/error";
import Link from "next/link"; import Link from "next/link";
import { InfoBox } from "../../../web/common/InfoBox";
import { Layout } from "../../../web/common/Layout";
import { LineHeader } from "../../../web/common/LineHeader";
import { import {
DashboardByIdDocument, DashboardFragment DashboardByIdDocument, DashboardFragment
} from "../../../web/dashboards/queries.generated"; } from "../../../web/dashboards/queries.generated";
import { DisplayQuestions } from "../../../web/display/DisplayQuestions"; import { QuestionCardsList } from "../../../web/questions/components/QuestionCardsList";
import { InfoBox } from "../../../web/display/InfoBox";
import { Layout } from "../../../web/display/Layout";
import { LineHeader } from "../../../web/display/LineHeader";
import { ssrUrql } from "../../../web/urql"; import { ssrUrql } from "../../../web/urql";
interface Props { interface Props {
@ -84,7 +84,7 @@ const ViewDashboardPage: NextPage<Props> = ({ dashboard }) => {
<> <>
<DashboardMetadata dashboard={dashboard} /> <DashboardMetadata dashboard={dashboard} />
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<DisplayQuestions <QuestionCardsList
results={dashboard.questions} results={dashboard.questions}
numDisplay={dashboard.questions.length} numDisplay={dashboard.questions.length}
showIdToggle={false} showIdToggle={false}

View File

@ -1,16 +1,86 @@
import { NextPage } from "next"; import { GetServerSideProps, NextPage } from "next";
import React from "react"; import React from "react";
import { Layout } from "../web/display/Layout"; import { getPlatformsConfig, platforms } from "../backend/platforms";
import { Props } from "../web/search/anySearchPage"; import { Layout } from "../web/common/Layout";
import { CommonDisplay } from "../web/search/CommonDisplay"; import { Props, QueryParameters, SearchScreen } from "../web/search/components/SearchScreen";
import { FrontpageDocument, SearchDocument } from "../web/search/queries.generated";
import { ssrUrql } from "../web/urql";
export { getServerSideProps } from "../web/search/anySearchPage"; export const getServerSideProps: GetServerSideProps<Props> = async (
context
) => {
const [ssrCache, client] = ssrUrql();
const urlQuery = context.query;
const platformsConfig = getPlatformsConfig({ withGuesstimate: true });
const defaultQueryParameters: QueryParameters = {
query: "",
starsThreshold: 2,
forecastsThreshold: 0,
forecastingPlatforms: platforms.map((platform) => platform.name),
};
const initialQueryParameters: QueryParameters = {
...defaultQueryParameters,
};
if (urlQuery.query) {
initialQueryParameters.query = String(urlQuery.query);
}
if (urlQuery.starsThreshold) {
initialQueryParameters.starsThreshold = Number(urlQuery.starsThreshold);
}
if (urlQuery.forecastsThreshold !== undefined) {
initialQueryParameters.forecastsThreshold = Number(
urlQuery.forecastsThreshold
);
}
if (urlQuery.forecastingPlatforms !== undefined) {
initialQueryParameters.forecastingPlatforms = String(
urlQuery.forecastingPlatforms
).split("|");
}
const defaultNumDisplay = 21;
const initialNumDisplay = Number(urlQuery.numDisplay) || defaultNumDisplay;
const defaultResults = (await client.query(FrontpageDocument).toPromise())
.data.result;
if (
!!initialQueryParameters &&
initialQueryParameters.query != "" &&
initialQueryParameters.query != undefined
) {
// must match the query from CommonDisplay
await client
.query(SearchDocument, {
input: {
...initialQueryParameters,
limit: initialNumDisplay,
},
})
.toPromise();
}
return {
props: {
urqlState: ssrCache.extractData(),
initialQueryParameters,
defaultQueryParameters,
initialNumDisplay,
defaultNumDisplay,
defaultResults,
platformsConfig,
},
};
};
const IndexPage: NextPage<Props> = (props) => { const IndexPage: NextPage<Props> = (props) => {
return ( return (
<Layout page="search"> <Layout page="search">
<CommonDisplay {...props} /> <SearchScreen {...props} />
</Layout> </Layout>
); );
}; };

View File

@ -4,8 +4,8 @@ import { GetServerSideProps, NextPage } from "next";
import React from "react"; import React from "react";
import { platforms } from "../backend/platforms"; import { platforms } from "../backend/platforms";
import { DisplayQuestion } from "../web/display/DisplayQuestion";
import { QuestionFragment } from "../web/fragments.generated"; import { QuestionFragment } from "../web/fragments.generated";
import { QuestionCard } from "../web/questions/components/QuestionCard";
import { SearchDocument } from "../web/search/queries.generated"; import { SearchDocument } from "../web/search/queries.generated";
import { ssrUrql } from "../web/urql"; import { ssrUrql } from "../web/urql";
@ -58,7 +58,7 @@ const SecretEmbedPage: NextPage<Props> = ({ results }) => {
<div> <div>
<div id="secretEmbed"> <div id="secretEmbed">
{result ? ( {result ? (
<DisplayQuestion <QuestionCard
question={result} question={result}
showTimeStamp={true} showTimeStamp={true}
expandFooterToFullWidth={true} expandFooterToFullWidth={true}

View File

@ -2,8 +2,8 @@ import { NextPage } from "next";
import Link from "next/link"; import Link from "next/link";
import React from "react"; import React from "react";
import { Card } from "../web/display/Card"; import { Card } from "../web/common/Card";
import { Layout } from "../web/display/Layout"; import { Layout } from "../web/common/Layout";
type AnyTool = { type AnyTool = {
title: string; title: string;

View File

@ -1,7 +1,7 @@
import { useState } from "react"; import { useState } from "react";
import { CopyToClipboard } from "react-copy-to-clipboard"; import { CopyToClipboard } from "react-copy-to-clipboard";
import { Button } from "../display/Button"; import { Button } from "./Button";
// https://stackoverflow.com/questions/39501289/in-reactjs-how-to-copy-text-to-clipboard // https://stackoverflow.com/questions/39501289/in-reactjs-how-to-copy-text-to-clipboard

View File

@ -1,10 +1,16 @@
import chroma from "chroma-js"; import chroma from "chroma-js";
import React from "react"; import React from "react";
import Select from "react-select"; import Select, { StylesConfig } from "react-select";
import { PlatformConfig } from "../../backend/platforms"; import { PlatformConfig } from "../../backend/platforms";
const colourStyles = { type Option = {
value: string;
label: string;
color: string;
};
const colourStyles: StylesConfig<Option> = {
control: (styles) => ({ ...styles, backgroundColor: "white" }), control: (styles) => ({ ...styles, backgroundColor: "white" }),
option: (styles, { data, isDisabled, isFocused, isSelected }) => { option: (styles, { data, isDisabled, isFocused, isSelected }) => {
const color = chroma(data.color); const color = chroma(data.color);
@ -70,12 +76,6 @@ export const MultiSelectPlatform: React.FC<Props> = ({
value, value,
platformsConfig, platformsConfig,
}) => { }) => {
type Option = {
value: string;
label: string;
color: string;
};
const options: Option[] = platformsConfig.map((platform) => ({ const options: Option[] = platformsConfig.map((platform) => ({
value: platform.name, value: platform.name,
label: platform.label, label: platform.label,

View File

@ -1,7 +1,7 @@
import React, { EventHandler, SyntheticEvent, useState } from "react"; import React, { EventHandler, SyntheticEvent, useState } from "react";
import { Button } from "./Button"; import { Button } from "../common/Button";
import { InfoBox } from "./InfoBox"; import { InfoBox } from "../common/InfoBox";
const exampleInput = `{ const exampleInput = `{
"title": "Random example", "title": "Random example",

View File

@ -1,11 +1,11 @@
import domtoimage from "dom-to-image"; // https://github.com/tsayen/dom-to-image 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 { Button } from "../../common/Button";
import { CopyParagraph } from "../../common/CopyParagraph"; import { CopyParagraph } from "../../common/CopyParagraph";
import { Button } from "../../display/Button";
import { DisplayQuestion } from "../../display/DisplayQuestion";
import { QuestionFragment } from "../../fragments.generated"; import { QuestionFragment } from "../../fragments.generated";
import { uploadToImgur } from "../../worker/uploadToImgur"; import { uploadToImgur } from "../../worker/uploadToImgur";
import { QuestionCard } from "./QuestionCard";
const domToImageWrapper = async (node: HTMLDivElement) => { const domToImageWrapper = async (node: HTMLDivElement) => {
const scale = 3; // Increase for better quality const scale = 3; // Increase for better quality
@ -121,7 +121,7 @@ export const CaptureQuestion: React.FC<Props> = ({ question }) => {
return ( return (
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 place-items-center"> <div className="grid grid-cols-1 md:grid-cols-2 gap-4 place-items-center">
<div ref={containerRef}> <div ref={containerRef}>
<DisplayQuestion <QuestionCard
question={question} question={question}
showTimeStamp={true} showTimeStamp={true}
showExpandButton={false} showExpandButton={false}

View File

@ -1,8 +1,8 @@
import { QuestionFragment } from "../../fragments.generated";
import { import {
formatIndicatorValue, qualityIndicatorLabels, UsedIndicatorName formatIndicatorValue, qualityIndicatorLabels, UsedIndicatorName
} from "../../display/DisplayQuestion/QuestionFooter"; } from "./QuestionCard/QuestionFooter";
import { Stars } from "../../display/Stars"; import { Stars } from "./Stars";
import { QuestionFragment } from "../../fragments.generated";
interface Props { interface Props {
question: QuestionFragment; question: QuestionFragment;

View File

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

View File

@ -2,11 +2,11 @@ import Link from "next/link";
import { FaExpand } from "react-icons/fa"; import { FaExpand } from "react-icons/fa";
import ReactMarkdown from "react-markdown"; import ReactMarkdown from "react-markdown";
import { CopyText } from "../../common/CopyText"; import { Card } from "../../../common/Card";
import { QuestionFragment } from "../../fragments.generated"; import { CopyText } from "../../../common/CopyText";
import { QuestionOptions } from "../../questions/components/QuestionOptions"; import { QuestionFragment } from "../../../fragments.generated";
import { cleanText } from "../../utils"; import { cleanText } from "../../../utils";
import { Card } from "../Card"; import { QuestionOptions } from "../QuestionOptions";
import { QuestionFooter } from "./QuestionFooter"; import { QuestionFooter } from "./QuestionFooter";
const truncateText = (length: number, text: string): string => { const truncateText = (length: number, text: string): string => {
@ -107,7 +107,7 @@ interface Props {
showExpandButton?: boolean; showExpandButton?: boolean;
} }
export const DisplayQuestion: React.FC<Props> = ({ export const QuestionCard: React.FC<Props> = ({
question, question,
showTimeStamp, showTimeStamp,
expandFooterToFullWidth, expandFooterToFullWidth,

View File

@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import { QuestionFragment } from "../fragments.generated"; import { QuestionFragment } from "../../fragments.generated";
import { DisplayQuestion } from "./DisplayQuestion"; import { QuestionCard } from "./QuestionCard";
interface Props { interface Props {
results: QuestionFragment[]; results: QuestionFragment[];
@ -9,18 +9,18 @@ interface Props {
showIdToggle: boolean; showIdToggle: boolean;
} }
export const DisplayQuestions: React.FC<Props> = ({ export const QuestionCardsList: React.FC<Props> = ({
results, results,
numDisplay, numDisplay,
showIdToggle, showIdToggle,
}) => { }) => {
if (!results) { if (!results) {
return <></>; return null;
} }
return ( return (
<> <>
{results.slice(0, numDisplay).map((result) => ( {results.slice(0, numDisplay).map((result) => (
<DisplayQuestion <QuestionCard
key={result.id} key={result.id}
question={result} question={result}
showTimeStamp={false} showTimeStamp={false}

View File

@ -2,10 +2,10 @@ import { GetServerSideProps, NextPage } from "next";
import { FaExternalLinkAlt } from "react-icons/fa"; import { FaExternalLinkAlt } from "react-icons/fa";
import ReactMarkdown from "react-markdown"; import ReactMarkdown from "react-markdown";
import { Card } from "../../common/Card";
import { Layout } from "../../common/Layout";
import { LineHeader } from "../../common/LineHeader";
import { Query } from "../../common/Query"; import { Query } from "../../common/Query";
import { Card } from "../../display/Card";
import { Layout } from "../../display/Layout";
import { LineHeader } from "../../display/LineHeader";
import { QuestionWithHistoryFragment } from "../../fragments.generated"; import { QuestionWithHistoryFragment } from "../../fragments.generated";
import { ssrUrql } from "../../urql"; import { ssrUrql } from "../../urql";
import { CaptureQuestion } from "../components/CaptureQuestion"; import { CaptureQuestion } from "../components/CaptureQuestion";

View File

@ -1,94 +0,0 @@
import { GetServerSideProps } from "next";
import { getPlatformsConfig, PlatformConfig, platforms } from "../../backend/platforms";
import { QuestionFragment } from "../fragments.generated";
import { ssrUrql } from "../urql";
import { FrontpageDocument, SearchDocument } from "./queries.generated";
/* Common code for / and /capture (/capture is deprecated, TODO - refactor) */
export interface QueryParameters {
query: string;
starsThreshold: number;
forecastsThreshold: number;
forecastingPlatforms: string[]; // platform names
}
export interface Props {
defaultResults: QuestionFragment[];
initialQueryParameters: QueryParameters;
defaultQueryParameters: QueryParameters;
initialNumDisplay: number;
defaultNumDisplay: number;
platformsConfig: PlatformConfig[];
}
export const getServerSideProps: GetServerSideProps<Props> = async (
context
) => {
const [ssrCache, client] = ssrUrql();
const urlQuery = context.query;
const platformsConfig = getPlatformsConfig({ withGuesstimate: true });
const defaultQueryParameters: QueryParameters = {
query: "",
starsThreshold: 2,
forecastsThreshold: 0,
forecastingPlatforms: platforms.map((platform) => platform.name),
};
const initialQueryParameters: QueryParameters = {
...defaultQueryParameters,
};
if (urlQuery.query) {
initialQueryParameters.query = String(urlQuery.query);
}
if (urlQuery.starsThreshold) {
initialQueryParameters.starsThreshold = Number(urlQuery.starsThreshold);
}
if (urlQuery.forecastsThreshold !== undefined) {
initialQueryParameters.forecastsThreshold = Number(
urlQuery.forecastsThreshold
);
}
if (urlQuery.forecastingPlatforms !== undefined) {
initialQueryParameters.forecastingPlatforms = String(
urlQuery.forecastingPlatforms
).split("|");
}
const defaultNumDisplay = 21;
const initialNumDisplay = Number(urlQuery.numDisplay) || defaultNumDisplay;
const defaultResults = (await client.query(FrontpageDocument).toPromise())
.data.result;
if (
!!initialQueryParameters &&
initialQueryParameters.query != "" &&
initialQueryParameters.query != undefined
) {
// must match the query from CommonDisplay
await client
.query(SearchDocument, {
input: {
...initialQueryParameters,
limit: initialNumDisplay,
},
})
.toPromise();
}
return {
props: {
urqlState: ssrCache.extractData(),
initialQueryParameters,
defaultQueryParameters,
initialNumDisplay,
defaultNumDisplay,
defaultResults,
platformsConfig,
},
};
};

View File

@ -1,5 +1,3 @@
import React from "react";
interface Props { interface Props {
value: string; value: string;
onChange: (v: string) => void; onChange: (v: string) => void;

View File

@ -2,20 +2,34 @@ import { useRouter } from "next/router";
import React, { Fragment, useMemo, useState } from "react"; import React, { Fragment, useMemo, useState } from "react";
import { useQuery } from "urql"; import { useQuery } from "urql";
import { ButtonsForStars } from "../display/ButtonsForStars"; import { PlatformConfig } from "../../../backend/platforms";
import { DisplayQuestions } from "../display/DisplayQuestions"; import { MultiSelectPlatform } from "../../common/MultiSelectPlatform";
import { MultiSelectPlatform } from "../display/MultiSelectPlatform"; import { ButtonsForStars } from "../../display/ButtonsForStars";
import { QueryForm } from "../display/QueryForm"; import { SliderElement } from "../../display/SliderElement";
import { SliderElement } from "../display/SliderElement"; import { QuestionFragment } from "../../fragments.generated";
import { QuestionFragment } from "../fragments.generated"; import { useIsFirstRender, useNoInitialEffect } from "../../hooks";
import { useIsFirstRender, useNoInitialEffect } from "../hooks"; import { QuestionCardsList } from "../../questions/components/QuestionCardsList";
import { Props as AnySearchPageProps, QueryParameters } from "./anySearchPage"; import { SearchDocument } from "../queries.generated";
import { SearchDocument } from "./queries.generated"; import { QueryForm } from "./QueryForm";
interface Props extends AnySearchPageProps {} export interface QueryParameters {
query: string;
starsThreshold: number;
forecastsThreshold: number;
forecastingPlatforms: string[]; // platform names
}
export interface Props {
defaultResults: QuestionFragment[];
initialQueryParameters: QueryParameters;
defaultQueryParameters: QueryParameters;
initialNumDisplay: number;
defaultNumDisplay: number;
platformsConfig: PlatformConfig[];
}
/* Body */ /* Body */
export const CommonDisplay: React.FC<Props> = ({ export const SearchScreen: React.FC<Props> = ({
defaultResults, defaultResults,
initialQueryParameters, initialQueryParameters,
defaultQueryParameters, defaultQueryParameters,
@ -37,8 +51,6 @@ export const CommonDisplay: React.FC<Props> = ({
const [forceSearch, setForceSearch] = useState(0); const [forceSearch, setForceSearch] = useState(0);
const [advancedOptions, showAdvancedOptions] = useState(false); const [advancedOptions, showAdvancedOptions] = useState(false);
const [whichResultToDisplayAndCapture, setWhichResultToDisplayAndCapture] =
useState(0);
const [showIdToggle, setShowIdToggle] = useState(false); const [showIdToggle, setShowIdToggle] = useState(false);
const [typing, setTyping] = useState(false); const [typing, setTyping] = useState(false);
@ -104,7 +116,7 @@ export const CommonDisplay: React.FC<Props> = ({
: numDisplay; : numDisplay;
return ( return (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<DisplayQuestions <QuestionCardsList
results={results} results={results}
numDisplay={numDisplayRounded} numDisplay={numDisplayRounded}
showIdToggle={showIdToggle} showIdToggle={showIdToggle}
@ -204,7 +216,7 @@ export const CommonDisplay: React.FC<Props> = ({
}; };
/* Change selected platforms */ /* Change selected platforms */
const onChangeSelectedPlatforms = (value) => { const onChangeSelectedPlatforms = (value: string[]) => {
setQueryParameters({ setQueryParameters({
...queryParameters, ...queryParameters,
forecastingPlatforms: value, forecastingPlatforms: value,
@ -305,8 +317,6 @@ export const CommonDisplay: React.FC<Props> = ({
</p> </p>
</div> </div>
) : null} ) : null}
<br />
</Fragment> </Fragment>
); );
}; };

View File

@ -1,7 +1,7 @@
import { NextPage } from "next"; import { NextPage } from "next";
import { Layout } from "../../common/Layout";
import { Query } from "../../common/Query"; import { Query } from "../../common/Query";
import { Layout } from "../../display/Layout";
import { PlatformsStatusDocument } from "../queries.generated"; import { PlatformsStatusDocument } from "../queries.generated";
const StatusPage: NextPage = () => { const StatusPage: NextPage = () => {