Skip to content

Commit

Permalink
hotkeys helpbutton for toggling JSON Debugmode and OSM Power User Mod…
Browse files Browse the repository at this point in the history
…e (Sign in)
  • Loading branch information
bjoernuhlig committed May 26, 2023
1 parent 20b69b7 commit eae93e2
Show file tree
Hide file tree
Showing 9 changed files with 271 additions and 22 deletions.
184 changes: 184 additions & 0 deletions src/components/App/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import { EquipmentProperties, PlaceProperties } from "@sozialhelden/a11yjson";
import "focus-visible";
import findIndex from "lodash/findIndex";
import includes from "lodash/includes";
import * as React from "react";
import "../../lib/NativeAppStrings";
import { hasBigViewport } from "../../lib/ViewportSize";
import config from "../../lib/config";
import savedState, { saveState } from "../../lib/savedState";
import { isTouchDevice } from "../../lib/userAgent";
import { PlaceDetailsProps } from "../app/PlaceDetailsProps";
import MainView, { UnstyledMainView } from "./MainView";

interface Props extends PlaceDetailsProps {
className?: string;
}

interface State {
isMainMenuOpen: boolean;
isSearchBarVisible: boolean;
isOnSmallViewport: boolean;
isSearchToolbarExpanded: boolean;
}

function isStickySearchBarSupported() {
return hasBigViewport() && !isTouchDevice();
}

class App extends React.Component<Props, State> {
props: Props;

state: State = {
lat: null,
lon: null,
isSpecificLatLonProvided: false,
zoom: null,
isSearchBarVisible: isStickySearchBarSupported(),
isMainMenuOpen: false,
modalNodeState: null,
isOnSmallViewport: false,
isSearchToolbarExpanded: false,
};

map: any;

mainView: UnstyledMainView;

static getDerivedStateFromProps(props: Props, state: State): Partial<State> {
const newState: Partial<State> = {
isSearchToolbarExpanded: false,
isSearchBarVisible: isStickySearchBarSupported(),
};

const parsedZoom =
typeof props.zoom === "string" ? parseInt(props.zoom, 10) : null;
const parsedLat =
typeof props.lat === "string" ? parseFloat(props.lat) : null;
const parsedLon =
typeof props.lon === "string" ? parseFloat(props.lon) : null;

newState.extent = state.extent || props.extent || null;
newState.zoom =
state.zoom ||
parsedZoom ||
Number.parseInt(savedState.map.lastZoom, 10) ||
null;
newState.lat =
state.lat ||
parsedLat ||
(savedState.map.lastCenter &&
Number.parseFloat(savedState.map.lastCenter[0])) ||
null;
newState.lon =
state.lon ||
parsedLon ||
(savedState.map.lastCenter &&
Number.parseFloat(savedState.map.lastCenter[1])) ||
null;

newState.isSpecificLatLonProvided =
Boolean(parsedLat) && Boolean(parsedLon);

return newState;
}

onMoveEnd = (state: Partial<State>) => {
let { zoom, lat, lon } = state;

// Adjust zoom level to be stored in the local storage to make sure the user can
// see some places when reloading the app after some time.
const lastZoom = String(
Math.max(
zoom || 0,
config.minZoomWithSetCategory,
config.minZoomWithoutSetCategory
)
);

saveState({
"map.lastZoom": lastZoom,
"map.lastCenter.lat": String(lat),
"map.lastCenter.lon": String(lon),
"map.lastMoveDate": new Date().toString(),
});

this.setState({ extent: null, lat, lon, zoom });
};

onMapClick = () => {
if (this.state.isSearchToolbarExpanded) {
this.closeSearch();
this.mainView && this.mainView.focusMap();
}
};

showSelectedFeature = (
featureId: string | number,
properties?: PlaceProperties | EquipmentProperties | null
) => {
if (!featureId) {
debugger;
}
const featureIdString = featureId.toString();
const { routerHistory } = this.props;

// show equipment inside their place details
let routeName = "placeDetail";
const params = this.getCurrentParams() as any;

params.id = featureIdString;
delete params.eid;

if (
["elevator", "escalator"].includes(properties.category) &&
properties.placeInfoId
) {
const placeInfoId = properties.placeInfoId;
if (includes(["elevator", "escalator"], properties.category)) {
routeName = "equipment";
params.id = placeInfoId;
params.eid = featureIdString;
}
}

let activeCluster = null;
if (this.state.activeCluster) {
const index = findIndex(
this.state.activeCluster.features,
// @ts-ignore
(f) => (f.id || f._id) === featureIdString
);
activeCluster = index !== -1 ? this.state.activeCluster : null;
}

this.setState({ activeCluster }, () => {
routerHistory.push(routeName, params);
});
};

render() {
const { isSpecificLatLonProvided } = this.state;
const isNodeRoute = Boolean(this.props.featureId);
const mapMoveDate = savedState.map.lastMoveDate;
const wasMapMovedRecently =
mapMoveDate && +new Date() - +mapMoveDate < config.locateTimeout;
const shouldLocateOnStart =
!isSpecificLatLonProvided && !isNodeRoute && !wasMapMovedRecently;
const isSearchBarVisible = this.state.isSearchBarVisible;

return (
<>
<GlobalStyle />
<MainView
{...extraProps}
ref={(mainView) => {
this.mainView = mainView;
}}
/>
</>
);
}
}

export default App;
9 changes: 5 additions & 4 deletions src/components/App/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import styled from "styled-components";
import { AppContext } from "../../lib/context/AppContext";
import LoadableMapView from "../MapNew/LoadableMapView";
import GlobalStyle from "./GlobalAppStyle";
import HeadMetaTags from "./HeadMetaTags";
import MainMenu from "./MainMenu/MainMenu";
Expand Down Expand Up @@ -64,9 +63,11 @@ export default function Layout({
/>
)}

<main style={{ height: "100%" }} ref={containerRef}>
<LoadableMapView {...{ containerRef }} />

<main
style={{ height: "100%" }}
ref={containerRef}
>
<MapView {...{ containerRef }} />
<BlurLayer active={blur} style={{ zIndex: 1000 }} />
<div style={{ zIndex: 2000 }}>{children}</div>
<ToastContainer position="bottom-center" />
Expand Down
24 changes: 20 additions & 4 deletions src/components/App/MainMenu/AppLinks.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useHotkeys } from "@blueprintjs/core";
import Link from "next/link";
import React from "react";
import { useMemo, useState } from "react";
import styled from "styled-components";
import colors from "../../../lib/colors";
import { useCurrentApp } from "../../../lib/context/AppContext";
Expand Down Expand Up @@ -50,6 +51,19 @@ export default function AppLinks(props: {}) {
related: { appLinks },
} = app;


const [toogle, setToogle] = useState(false);
const hotkeys = useMemo(() => [
{
combo: "l",
global: true,
label: "Toogle OSM Power User Mode",
onKeyDown: () => setToogle(!toogle),
},

], [toogle]);
const { handleKeyDown, handleKeyUp } = useHotkeys(hotkeys);

const links = Object.values(appLinks)
.sort((a, b) => (a.order || 0) - (b.order || 0))
.map((link) => {
Expand Down Expand Up @@ -89,10 +103,12 @@ export default function AppLinks(props: {}) {
if (isEventsLink) {
return <JoinedEventLink {...{ label, url }} key="joined-event" />;
}

const isSessionLink = link.tags && link.tags.indexOf("session") !== -1;
if (isSessionLink) {
return <SessionLink {...{ label }} key="session" className={className} />;
return (
toogle && <SessionLink {...{ label }} key="session" className={className} onKeyDown={handleKeyDown} />
);
}

if (typeof url === "string") {
Expand All @@ -108,4 +124,4 @@ export default function AppLinks(props: {}) {
});

return <>{links}</>;
}
}
24 changes: 20 additions & 4 deletions src/components/CombinedFeaturePanel/CombinedFeaturePanel.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { useHotkeys } from "@blueprintjs/core";
import { uniqBy } from "lodash";
import { useMemo, useState } from "react";
import styled from "styled-components";
import colors from "../../lib/colors";
import {
Expand All @@ -7,9 +9,9 @@ import {
isOSMFeature,
isSearchResultFeature
} from "../../lib/model/shared/AnyFeature";
import FeaturesDebugJSON from "./components/FeaturesDebugJSON";
import OSMBuildingDetails from "./OSMBuildingDetails";
import OSMSidewalkDetails from "./OSMSidewalkDetails";
import FeaturesDebugJSON from "./components/FeaturesDebugJSON";
import PlaceOfInterestDetails from "./type-specific/poi/PlaceOfInterestDetails";

type Props = {
Expand Down Expand Up @@ -46,9 +48,21 @@ export function CombinedFeaturePanel(props: Props) {
isSearchResultFeature(feature) ? feature.properties.osm_id : feature._id
);

/* Hotkeys */
const [toogle, setToogle] = useState(false);
const hotkeys = useMemo(() => [
{
combo: "j",
global: true,
label: "Show JSON Feature Debugger",
onKeyDown: () => setToogle(!toogle),
},

], [toogle]);
const { handleKeyDown, handleKeyUp } = useHotkeys(hotkeys);

return (
<Panel>
<Panel onKeyDown={handleKeyDown} >
{features && features[0] && (
<>
<PlaceOfInterestDetails feature={features[0]} />
Expand All @@ -65,9 +79,11 @@ export function CombinedFeaturePanel(props: Props) {
features
.slice(1)
.map((feature) => <FeatureSection key={getKey(feature)} feature={feature} />)}

<p>
<FeaturesDebugJSON features={features} />
{toogle && <FeaturesDebugJSON features={features} /> }
</p>
</Panel>
</Panel>
);
}

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type Props = {
const Card = styled.section`
background-color: white;
padding: 0.25rem 0.5rem;
box-shadow: 0 0.125rem 0.125rem rgba(0, 0, 0, 0.1);
box-shadow: 0 0.125rem 1.125rem rgba(0, 0, 0, 0.1);
border-radius: 0.25rem;
margin: 0 -0.25rem;
`;
Expand Down
23 changes: 23 additions & 0 deletions src/components/CombinedFeaturePanel/components/HelpButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import {
Button,
HotkeysContext
} from '@blueprintjs/core';
import React from "react";

export default function HelpButton() {
const [, dispatch] = React.useContext(HotkeysContext);
const openHelp = React.useCallback(() => {
dispatch({ type: 'OPEN_DIALOG' });
}, [dispatch]);
return (
<Button
text="?"
large
onClick={openHelp}
style={{
position: 'fixed', left: '1rem', bottom: '1rem', borderRadius: '50%', fontSize: '1rem', zIndex: 10,
}}
/>
);
}

7 changes: 6 additions & 1 deletion src/components/MapNew/MapView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { useRouter } from "next/router";
import * as React from "react";
import { useCallback, useLayoutEffect, useRef, useState } from "react";
import {
Layer, Map, MapProvider, MapRef,
Layer,
Map,
MapProvider,
MapRef,
NavigationControl,
Source,
ViewState,
Expand All @@ -17,6 +20,7 @@ import { uniq } from "lodash";
import "mapbox-gl/dist/mapbox-gl.css";
import { createGlobalStyle } from "styled-components";
import getFeatureIdsFromLocation from "../../lib/model/shared/getFeatureIdsFromLocation";
import HelpButton from "../CombinedFeaturePanel/components/HelpButton";
import { databaseTableNames, filterLayers } from "./filterLayers";
import useMapStyle from "./useMapStyle";

Expand Down Expand Up @@ -225,6 +229,7 @@ export default function MapView(props: IProps) {
<NavigationControl style={{ right: "1rem", top: "1rem" }} />
</Map>
</MapProvider>
<HelpButton />
</>
);
}
7 changes: 4 additions & 3 deletions src/components/Session/SessionLink.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

import { Spinner } from "@blueprintjs/core"
import { useSession } from "next-auth/react"
import { Spinner } from "@blueprintjs/core";
import { useSession } from "next-auth/react";
import Link from "next/link";
import { t } from "ttag";
import { UserIcon } from "../icons/ui-elements";
Expand All @@ -27,4 +27,5 @@ export default function SessionLink({ label, className }: { label: string, class
return <Link href={"/me"} className={className}>
{t`Sign in`}
</Link>
}
}

Loading

0 comments on commit eae93e2

Please sign in to comment.