Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
d537eb0
add ZoomBox with zoomLevel
clarasb Aug 1, 2025
3bffd99
zoom level - round decimal digits
clarasb Aug 1, 2025
7c5f09a
add ZoomBox.stories.tsx
clarasb Aug 1, 2025
50f15fd
add DatasetLevel
clarasb Aug 12, 2025
40b9941
update ZoomBox
clarasb Aug 12, 2025
9a99488
update CHANGES.md
clarasb Aug 12, 2025
bda8644
update ZoomBox.tsx
clarasb Aug 12, 2025
dcaaa05
update ZoomBox.tsx
clarasb Aug 12, 2025
1257ebf
add dataset levels info to Info-Panel
clarasb Aug 13, 2025
25821b4
change position and layout of box
clarasb Aug 15, 2025
b9e01c3
add visibility control for zoomBox
clarasb Aug 18, 2025
7f2e7c3
update styling - remove shadow
clarasb Aug 18, 2025
ebd5577
Apply suggestions from code review
clarasb Sep 18, 2025
f3aa1ec
create ZoomBox directory, update Settings Dialog and add translations
clarasb Sep 18, 2025
820afc8
add getDatasetLevelSelector
clarasb Sep 19, 2025
38e22f1
add zoomLevel to controlState
clarasb Sep 23, 2025
ef8bd91
fix typing
clarasb Sep 23, 2025
c3dec9c
add description to getDatasetLevel()
clarasb Sep 23, 2025
3d0f422
save DatasetZLevel in controlState
clarasb Oct 1, 2025
2194032
Merge branch 'main' into clarasb-287-add_zoom_level
clarasb Oct 1, 2025
6781643
rename ZoomBox to ZoomInfoBox and extend the information on dataset l…
clarasb Oct 13, 2025
fb0edca
update setZoomLevel and add setDatasetZLevel
clarasb Oct 13, 2025
eff2a4b
add setDatasetZLevel to hook dependency
clarasb Oct 13, 2025
ab7f31a
rename showZoomBox to showZoomInfoBox
clarasb Oct 14, 2025
5eab41d
formatting
clarasb Oct 14, 2025
d842ea7
update description for getDatasetLevel
clarasb Oct 14, 2025
b0db37a
add zoom information box to documentation
clarasb Oct 22, 2025
7de1aee
Merge branch 'main' into clarasb-287-add_zoom_level
clarasb Oct 22, 2025
cd1f58c
update ZoomInfoBox.stories.tsx
clarasb Oct 22, 2025
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
21 changes: 14 additions & 7 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@
* A pin icon is now used in the dataset selector to mark a dataset
that holds a pinned variable. (#424)

* Slimmed down the main application bar by grouping features under a
single button that opens a dropdown menu. The features are:
Documentation, Developer Reference, Imprint, and Settings. (#540)
* Slimmed down the main application bar by grouping features under a
single button that opens a dropdown menu. The features are:
Documentation, Developer Reference, Imprint, and Settings. (#540)

### Fixes

* Applied workaround for a bug in `html-to-image` libary that causes an
issuesfor the export of screenshorts (charts and map) in the Firefox
browser.
* Applied workaround for a bug in `html-to-image` libary that causes an
issue for the export of screenshorts (charts and map) in the Firefox
browser.

### New Features

Expand All @@ -42,10 +42,17 @@
Window. If this feature is configured, an `About` window can be opened
with a button in the header and it will be shown initially while
data is loading. (#508)

* A zoom-level indicator was added to the map. This box displays the current
zoom level of the map and the dataset resolution level used for displaying it.
The visibility of this feature can be controlled in the settings. The initial visibility
can be set in `config.json` (`"branding":{ "showZoomInfoBox": true, ...`),
the default is `false`. In addition, the total number of dataset levels has been
added to the metadata in the Info panel. (#287)

### Other changes

* Aligned styling of map elements (Zoom, MapActionsBar, ScaleBar, Attritution,
* Aligned styling of map elements (Zoom, MapActionsBar, ScaleBar, Attribution,
ColorLegend) to match styling of the rest of the Viewer. (#545).

* Redux Developement tools is now available in development mode. Installation of
Expand Down
Binary file added docs/assets/images/zoom_infobox.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 changes: 46 additions & 0 deletions docs/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,52 @@ A list of all the features that the viewer contains will be created here, in whi
</tbody>
</table>

### Zoom Information Box

<table>
<thead>
<tr>
<th colspan="2">
<img src="../assets/images/zoom_infobox.png" alt="Zoom Infobox" />
</th>
</tr>
</thead>
<tbody>
<tr>
<td><b>Feature Name</b></td>
<td>Zoom Information Box</td>
</tr>
<tr>
<td><b>Description</b></td>
<td>
Displays an information box that showing the current
zoom level of the map and the dataset resolution level (particularly
useful for multi-resolution dataset) used for displaying the dataset
in the map.
Comment on lines +514 to +517
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Displays an information box that showing the current
zoom level of the map and the dataset resolution level (particularly
useful for multi-resolution dataset) used for displaying the dataset
in the map.
Displays an information box showing the current
map zoom level and the dataset resolution level used for displaying the
dataset on the map. The the dataset resolution level is particularly
useful for multi-resolution datasets.

</td>
</tr>
<tr></tr>
<tr>
<td><b>Functionality</b></td>
<td>
The visibility of this feature can be controlled in the
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
The visibility of this feature can be controlled in the
The visibility of this feature can be controlled through the

<a
href="../user_guide/settings"
rel="noopener noreferrer"
>settings</a
>.
The initial visibility can be set in the Viewer configuration.
</td>
</tr>
<tr>
<td><b>Aim</b></td>
<td>Enable users to quickly access information about the zoom and dataset
level.
</td>
</tr>
</tbody>
</table>

### Share Permalink

<table>
Expand Down
32 changes: 31 additions & 1 deletion src/actions/controlActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -823,6 +823,34 @@ export function updateUserColorBars(

////////////////////////////////////////////////////////////////////////////////

export const SET_ZOOM_LEVEL = "SET_ZOOM_LEVEL";

export interface SetZoomLevel {
type: typeof SET_ZOOM_LEVEL;
zoomLevel: number | undefined;
}

export function setZoomLevel(zoomLevel: number | undefined): SetZoomLevel {
return { type: SET_ZOOM_LEVEL, zoomLevel };
}

////////////////////////////////////////////////////////////////////////////////

export const SET_DATASET_Z_LEVEL = "SET_DATASET_Z_LEVEL";

export interface SetDatasetZLevel {
type: typeof SET_DATASET_Z_LEVEL;
datasetZLevel: number | undefined;
}

export function setDatasetZLevel(
datasetZLevel: number | undefined,
): SetDatasetZLevel {
return { type: SET_DATASET_Z_LEVEL, datasetZLevel };
}

////////////////////////////////////////////////////////////////////////////////

export type ControlAction =
| SelectDataset
| UpdateDatasetPlaceGroup
Expand Down Expand Up @@ -860,4 +888,6 @@ export type ControlAction =
| SetMapPointInfoBoxEnabled
| SetVariableCompareMode
| UpdateVariableSplitPos
| FlyTo;
| FlyTo
| SetZoomLevel
| SetDatasetZLevel;
1 change: 1 addition & 0 deletions src/components/InfoPanel/DatasetInfoCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ const DatasetInfoCard: React.FC<DatasetInfoContentProps> = ({
dataset.bbox.map((x) => getLabelForValue(x, 3)).join(", "),
],
[i18n.get("Spatial reference system"), dataset.spatialRef],
[i18n.get("Levels"), dataset.resolutions.length],
];
content = (
<InfoCardContent>
Expand Down
10 changes: 10 additions & 0 deletions src/components/SettingsDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,16 @@ const SettingsDialog: React.FC<SettingsDialogProps> = ({
updateSettings={updateSettings}
/>
</SettingsSubPanel>
<SettingsSubPanel
label={i18n.get("Show zoom level indicator")}
value={getOnOff(settings.showZoomInfoBox)}
>
<ToggleSetting
propertyName={"showZoomInfoBox"}
settings={settings}
updateSettings={updateSettings}
/>
</SettingsSubPanel>
<SettingsSubPanel label={i18n.get("On dataset selection")}>
<TextField
variant="standard"
Expand Down
39 changes: 39 additions & 0 deletions src/components/Viewer/Viewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ import { setFeatureStyle } from "@/components/ol/style";
import { findMapLayer } from "@/components/ol/util";
import { isNumber } from "@/util/types";

import { getDatasetZLevel } from "@/model/dataset";

const SELECTION_LAYER_ID = "selection";
const SELECTION_LAYER_SOURCE = new OlVectorSource();

Expand Down Expand Up @@ -126,6 +128,9 @@ interface ViewerProps {
variableSplitPos?: number;
onMapRef?: (map: OlMap | null) => void;
importUserPlacesFromText?: (text: string) => void;
setZoomLevel?: (zoomLevel: number | undefined) => void;
setDatasetZLevel?: (datasetZLevel: number | undefined) => void;
zoomBox?: MapElement;
}

export default function Viewer({
Expand Down Expand Up @@ -158,6 +163,9 @@ export default function Viewer({
imageSmoothing,
variableSplitPos,
onMapRef,
zoomBox,
setZoomLevel,
setDatasetZLevel,
}: ViewerProps) {
theme = useTheme();

Expand Down Expand Up @@ -355,11 +363,41 @@ export default function Viewer({
console.log("tile load progress:", p);
}, []);

const handleMapZoom = (
event: OlMapBrowserEvent<UIEvent>,
map: OlMap | undefined,
) => {
if (setZoomLevel) {
const zoomLevel = event.target.getZoom();
setZoomLevel(zoomLevel);
}

if (setDatasetZLevel) {
const datasetZLevel = getDatasetZLevel(event.target, map);
setDatasetZLevel(datasetZLevel);
}
};

useEffect(() => {
/* Force update of datasetZLevel after variable change. This is needed at
the moment and might become redundant in the future.
This ensures that datasetZLevel gets set, when the Viewer starts, so that
the datasetLevel can be calculated.
*/
if (map) {
if (setDatasetZLevel) {
const datasetZLevel = getDatasetZLevel(map.getView(), map);
setDatasetZLevel(datasetZLevel);
}
}
}, [map, variableLayer, setDatasetZLevel]);

return (
<ErrorBoundary>
<Map
id={mapId}
onClick={(event) => handleMapClick(event)}
onZoom={(event, map) => handleMapZoom(event, map)}
onMapRef={handleMapRef}
mapObjects={MAP_OBJECTS}
isStale={true}
Expand Down Expand Up @@ -431,6 +469,7 @@ export default function Viewer({
{mapPointInfoBox}
{mapControlActions}
{mapSplitter}
{zoomBox}
<ScaleLine bar={false} />
</Map>
</ErrorBoundary>
Expand Down
31 changes: 31 additions & 0 deletions src/components/ZoomInfoBox/ZoomInfoBox.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { Meta, StoryObj } from "@storybook/react-vite";
import ZoomInfoBox from "./ZoomInfoBox";

const meta: Meta = {
component: ZoomInfoBox,
title: "ZoomInfoBox",
parameters: {
// Optional parameter to center the component in the Canvas.
// More info: https://storybook.js.org/docs/configure/story-layout
layout: "centered",
},
// This component will have an automatically generated Autodocs entry:
// https://storybook.js.org/docs/writing-docs/autodocs
tags: ["autodocs"],
} satisfies Meta<typeof ZoomInfoBox>;

// noinspection JSUnusedGlobalSymbols
export default meta;

type Story = StoryObj<typeof meta>;

// noinspection JSUnusedGlobalSymbols
export const Default: Story = {
args: {
style: {},
zoomLevel: 10,
datasetLevel: 3,
datasetLevels: 4,
visibility: true,
},
};
110 changes: 110 additions & 0 deletions src/components/ZoomInfoBox/ZoomInfoBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright (c) 2019-2025 by xcube team and contributors
* Permissions are hereby granted under the terms of the MIT License:
* https://opensource.org/licenses/MIT.
*/

import { CSSProperties } from "react";
import { alpha } from "@mui/material/styles";
import Box from "@mui/material/Box";
import Divider from "@mui/material/Divider";
import Typography from "@mui/material/Typography";

import { getLabelForValue } from "@/util/label";
import { makeStyles } from "@/util/styles";
import { getBorderStyle } from "@/components/ColorBarLegend/style";

const styles = makeStyles({
container: (theme) => ({
position: "absolute",
zIndex: 1000,
border: getBorderStyle(theme),
borderRadius: "4px",
backgroundColor: alpha(theme.palette.background.default, 0.85),
minWidth: "120px",
paddingLeft: theme.spacing(1.5),
paddingRight: theme.spacing(1.5),
paddingBottom: theme.spacing(0.5),
paddingTop: theme.spacing(0.5),
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
gap: 1,
}),
title: {
fontSize: "0.8rem",
fontWeight: "normal",
wordBreak: "break-word",
wordWrap: "break-word",
},
subTitle: {
fontSize: "0.7rem",
fontWeight: "lighter",
wordBreak: "break-word",
wordWrap: "break-word",
},
});

interface ZoomInfoBoxProps {
style: CSSProperties;
zoomLevel: number | undefined;
datasetLevel: number | undefined;
datasetLevels: number;
visibility: boolean;
}

export default function ZoomInfoBox({
style,
zoomLevel,
datasetLevel,
datasetLevels,
visibility,
}: ZoomInfoBoxProps): JSX.Element | null {
if (!visibility) {
return null;
}

return (
<div>
<Box
//className="ol-unselectable ol-control"
sx={styles.container}
style={style}
>
<Box>
<Typography sx={styles.title} variant="subtitle1" color="textPrimary">
{"Zoom"}
</Typography>
<Typography
sx={styles.subTitle}
variant="subtitle2"
color="textPrimary"
>
{zoomLevel !== undefined
? getLabelForValue(zoomLevel, 4)
: "no zoom level"}
</Typography>
</Box>
<Divider orientation="vertical" flexItem />
<Box>
<Typography sx={styles.title} variant="subtitle1" color="textPrimary">
{"Level"}
</Typography>
<Typography
sx={styles.subTitle}
variant="subtitle2"
color="textPrimary"
>
{/* increment datasetLevel with +1, so that the dataset level range
starts with 1 instead of 0.*/}
{datasetLevel !== undefined
? getLabelForValue(datasetLevel + 1, 0) +
" / " +
getLabelForValue(datasetLevels, 0)
: "no dataset level"}
</Typography>
</Box>
</Box>
</div>
);
}
9 changes: 9 additions & 0 deletions src/components/ZoomInfoBox/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* Copyright (c) 2019-2025 by xcube team and contributors
* Permissions are hereby granted under the terms of the MIT License:
* https://opensource.org/licenses/MIT.
*/

import ZoomInfoBox from "./ZoomInfoBox";

export default ZoomInfoBox;
Loading