Skip to content

Commit

Permalink
Merge pull request #91 from flatironinstitute/query-url-loading-back-…
Browse files Browse the repository at this point in the history
…button

Enable back button functionality, clear url on load
  • Loading branch information
WardBrian authored Jun 27, 2024
2 parents db93faf + 26ee51e commit 5e41980
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 31 deletions.
24 changes: 15 additions & 9 deletions gui/src/app/SPAnalysis/SPAnalysisContextProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -19,10 +20,9 @@ export const SPAnalysisContext = createContext<SPAnalysisContextType>({


const SPAnalysisContextProvider: FunctionComponent<PropsWithChildren<SPAnalysisContextProviderProps>> = ({ children }) => {
const [data, update] = useReducer<SPAnalysisReducerType>(SPAnalysisReducer, initialDataModel)

const { queries, clearSearchParams } = useQueryParams();

const [data, update] = useReducer<SPAnalysisReducerType>(SPAnalysisReducer(clearSearchParams), initialDataModel)
const [searchParams, setSearchParams] = useSearchParams();

useEffect(() => {
// as user reloads the page or closes the tab, save state to local storage
Expand All @@ -38,11 +38,15 @@ const SPAnalysisContextProvider: FunctionComponent<PropsWithChildren<SPAnalysisC
}, [data])

useEffect(() => {
if (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
Expand All @@ -51,8 +55,10 @@ const SPAnalysisContextProvider: FunctionComponent<PropsWithChildren<SPAnalysisC
const parsedData = deserializeAnalysisFromLocalStorage(savedState)
update({ type: 'loadInitialData', state: parsedData })
}

}, [data, queries])
// once we have loaded some data, we don't need the localStorage again
// and it will be overwritten by the above event listener on close
localStorage.removeItem('stan-playground-saved-state')
}, [searchParams, setSearchParams])

return (
<SPAnalysisContext.Provider value={{ data, update }}>
Expand Down
15 changes: 2 additions & 13 deletions gui/src/app/SPAnalysis/SPAnalysisQueryLoading.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { useSearchParams } from "react-router-dom";
import { SPAnalysisDataModel, initialDataModel, persistStateToEphemera } from "./SPAnalysisDataModel";
import { useCallback } from "react";


enum QueryParamKeys {
Expand All @@ -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
Expand All @@ -49,7 +38,7 @@ export const useQueryParams = () => {
seed: searchParams.get(QueryParamKeys.SOSeed),
}

return { queries, clearSearchParams }
return queries;
}

export const queryStringHasParameters = (query: QueryParams) => {
Expand Down
11 changes: 2 additions & 9 deletions gui/src/app/SPAnalysis/SPAnalysisReducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -123,4 +116,4 @@ const loadFromProjectFiles = (data: SPAnalysisDataModel, files: Partial<FieldsCo
newData = fileKeys.reduce((currData, currField) => loadFileFromString(currData, currField, files[currField] ?? ''), newData)
newData = persistStateToEphemera(newData)
return newData
}
}

0 comments on commit 5e41980

Please sign in to comment.