diff --git a/josh-ui/src/App.tsx b/josh-ui/src/App.tsx index 4c5d57e58..32b7d850c 100644 --- a/josh-ui/src/App.tsx +++ b/josh-ui/src/App.tsx @@ -2,6 +2,7 @@ import './App.scss'; import {FileList} from './FileBrowser'; import {useEffect} from 'react'; +import {None, Option} from 'tsoption'; import { BrowserRouter, @@ -20,6 +21,7 @@ import {match} from "ts-pattern"; import {FileViewer} from "./FileViewer"; import {HistoryList} from "./History"; import {Breadcrumbs} from "./Breadcrumbs"; +import {DEFAULT_FILTER} from "./Josh"; function useNavigateCallback(): NavigateCallback { const navigate = useNavigate() @@ -47,46 +49,80 @@ function useNavigateCallback(): NavigateCallback { function useGetSearchParam() { let [ searchParams ] = useSearchParams() - return (key: string): string => { + return (key: string): Option => { let value = searchParams.get(key) + if (value === null) { - throw new Error(`Search param ${key} was not provided`) + return new None() } - return value + return Option.of(value) + } +} + +function useStrictGetSearchParam() { + const param = useGetSearchParam() + + return (key: string): string => { + const value = param(key) + + if (value.isEmpty()) { + throw new Error(`Search param ${key} was not provided`) + } else { + return value.getOrElse('') + } } } function Select() { + const param = useGetSearchParam() + useEffect(() => { document.title = `Select repo - Josh` }); + const filter = param('filter').flatMap(value => { + if (value === DEFAULT_FILTER) { + return new None() + } else { + return Option.of(value) + } + }) + return
- +
} -function TopNav(props: { repo: string, filter: string}) { +function TopNav(props: { repo: string, filter: string }) { + const selectParams = { + repo: props.repo, + filter: props.filter, + } + return
- now browsing: {props.repo} + now browsing: {props.repo} - {props.filter !== ':/' && + {props.filter !== DEFAULT_FILTER && {props.filter} } - select repo + select repo
} function Browse() { - const param = useGetSearchParam() + const param = useStrictGetSearchParam() useEffect(() => { document.title = `/${param('path')} - ${param('repo')} - Josh` @@ -115,7 +151,7 @@ function Browse() { } function History() { - const param = useGetSearchParam() + const param = useStrictGetSearchParam() useEffect(() => { document.title = `History - ${param('repo')} - Josh` @@ -137,7 +173,7 @@ function History() { function View() { - const param = useGetSearchParam() + const param = useStrictGetSearchParam() useEffect(() => { document.title = `${param('path')} - ${param('repo')} - Josh` diff --git a/josh-ui/src/Josh.tsx b/josh-ui/src/Josh.tsx new file mode 100644 index 000000000..a6c828836 --- /dev/null +++ b/josh-ui/src/Josh.tsx @@ -0,0 +1 @@ +export const DEFAULT_FILTER = ':/' diff --git a/josh-ui/src/RepoSelector.tsx b/josh-ui/src/RepoSelector.tsx index 9f9c2ee03..e72583000 100644 --- a/josh-ui/src/RepoSelector.tsx +++ b/josh-ui/src/RepoSelector.tsx @@ -3,6 +3,7 @@ import {match, select, when} from 'ts-pattern'; import {None, Option} from 'tsoption'; import {getServer} from './Server'; import {NavigateCallback, NavigateTargetType} from "./Navigation"; +import {DEFAULT_FILTER} from "./Josh"; type Remote = | { type: 'None' } @@ -48,6 +49,8 @@ function formatHint(checkResult: UrlCheckResult, filter: Option): string type RepoSelectorProps = { navigateCallback: NavigateCallback + repo: Option + filter: Option } type State = { @@ -65,8 +68,8 @@ type ParsedInput = { export class RepoSelector extends React.Component { state: State = { remote: { type: 'None' }, - repo: new None(), - filter: new None(), + repo: this.props.repo, + filter: this.props.filter, }; componentDidMount () { @@ -143,7 +146,7 @@ export class RepoSelector extends React.Component { this.props.navigateCallback(NavigateTargetType.History, { repo: parsedInput.target[0].getOrElse('') + '.git', path: '', - filter: parsedInput.target[1].getOrElse(':/'), + filter: parsedInput.target[1].getOrElse(DEFAULT_FILTER), rev: 'HEAD', }) } @@ -169,6 +172,7 @@ export class RepoSelector extends React.Component { } {