From 62a74e99547a191a18233580aa01b81ab3e0c2e6 Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Wed, 26 Jun 2024 20:01:34 +0000 Subject: [PATCH 1/2] Enable back button, clears url on load --- .../SPAnalysis/SPAnalysisContextProvider.tsx | 19 +++++++++++++------ .../app/SPAnalysis/SPAnalysisQueryLoading.ts | 15 ++------------- gui/src/app/SPAnalysis/SPAnalysisReducer.ts | 11 ++--------- 3 files changed, 17 insertions(+), 28 deletions(-) diff --git a/gui/src/app/SPAnalysis/SPAnalysisContextProvider.tsx b/gui/src/app/SPAnalysis/SPAnalysisContextProvider.tsx index f18fa591..62d28843 100644 --- a/gui/src/app/SPAnalysis/SPAnalysisContextProvider.tsx +++ b/gui/src/app/SPAnalysis/SPAnalysisContextProvider.tsx @@ -2,7 +2,8 @@ import { initialDataModel, SPAnalysisDataModel } from "./SPAnalysisDataModel" import { createContext, FunctionComponent, PropsWithChildren, useEffect, useReducer } from "react" import { SPAnalysisReducer, SPAnalysisReducerAction, SPAnalysisReducerType } from "./SPAnalysisReducer" import { deserializeAnalysisFromLocalStorage, serializeAnalysisToLocalStorage } from "./SPAnalysisSerialization" -import { fetchRemoteAnalysis, queryStringHasParameters, useQueryParams } from "./SPAnalysisQueryLoading" +import { fetchRemoteAnalysis, queryStringHasParameters, fromQueryParams } from "./SPAnalysisQueryLoading" +import { useSearchParams } from "react-router-dom" type SPAnalysisContextType = { data: SPAnalysisDataModel @@ -19,10 +20,10 @@ export const SPAnalysisContext = createContext({ const SPAnalysisContextProvider: FunctionComponent> = ({ children }) => { + const [data, update] = useReducer(SPAnalysisReducer, initialDataModel) - const { queries, clearSearchParams } = useQueryParams(); + const [searchParams, setSearchParams] = useSearchParams(); - const [data, update] = useReducer(SPAnalysisReducer(clearSearchParams), initialDataModel) useEffect(() => { // as user reloads the page or closes the tab, save state to local storage @@ -38,11 +39,17 @@ const SPAnalysisContextProvider: FunctionComponent { - if (data != initialDataModel) return; + if (searchParams.size === 0 && data !== initialDataModel) return; + const queries = fromQueryParams(searchParams) if (queryStringHasParameters(queries)) { fetchRemoteAnalysis(queries).then((data) => { - update({ type: 'loadInitialData', state: data }) + update({ type: 'loadInitialData', state: data }); + + // set title so that history is better preserved in the browser + document.title = "Stan Playground - " + data.meta.title; + // clear search parameters now that load is complete + setSearchParams(new URLSearchParams()); }) } else { // load the saved state on first load @@ -52,7 +59,7 @@ const SPAnalysisContextProvider: FunctionComponent diff --git a/gui/src/app/SPAnalysis/SPAnalysisQueryLoading.ts b/gui/src/app/SPAnalysis/SPAnalysisQueryLoading.ts index 9282c58a..c7351e26 100644 --- a/gui/src/app/SPAnalysis/SPAnalysisQueryLoading.ts +++ b/gui/src/app/SPAnalysis/SPAnalysisQueryLoading.ts @@ -1,6 +1,4 @@ -import { useSearchParams } from "react-router-dom"; import { SPAnalysisDataModel, initialDataModel, persistStateToEphemera } from "./SPAnalysisDataModel"; -import { useCallback } from "react"; enum QueryParamKeys { @@ -19,16 +17,7 @@ type QueryParams = { [key in QueryParamKeys]: string | null } -export const useQueryParams = () => { - const [searchParams, setSearchParams] = useSearchParams(); - - const clearSearchParams = useCallback(() => { - // whenever the data state is 'dirty', we want to - // clear the URL bar as to indiciate that the viewed content is - // no longer what the link would point to - if (searchParams.size !== 0) - setSearchParams(new URLSearchParams()) - }, [searchParams, setSearchParams]); +export const fromQueryParams = (searchParams: URLSearchParams) => { for (const key of searchParams.keys()) { // warn on unknown keys @@ -49,7 +38,7 @@ export const useQueryParams = () => { seed: searchParams.get(QueryParamKeys.SOSeed), } - return { queries, clearSearchParams } + return queries; } export const queryStringHasParameters = (query: QueryParams) => { diff --git a/gui/src/app/SPAnalysis/SPAnalysisReducer.ts b/gui/src/app/SPAnalysis/SPAnalysisReducer.ts index 8e2ab806..4577f399 100644 --- a/gui/src/app/SPAnalysis/SPAnalysisReducer.ts +++ b/gui/src/app/SPAnalysis/SPAnalysisReducer.ts @@ -34,14 +34,7 @@ export type SPAnalysisReducerAction = { type: 'clear' } -export const SPAnalysisReducer = (onDirty: () => void) => (s: SPAnalysisDataModel, a: SPAnalysisReducerAction) => { - if (a.type !== "loadInitialData") { - // TextEditor seems to trigger occasional spurious edits where nothing changes - if (a.type !== "editFile" || s[a.filename] != a.content) { - onDirty(); - } - } - +export const SPAnalysisReducer = (s: SPAnalysisDataModel, a: SPAnalysisReducerAction) => { switch (a.type) { case "loadStanie": { const dataFileContent = JSON.stringify(a.stanie.data, null, 2); @@ -123,4 +116,4 @@ const loadFromProjectFiles = (data: SPAnalysisDataModel, files: Partial loadFileFromString(currData, currField, files[currField] ?? ''), newData) newData = persistStateToEphemera(newData) return newData -} \ No newline at end of file +} From 26ee51e7fc3b27240577ba3e7ef3ad879e82a7d0 Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Thu, 27 Jun 2024 20:14:47 +0000 Subject: [PATCH 2/2] Avoid conditional in useEffect --- gui/src/app/SPAnalysis/SPAnalysisContextProvider.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/gui/src/app/SPAnalysis/SPAnalysisContextProvider.tsx b/gui/src/app/SPAnalysis/SPAnalysisContextProvider.tsx index 62d28843..ddad1ed7 100644 --- a/gui/src/app/SPAnalysis/SPAnalysisContextProvider.tsx +++ b/gui/src/app/SPAnalysis/SPAnalysisContextProvider.tsx @@ -24,7 +24,6 @@ const SPAnalysisContextProvider: FunctionComponent { // as user reloads the page or closes the tab, save state to local storage const handleBeforeUnload = () => { @@ -39,8 +38,6 @@ const SPAnalysisContextProvider: FunctionComponent { - if (searchParams.size === 0 && data !== initialDataModel) return; - const queries = fromQueryParams(searchParams) if (queryStringHasParameters(queries)) { fetchRemoteAnalysis(queries).then((data) => { @@ -58,8 +55,10 @@ const SPAnalysisContextProvider: FunctionComponent