Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable download button and show tooltip at low zoom levels. [#37 #59] #63

Merged
merged 8 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions site/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions site/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"pmtiles": "^3.0.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-floater": "^0.9.3",
"react-map-gl": "^7.1.7"
},
"devDependencies": {
Expand Down
11 changes: 9 additions & 2 deletions site/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,22 @@ import { useState, useEffect } from "react";

function App() {
const [modeName, setModeName] = useState("theme-dark");
const [zoom, setZoom] = useState(0);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new zoom hook, used to update the download button state


useEffect(() => {
keepTheme(setModeName);
}, [setModeName]);

return (
<MapProvider>
<Header mode={modeName} setMode={setModeName} />
<Map mode={modeName} />
<Header
mode={modeName}
setMode={setModeName}
zoom={zoom}
setZoom={setZoom}
/>
<Map mode={modeName} setZoom={setZoom} />
<Footer mode={modeName} />
</MapProvider>
);
}
Expand Down
10 changes: 9 additions & 1 deletion site/src/Map.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
import "maplibre-gl/dist/maplibre-gl.css";
import * as pmtiles from "pmtiles";
import maplibregl from "maplibre-gl";

import { useState, useEffect, useCallback, useRef } from "react";
import { Layer, GeolocateControl } from "react-map-gl/maplibre";
import InspectorPanel from "./InspectorPanel";
Expand Down Expand Up @@ -133,7 +134,7 @@ ThemeTypeLayer.propTypes = {
extrusion: PropTypes.bool,
};

export default function Map({ mode }) {
export default function Map({ mode, setZoom }) {
const mapRef = useRef();
const [cursor, setCursor] = useState("auto");
const [mapEntity, setMapEntity] = useState({});
Expand All @@ -144,6 +145,7 @@ export default function Map({ mode }) {
useEffect(() => {
const protocol = new pmtiles.Protocol();
maplibregl.addProtocol("pmtiles", protocol.tile);

return () => {
maplibregl.removeProtocol("pmtiles");
};
Expand Down Expand Up @@ -173,6 +175,10 @@ export default function Map({ mode }) {
}
}, []);

const handleZoom = (event) => {
setZoom(event.target.getZoom());
};

return (
<>
<div className={`map ${mode}`}>
Expand All @@ -185,6 +191,7 @@ export default function Map({ mode }) {
onClick={onClick}
cursor={cursor}
hash={true}
onZoom={handleZoom}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Zoom state is dependent on map's zoom state.

mapStyle={MAP_STYLE}
interactiveLayerIds={interactiveLayerIds}
initialViewState={INITIAL_VIEW_STATE}
Expand Down Expand Up @@ -318,6 +325,7 @@ export default function Map({ mode }) {
{Object.keys(mapEntity).length > 0 && (
<InspectorPanel entity={mapEntity} />
)}

<ThemeSelector visibleThemes={setVisibleThemes}></ThemeSelector>
</div>
</div>
Expand Down
4 changes: 4 additions & 0 deletions site/src/nav/DownloadButton.css
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,7 @@ svg.icon-refresh > path.secondary {
div.download-text {
padding-left: 1px;
}

div.download-zoom-tip {
border-radius: 10px;
}
88 changes: 71 additions & 17 deletions site/src/nav/DownloadButton.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,20 @@ import {
import downloadIcon from "/download.svg";
import RefreshIcon from "../icons/icon-refresh.svg?react";
import "./DownloadButton.css";
import Floater from "react-floater";

function DownloadButton() {
const ZOOM_BOUND = 16;

function DownloadButton({ mode, zoom, setZoom }) {
const { myMap } = useMap();

const [loading, setLoading] = useState(false);
const [showFloater, setShowFloater] = useState(false);

useEffect(() => {
if (myMap) {
myMap.getBounds();
setZoom(myMap.getZoom());
}
}, [myMap]);

Expand Down Expand Up @@ -81,25 +86,74 @@ function DownloadButton() {
setLoading(false);
};

const handleToggleTooltip = () => {
if (zoom < ZOOM_BOUND) {
setShowFloater(!showFloater);
}
};

return (
<div className="button--download">
<button
className={`button button--primary ${loading ? "disabled" : ""}`}
onClick={handleDownloadClick}
>
<div className="wrapper">
<div className="download-icon">
{!loading ? (
<img className={"dl-img"} src={downloadIcon} />
) : (
<RefreshIcon />
)}
<div>
<Floater
styles={{
container: {
borderRadius: "10px",
padding: "10px",
color: mode === "theme-dark" ? "white" : "black",
fontSize: ".7rem",
background:
mode === "theme-dark"
? "var(--ifm-navbar-background-color)"
: "var(--ifm-color-secondary-light)",
},
arrow: {
color:
mode === "theme-dark"
? "var(--ifm-navbar-background-color)"
: "var(--ifm-color-secondary-light)",
},
}}
content={
<div>
The download button is disabled at zoom levels below {ZOOM_BOUND}.
This is done to prevent downloading large amounts of data. To
reenable the button, zoom further in. If you wish to download a
larger area of data points, consider using our python installer,
found at{" "}
<a
href={"https://github.com/OvertureMaps/overturemaps-py"}
target="_blank"
rel="noreferrer noopener"
>
our git repository
</a>
.
</div>
<div className="download-text">
{loading ? "Downloading..." : "Download Visible"}
}
open={showFloater}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Floater is "controlled", and only is shown when use is hovering over the 'button--download' div element.

target={".button--download"}
/>
<div className="button--download" onMouseDown={handleToggleTooltip}>
<button
className={`button button--primary ${
loading || zoom < ZOOM_BOUND ? "disabled" : ""
}`}
onClick={handleDownloadClick}
>
<div className="wrapper">
<div className="download-icon">
{!loading ? (
<img className={"dl-img"} src={downloadIcon} />
) : (
<RefreshIcon />
)}
</div>
<div className="download-text">
{loading ? "Downloading..." : "Download Visible"}
</div>
</div>
</div>
</button>
</button>
</div>
</div>
);
}
Expand Down
4 changes: 2 additions & 2 deletions site/src/nav/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import OvertureWordmark from "./OvertureWordmark";
import DarkModeToggle from "./DarkModeToggle";
import PropTypes from "prop-types";

export default function Header({ mode, setMode }) {
export default function Header({ zoom, mode, setMode, setZoom }) {
return (
<nav aria-label="Main" className="navbar navbar--fixed-top">
<div className="navbar__inner">
Expand All @@ -12,7 +12,7 @@ export default function Header({ mode, setMode }) {
</div>
<div className="navbar__items navbar__items--right">
<DarkModeToggle mode={mode} setMode={setMode} />
<DownloadButton />
<DownloadButton zoom={zoom} mode={mode} setZoom={setZoom} />
</div>
</div>
</nav>
Expand Down