feat: /capture and / are static
This commit is contained in:
		
							parent
							
								
									98c7c31a0f
								
							
						
					
					
						commit
						f056d257b2
					
				|  | @ -1,33 +1,18 @@ | ||||||
| import { GetServerSideProps, NextPage } from 'next'; | import { GetStaticProps, NextPage } from 'next'; | ||||||
| import React from 'react'; | import React from 'react'; | ||||||
| 
 | 
 | ||||||
| import { getFrontpage } from '../backend/frontpage'; | import { getFrontpage } from '../backend/frontpage'; | ||||||
| import CommonDisplay, { QueryParameters } from '../web/display/commonDisplay'; | import CommonDisplay from '../web/display/commonDisplay'; | ||||||
| import { displayForecastsWrapperForCapture } from '../web/display/displayForecastsWrappers'; | import { displayForecastsWrapperForCapture } from '../web/display/displayForecastsWrappers'; | ||||||
| import { platformsWithLabels } from '../web/platforms'; |  | ||||||
| import Layout from './layout'; | import Layout from './layout'; | ||||||
| 
 | 
 | ||||||
| /* get Props */ | /* get Props */ | ||||||
| 
 | 
 | ||||||
| interface Props { | interface Props { | ||||||
|   initialQueryParameters: QueryParameters; |  | ||||||
|   defaultResults: any; |   defaultResults: any; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export const getServerSideProps: GetServerSideProps<Props> = async ( | export const getStaticProps: GetStaticProps<Props> = async (context) => { | ||||||
|   context |  | ||||||
| ) => { |  | ||||||
|   let urlQuery = context.query; |  | ||||||
| 
 |  | ||||||
|   let initialQueryParameters: QueryParameters = { |  | ||||||
|     query: "", |  | ||||||
|     numDisplay: 21, |  | ||||||
|     starsThreshold: 2, |  | ||||||
|     forecastsThreshold: 0, |  | ||||||
|     forecastingPlatforms: platformsWithLabels, // weird key value format,
 |  | ||||||
|     ...urlQuery, |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   let frontPageForecasts = await getFrontpage(); |   let frontPageForecasts = await getFrontpage(); | ||||||
|   frontPageForecasts = frontPageForecasts.map((forecast) => ({ |   frontPageForecasts = frontPageForecasts.map((forecast) => ({ | ||||||
|     ...forecast, |     ...forecast, | ||||||
|  | @ -39,19 +24,18 @@ export const getServerSideProps: GetServerSideProps<Props> = async ( | ||||||
| 
 | 
 | ||||||
|   return { |   return { | ||||||
|     props: { |     props: { | ||||||
|       initialQueryParameters: initialQueryParameters, |  | ||||||
|       defaultResults: frontPageForecasts, |       defaultResults: frontPageForecasts, | ||||||
|     }, |     }, | ||||||
|  |     revalidate: 3600 * 6, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* Body */ | /* Body */ | ||||||
| const Home: NextPage<Props> = ({ defaultResults, initialQueryParameters }) => { | const CapturePage: NextPage<Props> = ({ defaultResults }) => { | ||||||
|   return ( |   return ( | ||||||
|     <Layout page={"capture"}> |     <Layout page={"capture"}> | ||||||
|       <CommonDisplay |       <CommonDisplay | ||||||
|         defaultResults={defaultResults} |         defaultResults={defaultResults} | ||||||
|         initialQueryParameters={initialQueryParameters} |  | ||||||
|         hasSearchbar={true} |         hasSearchbar={true} | ||||||
|         hasCapture={true} |         hasCapture={true} | ||||||
|         hasAdvancedOptions={false} |         hasAdvancedOptions={false} | ||||||
|  | @ -63,4 +47,4 @@ const Home: NextPage<Props> = ({ defaultResults, initialQueryParameters }) => { | ||||||
|   ); |   ); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export default Home; | export default CapturePage; | ||||||
|  |  | ||||||
|  | @ -1,33 +1,18 @@ | ||||||
| import { GetServerSideProps, NextPage } from 'next'; | import { GetStaticProps, NextPage } from 'next'; | ||||||
| import React from 'react'; | import React from 'react'; | ||||||
| 
 | 
 | ||||||
| import { getFrontpage } from '../backend/frontpage'; | import { getFrontpage } from '../backend/frontpage'; | ||||||
| import CommonDisplay, { QueryParameters } from '../web/display/commonDisplay'; | import CommonDisplay from '../web/display/commonDisplay'; | ||||||
| import { displayForecastsWrapperForSearch } from '../web/display/displayForecastsWrappers'; | import { displayForecastsWrapperForSearch } from '../web/display/displayForecastsWrappers'; | ||||||
| import { platformsWithLabels } from '../web/platforms'; |  | ||||||
| import Layout from './layout'; | import Layout from './layout'; | ||||||
| 
 | 
 | ||||||
| /* get Props */ | /* get Props */ | ||||||
| 
 | 
 | ||||||
| interface Props { | interface Props { | ||||||
|   initialQueryParameters: QueryParameters; |  | ||||||
|   defaultResults: any; |   defaultResults: any; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export const getServerSideProps: GetServerSideProps<Props> = async ( | export const getStaticProps: GetStaticProps<Props> = async (context) => { | ||||||
|   context |  | ||||||
| ) => { |  | ||||||
|   let urlQuery = context.query; |  | ||||||
| 
 |  | ||||||
|   let initialQueryParameters: QueryParameters = { |  | ||||||
|     query: "", |  | ||||||
|     numDisplay: 21, |  | ||||||
|     starsThreshold: 2, |  | ||||||
|     forecastsThreshold: 0, |  | ||||||
|     forecastingPlatforms: platformsWithLabels, // weird key value format,
 |  | ||||||
|     ...urlQuery, |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   let frontPageForecasts = await getFrontpage(); |   let frontPageForecasts = await getFrontpage(); | ||||||
|   frontPageForecasts = frontPageForecasts.map((forecast) => ({ |   frontPageForecasts = frontPageForecasts.map((forecast) => ({ | ||||||
|     ...forecast, |     ...forecast, | ||||||
|  | @ -39,19 +24,18 @@ export const getServerSideProps: GetServerSideProps<Props> = async ( | ||||||
| 
 | 
 | ||||||
|   return { |   return { | ||||||
|     props: { |     props: { | ||||||
|       initialQueryParameters: initialQueryParameters, |  | ||||||
|       defaultResults: frontPageForecasts, |       defaultResults: frontPageForecasts, | ||||||
|     }, |     }, | ||||||
|  |     revalidate: 3600 * 6, | ||||||
|   }; |   }; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /* Body */ | /* Body */ | ||||||
| const Home: NextPage<Props> = ({ defaultResults, initialQueryParameters }) => { | const IndexPage: NextPage<Props> = ({ defaultResults }) => { | ||||||
|   return ( |   return ( | ||||||
|     <Layout page={"search"}> |     <Layout page={"search"}> | ||||||
|       <CommonDisplay |       <CommonDisplay | ||||||
|         defaultResults={defaultResults} |         defaultResults={defaultResults} | ||||||
|         initialQueryParameters={initialQueryParameters} |  | ||||||
|         hasSearchbar={true} |         hasSearchbar={true} | ||||||
|         hasCapture={false} |         hasCapture={false} | ||||||
|         hasAdvancedOptions={true} |         hasAdvancedOptions={true} | ||||||
|  | @ -63,4 +47,4 @@ const Home: NextPage<Props> = ({ defaultResults, initialQueryParameters }) => { | ||||||
|   ); |   ); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export default Home; | export default IndexPage; | ||||||
|  |  | ||||||
|  | @ -1,6 +1,7 @@ | ||||||
|  | import { useRouter } from 'next/router'; | ||||||
| import React, { Fragment, useEffect, useState } from 'react'; | import React, { Fragment, useEffect, useState } from 'react'; | ||||||
| 
 | 
 | ||||||
| import { platformNames, PlatformWithLabel } from '../platforms'; | import { platformsWithLabels, PlatformWithLabel } from '../platforms'; | ||||||
| import searchAccordingToQueryData from '../worker/searchAccordingToQueryData'; | import searchAccordingToQueryData from '../worker/searchAccordingToQueryData'; | ||||||
| import ButtonsForStars from './buttonsForStars'; | import ButtonsForStars from './buttonsForStars'; | ||||||
| import Form from './form'; | import Form from './form'; | ||||||
|  | @ -20,7 +21,6 @@ export interface QueryParameters extends QueryParametersWithoutNum { | ||||||
| 
 | 
 | ||||||
| interface Props { | interface Props { | ||||||
|   defaultResults: any; |   defaultResults: any; | ||||||
|   initialQueryParameters: QueryParameters; |  | ||||||
|   hasSearchbar: boolean; |   hasSearchbar: boolean; | ||||||
|   hasCapture: boolean; |   hasCapture: boolean; | ||||||
|   hasAdvancedOptions: boolean; |   hasAdvancedOptions: boolean; | ||||||
|  | @ -34,28 +34,17 @@ interface Props { | ||||||
|   }) => React.ReactNode; |   }) => React.ReactNode; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Helper functions */ | const defaultQueryParameters: QueryParametersWithoutNum = { | ||||||
| 
 |   query: "", | ||||||
| // URL slugs
 |   starsThreshold: 2, | ||||||
| let transformObjectIntoUrlSlug = (obj: QueryParameters) => { |   forecastsThreshold: 0, | ||||||
|   let results = []; |   forecastingPlatforms: platformsWithLabels, // weird key value format,
 | ||||||
|   for (let key in obj) { |  | ||||||
|     if (typeof obj[key] === "number" || typeof obj[key] === "string") { |  | ||||||
|       results.push(`${key}=${obj[key]}`); |  | ||||||
|     } else if (key === "forecastingPlatforms") { |  | ||||||
|       let arr = obj[key].map((x) => x.value); |  | ||||||
|       let arrstring = arr.join("|"); |  | ||||||
|       results.push(`${key}=${arrstring}`); |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|   let string = "?" + results.join("&"); |  | ||||||
|   return string; |  | ||||||
| }; | }; | ||||||
|  | const defaultNumDisplay = 21; | ||||||
| 
 | 
 | ||||||
| /* Body */ | /* Body */ | ||||||
| const CommonDisplay: React.FC<Props> = ({ | const CommonDisplay: React.FC<Props> = ({ | ||||||
|   defaultResults, |   defaultResults, | ||||||
|   initialQueryParameters, |  | ||||||
|   hasSearchbar, |   hasSearchbar, | ||||||
|   hasCapture, |   hasCapture, | ||||||
|   hasAdvancedOptions, |   hasAdvancedOptions, | ||||||
|  | @ -63,14 +52,18 @@ const CommonDisplay: React.FC<Props> = ({ | ||||||
|   displaySeeMoreHint, |   displaySeeMoreHint, | ||||||
|   displayForecastsWrapper, |   displayForecastsWrapper, | ||||||
| }) => { | }) => { | ||||||
|  |   const router = useRouter(); | ||||||
|   /* States */ |   /* States */ | ||||||
| 
 | 
 | ||||||
|   const [queryParameters, setQueryParameters] = |   const [queryParameters, setQueryParameters] = | ||||||
|     useState<QueryParametersWithoutNum>(initialQueryParameters); |     useState<QueryParametersWithoutNum>(defaultQueryParameters); | ||||||
| 
 | 
 | ||||||
|   const [numDisplay, setNumDisplay] = useState( |   const [numDisplay, setNumDisplay] = useState(0); | ||||||
|     initialQueryParameters.numDisplay || 21 | 
 | ||||||
|   ); |   const [ready, setReady] = useState(false); | ||||||
|  | 
 | ||||||
|  |   // used to distinguish numDisplay updates which force search and don't force search, see effects below
 | ||||||
|  |   const [forceSearch, setForceSearch] = useState(0); | ||||||
| 
 | 
 | ||||||
|   const [results, setResults] = useState([]); |   const [results, setResults] = useState([]); | ||||||
|   const [advancedOptions, showAdvancedOptions] = useState(false); |   const [advancedOptions, showAdvancedOptions] = useState(false); | ||||||
|  | @ -78,13 +71,29 @@ const CommonDisplay: React.FC<Props> = ({ | ||||||
|     useState(0); |     useState(0); | ||||||
|   const [showIdToggle, setShowIdToggle] = useState(false); |   const [showIdToggle, setShowIdToggle] = useState(false); | ||||||
| 
 | 
 | ||||||
|  |   useEffect(() => { | ||||||
|  |     if (!router.isReady) return; | ||||||
|  | 
 | ||||||
|  |     setQueryParameters({ | ||||||
|  |       ...defaultQueryParameters, | ||||||
|  |       ...router.query, | ||||||
|  |     }); | ||||||
|  |     setNumDisplay( | ||||||
|  |       typeof router.query.numDisplay === "string" | ||||||
|  |         ? parseInt(router.query.numDisplay) | ||||||
|  |         : defaultNumDisplay | ||||||
|  |     ); | ||||||
|  |     setReady(true); | ||||||
|  |   }, [router.isReady]); | ||||||
|  | 
 | ||||||
|   /* Functions which I want to have access to the Home namespace */ |   /* Functions which I want to have access to the Home namespace */ | ||||||
|   // I don't want to create an "defaultResults" object for each search.
 |   // I don't want to create an "defaultResults" object for each search.
 | ||||||
|   async function executeSearchOrAnswerWithDefaultResults( |   async function executeSearchOrAnswerWithDefaultResults() { | ||||||
|     queryData: QueryParameters |     const queryData = { | ||||||
|   ) { |       ...queryParameters, | ||||||
|     // the queryData object has the same contents as queryParameters.
 |       numDisplay, | ||||||
|     // but I wanted to spare myself having to think about namespace conflicts.
 |     }; | ||||||
|  | 
 | ||||||
|     let filterManually = (queryData: QueryParameters, results) => { |     let filterManually = (queryData: QueryParameters, results) => { | ||||||
|       if ( |       if ( | ||||||
|         queryData.forecastingPlatforms && |         queryData.forecastingPlatforms && | ||||||
|  | @ -136,43 +145,46 @@ const CommonDisplay: React.FC<Props> = ({ | ||||||
|     }); |     }); | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   useEffect(() => { |   const updateRoute = () => { | ||||||
|     setResults([]); |     const stringify = (key: string, value: any) => { | ||||||
|     let newTimeoutId = setTimeout(async () => { |       if (key === "forecastingPlatforms") { | ||||||
|       let urlSlug = transformObjectIntoUrlSlug({ |         return value.map((x) => x.value).join("|"); | ||||||
|         ...queryParameters, |       } else { | ||||||
|         numDisplay, |         return String(value); | ||||||
|       }); |  | ||||||
|       let urlWithoutDefaultParameters = urlSlug |  | ||||||
|         .replace("?query=&", "?") |  | ||||||
|         .replace("&starsThreshold=2", "") |  | ||||||
|         .replace("&numDisplay=21", "") |  | ||||||
|         .replace("&forecastsThreshold=0", "") |  | ||||||
|         .replace(`&forecastingPlatforms=${platformNames.join("|")}`, ""); |  | ||||||
|       console.log(urlWithoutDefaultParameters); |  | ||||||
|       if (urlWithoutDefaultParameters != "?query=") { |  | ||||||
|         if (typeof window !== "undefined") { |  | ||||||
|           if (!window.location.href.includes(urlWithoutDefaultParameters)) { |  | ||||||
|             window.history.replaceState( |  | ||||||
|               null, |  | ||||||
|               "Metaforecast", |  | ||||||
|               urlWithoutDefaultParameters |  | ||||||
|             ); |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       } |       } | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
|       executeSearchOrAnswerWithDefaultResults({ |     const query = {}; | ||||||
|         ...queryParameters, |     for (const key of Object.keys(defaultQueryParameters)) { | ||||||
|         numDisplay, |       const value = stringify(key, queryParameters[key]); | ||||||
|       }); |       const defaultValue = stringify(key, defaultQueryParameters[key]); | ||||||
|  |       if (value === defaultValue) continue; | ||||||
|  |       query[key] = value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (numDisplay !== defaultNumDisplay) query["numDisplay"] = numDisplay; | ||||||
|  | 
 | ||||||
|  |     router.replace({ | ||||||
|  |       pathname: router.pathname, | ||||||
|  |       query, | ||||||
|  |     }); | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   useEffect(updateRoute, [numDisplay]); | ||||||
|  | 
 | ||||||
|  |   useEffect(() => { | ||||||
|  |     if (!ready) return; | ||||||
|  |     setResults([]); | ||||||
|  |     let newTimeoutId = setTimeout(() => { | ||||||
|  |       updateRoute(); | ||||||
|  |       executeSearchOrAnswerWithDefaultResults(); | ||||||
|     }, 500); |     }, 500); | ||||||
| 
 | 
 | ||||||
|     // avoid sending results if user has not stopped typing.
 |     // avoid sending results if user has not stopped typing.
 | ||||||
|     return () => { |     return () => { | ||||||
|       clearTimeout(newTimeoutId); |       clearTimeout(newTimeoutId); | ||||||
|     }; |     }; | ||||||
|   }, [queryParameters]); |   }, [ready, queryParameters, forceSearch]); | ||||||
| 
 | 
 | ||||||
|   /* State controllers */ |   /* State controllers */ | ||||||
| 
 | 
 | ||||||
|  | @ -195,7 +207,7 @@ const CommonDisplay: React.FC<Props> = ({ | ||||||
|   }; |   }; | ||||||
|   let onChangeSliderForNumDisplay = (event) => { |   let onChangeSliderForNumDisplay = (event) => { | ||||||
|     setNumDisplay(Math.round(event[0])); |     setNumDisplay(Math.round(event[0])); | ||||||
|     // FIXME - force new search if numDisplay is greater than last search limit
 |     setForceSearch(forceSearch + 1); // FIXME - force new search iff numDisplay is greater than last search limit
 | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   /* Change the forecast threshold */ |   /* Change the forecast threshold */ | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user