Skip to content

Commit

Permalink
WV-3049: Dismiss DDV notifications with local storage (#5101)
Browse files Browse the repository at this point in the history
* DDV Alerts WIP

* dismiss ddv zoom & location alerts

* clean up

* turn off alerts when zoomed or located correctly

* update ddv check to include Nadir

* cleanup

* include opera layer

* handle multiple dismissable alerts
  • Loading branch information
ryanweiler92 committed Apr 17, 2024
1 parent 4eb27c7 commit 778e88d
Show file tree
Hide file tree
Showing 6 changed files with 218 additions and 9 deletions.
69 changes: 67 additions & 2 deletions web/js/containers/alerts.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ import { DISABLE_VECTOR_ZOOM_ALERT, DISABLE_VECTOR_EXCEEDED_ALERT, MODAL_PROPERT
import safeLocalStorage from '../util/local-storage';
import { getActiveLayers, subdailyLayersActive } from '../modules/layers/selectors';

const { granuleModalProps, zoomModalProps } = MODAL_PROPERTIES;

const HAS_LOCAL_STORAGE = safeLocalStorage.enabled;
const {
DISMISSED_COMPARE_ALERT,
DISMISSED_DISTRACTION_FREE_ALERT,
DISMISSED_EVENT_VIS_ALERT,
DISSMISSED_DDV_ZOOM_ALERT,
DISSMISSED_DDV_LOCATION_ALERT,
} = safeLocalStorage.keys;

class DismissableAlerts extends React.Component {
Expand All @@ -24,6 +28,8 @@ class DismissableAlerts extends React.Component {
hasDismissedEvents: !!safeLocalStorage.getItem(DISMISSED_EVENT_VIS_ALERT),
hasDismissedCompare: !!safeLocalStorage.getItem(DISMISSED_COMPARE_ALERT),
hasDismissedDistractionFree: !!safeLocalStorage.getItem(DISMISSED_DISTRACTION_FREE_ALERT),
hasDismissedDDVZoom: !!safeLocalStorage.getItem(DISSMISSED_DDV_ZOOM_ALERT),
hasDismissedDDVLocation: !!safeLocalStorage.getItem(DISSMISSED_DDV_LOCATION_ALERT),
distractionFreeModeInitLoad: false,
};
}
Expand Down Expand Up @@ -75,12 +81,20 @@ class DismissableAlerts extends React.Component {
isVectorZoomAlertPresent,
isVectorExceededAlertPresent,
openAlertModal,
isDDVZoomAlertPresent,
isDDVLocationAlertPresent,
openGranuleAlertModal,
openZoomAlertModal,
ddvZoomAlerts,
ddvLocationAlerts,
} = this.props;
const {
hasDismissedEvents,
hasDismissedCompare,
hasDismissedDistractionFree,
distractionFreeModeInitLoad,
hasDismissedDDVZoom,
hasDismissedDDVLocation,
} = this.state;
const { eventModalProps, compareModalProps, vectorModalProps } = MODAL_PROPERTIES;
const hasFailCondition = !HAS_LOCAL_STORAGE
Expand All @@ -91,6 +105,8 @@ class DismissableAlerts extends React.Component {
const showEventsAlert = !isSmall && !hasDismissedEvents && isEventsActive;
const showCompareAlert = !isSmall && !hasDismissedCompare && isCompareActive;
const showAnimationAlert = isMobile && isAnimationActive && hasSubdailyLayers;
const showDDVZoomAlert = isDDVZoomAlertPresent && !hasDismissedDDVZoom;
const showDDVLocationAlert = isDDVLocationAlertPresent && !hasDismissedDDVLocation;

return isDistractionFreeModeActive
? !hasDismissedDistractionFree && (
Expand Down Expand Up @@ -148,7 +164,32 @@ class DismissableAlerts extends React.Component {
onDismiss={() => {}}
/>
)}

{showDDVZoomAlert
&& ddvZoomAlerts.map((layer) => (
<AlertUtil
id="zoom-alert"
isOpen
noPortal
title="Zoom in to see imagery for this layer"
messageTitle={layer}
message="Imagery is not available at this zoom level."
onDismiss={() => this.dismissAlert(DISSMISSED_DDV_ZOOM_ALERT, 'hasDismissedDDVZoom')}
onClick={openZoomAlertModal}
/>
))}
{ showDDVLocationAlert
&& ddvLocationAlerts.map((layer) => (
<AlertUtil
id="granule-alert"
isOpen
noPortal
title="Try moving the map or select a different date in the layer's settings."
messageTitle={layer}
message="Imagery is not available at this location or date."
onDismiss={() => this.dismissAlert(DISSMISSED_DDV_LOCATION_ALERT, 'hasDismissedDDVLocation')}
onClick={openGranuleAlertModal}
/>
))}
</>
);
}
Expand All @@ -157,19 +198,38 @@ const mapDispatchToProps = (dispatch) => ({
openAlertModal: ({ id, props }) => {
dispatch(openCustomContent(id, props));
},
openGranuleAlertModal: () => {
const { id, props } = granuleModalProps;
dispatch(openCustomContent(id, props));
},
openZoomAlertModal: () => {
const { id, props } = zoomModalProps;
dispatch(openCustomContent(id, props));
},
dismissVectorZoomAlert: () => dispatch({ type: DISABLE_VECTOR_ZOOM_ALERT }),
dismissVectorExceededAlert: () => dispatch({ type: DISABLE_VECTOR_EXCEEDED_ALERT }),
});
const mapStateToProps = (state) => {
const {
embed, events, sidebar, compare, alerts, ui, animation, screenSize,
} = state;
const { isVectorZoomAlertPresent, isVectorExceededAlertPresent } = alerts;
const {
isVectorZoomAlertPresent,
isVectorExceededAlertPresent,
isDDVZoomAlertPresent,
isDDVLocationAlertPresent,
ddvZoomAlerts,
ddvLocationAlerts,
} = alerts;
const activeLayers = getActiveLayers(state);
const hasActiveVectorLayers = hasVectorLayers(activeLayers);

return {
ddvLocationAlerts,
ddvZoomAlerts,
isCompareActive: compare.active,
isDDVZoomAlertPresent,
isDDVLocationAlertPresent,
isDistractionFreeModeActive: ui.isDistractionFreeModeActive,
isEmbedModeActive: embed.isEmbedModeActive,
isEventsActive: !!(events.selected.id && sidebar.activeTab === 'events'),
Expand Down Expand Up @@ -200,4 +260,9 @@ DismissableAlerts.propTypes = {
isVectorZoomAlertPresent: PropTypes.bool,
isVectorExceededAlertPresent: PropTypes.bool,
openAlertModal: PropTypes.func,
isDDVZoomAlertPresent: PropTypes.bool,
isDDVLocationAlertPresent: PropTypes.bool,
openGranuleAlertModal: PropTypes.func,
openZoomAlertModal: PropTypes.func,
activeDDVLayer: PropTypes.object,
};
90 changes: 83 additions & 7 deletions web/js/containers/sidebar/layer-row.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/* eslint-disable react/jsx-props-no-spreading */
/* eslint-disable react/no-danger */
import React, { useState, useEffect } from 'react';
import { useSelector, connect } from 'react-redux';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { Draggable } from 'react-beautiful-dnd';
import { isEmpty as lodashIsEmpty, get as lodashGet } from 'lodash';
Expand Down Expand Up @@ -40,6 +40,9 @@ import {
updateActiveChartingLayerAction,
} from '../../modules/charting/actions';
import AlertUtil from '../../components/util/alert';
import {
enableDDVZoomAlert, enableDDVLocationAlert, disableDDVLocationAlert, disableDDVZoomAlert,
} from '../../modules/alerts/actions';

const { events } = util;
const { vectorModalProps, granuleModalProps, zoomModalProps } = MODAL_PROPERTIES;
Expand All @@ -57,6 +60,8 @@ function LayerRow (props) {
layer,
compareState,
collections,
ddvLocationAlerts,
ddvZoomAlerts,
paletteLegends,
getPalette,
palette,
Expand Down Expand Up @@ -91,6 +96,12 @@ function LayerRow (props) {
isChartingActive,
activeChartingLayer,
updateActiveChartingLayer,
enableDDVZoomAlert,
enableDDVLocationAlert,
disableDDVLocationAlert,
disableDDVZoomAlert,
map,
selectedDate,
} = props;

const encodedLayerId = util.encodeId(layer.id);
Expand All @@ -114,8 +125,11 @@ function LayerRow (props) {
const [showGranuleAlert, setShowGranuleAlert] = useState(false);
const [hideZoomAlert, setHideZoomAlert] = useState(false);
const [hideGranuleAlert, setHideGranuleAlert] = useState(false);
const map = useSelector((state) => state.map);
const selectedDate = useSelector((state) => state.date.selected);

const ddvLayerZoomNoticeActive = ddvZoomAlerts.includes(layer.title);
const ddvLayerLocationNoticeActive = ddvLocationAlerts.includes(layer.title);
// All DDV layer notices are dismissable + Reflectance (Nadir BRDF-Adjusted) + DSWx-HLS
const isLayerNotificationDismissable = layer.type === 'ttiler' || layer.title === 'Reflectance (Nadir BRDF-Adjusted)' || layer.subtitle === 'DSWx-HLS';

useEffect(() => {
const asyncFunc = async () => {
Expand Down Expand Up @@ -164,6 +178,30 @@ function LayerRow (props) {
asyncFunc();
}, [map.extent, zot, selectedDate, isVisible]);

// hook that checks if the ddv layer zoom alert should be enabled or disabled
useEffect(() => {
const { title } = layer;
// if layer is ddv && layer IS NOT already in zoom alert list && zoom is at alertable level
if (isLayerNotificationDismissable && !ddvLayerZoomNoticeActive && showZoomAlert) {
enableDDVZoomAlert(title);
// if layer is ddv && layer IS already in zoom alert list && zoom is NOT at alertable level
} else if (isLayerNotificationDismissable && ddvLayerZoomNoticeActive && !showZoomAlert) {
disableDDVZoomAlert(title);
}
}, [showZoomAlert]);

// hook that checks if the ddv layer location alert should be enabled or disabled
useEffect(() => {
const { title } = layer;
// if layer is ddv && layer IS NOT already in location alert list && location is at alertable coordinates
if (isLayerNotificationDismissable && !ddvLayerLocationNoticeActive && showGranuleAlert) {
enableDDVLocationAlert(title);
// if layer is ddv && layer IS NOT already in location alert list && location is at alertable coordinates
} else if (isLayerNotificationDismissable && ddvLayerLocationNoticeActive && !showGranuleAlert) {
disableDDVLocationAlert(title);
}
}, [showGranuleAlert]);

useEffect(() => {
events.on(MAP_RUNNING_DATA, setRunningDataObj);
return () => {
Expand Down Expand Up @@ -253,6 +291,21 @@ function LayerRow (props) {
e.preventDefault();
};

// function called on click when removing a layer
const removeLayer = () => {
const { id, title } = layer;
// remove ddv location alert
if (ddvLayerLocationNoticeActive) {
disableDDVLocationAlert(title);
}
// remove ddv zoom alert
if (ddvLayerZoomNoticeActive) {
disableDDVZoomAlert(title);
}
// remove layer
onRemoveClick(id);
};

const renderDropdownMenu = () => (
<Dropdown className="layer-group-more-options" isOpen={showDropdownMenu} toggle={toggleDropdownMenuVisible}>
<DropdownToggle>
Expand Down Expand Up @@ -280,7 +333,7 @@ function LayerRow (props) {
</DropdownItem>
<DropdownItem
id={removeLayerBtnId}
onClick={() => onRemoveClick(layer.id)}
onClick={() => removeLayer()}
className="button wv-layers-options layer-options-dropdown-item"
>
{removeLayerBtnTitle}
Expand All @@ -297,7 +350,7 @@ function LayerRow (props) {
id={removeLayerBtnId}
aria-label={removeLayerBtnTitle}
className={isMobile ? 'hidden wv-layers-options' : 'button wv-layers-close'}
onClick={() => onRemoveClick(layer.id)}
onClick={() => removeLayer()}
>
<UncontrolledTooltip id="center-align-tooltip" placement="top" target={removeLayerBtnId}>
{removeLayerBtnTitle}
Expand Down Expand Up @@ -503,7 +556,7 @@ function LayerRow (props) {
))}
</div>
)}
{showZoomAlert && !hideZoomAlert && (
{showZoomAlert && !hideZoomAlert && !isLayerNotificationDismissable && (
<AlertUtil
id="zoom-alert"
isOpen
Expand All @@ -514,7 +567,7 @@ function LayerRow (props) {
onClick={openZoomAlertModal}
/>
)}
{showGranuleAlert && !hideGranuleAlert && (
{showGranuleAlert && !hideGranuleAlert && !isLayerNotificationDismissable && (
<AlertUtil
id="granule-alert"
isOpen
Expand Down Expand Up @@ -591,13 +644,17 @@ const makeMapStateToProps = () => {
);
const activeDate = compare.activeString === 'active' ? date.selected : date.selectedB;
const dailyDate = formatDailyDate(activeDate);
const selectedDate = date.selected;
const subdailyDate = formatSubdailyDate(activeDate);
const collections = getCollections(layers, dailyDate, subdailyDate, layer);
const measurementDescriptionPath = getDescriptionPath(state, ownProps);
const { ddvZoomAlerts, ddvLocationAlerts } = state.alerts;

return {
compare,
collections,
ddvLocationAlerts,
ddvZoomAlerts,
tracksForLayer,
measurementDescriptionPath,
globalTemperatureUnit,
Expand All @@ -614,6 +671,8 @@ const makeMapStateToProps = () => {
getPalette: (layerId, i) => getPalette(layer.id, i, compareState, state),
paletteLegends,
palettes,
map,
selectedDate,
renderedPalette: renderedPalettes[paletteName],
};
};
Expand Down Expand Up @@ -689,6 +748,18 @@ const mapDispatchToProps = (dispatch) => ({
updateActiveChartingLayer: (layersId) => {
dispatch(updateActiveChartingLayerAction(layersId));
},
enableDDVZoomAlert: (title) => {
dispatch(enableDDVZoomAlert(title));
},
enableDDVLocationAlert: (title) => {
dispatch(enableDDVLocationAlert(title));
},
disableDDVLocationAlert: (title) => {
dispatch(disableDDVLocationAlert(title));
},
disableDDVZoomAlert: (title) => {
dispatch(disableDDVZoomAlert(title));
},
});

export default connect(
Expand Down Expand Up @@ -739,4 +810,9 @@ LayerRow.propTypes = {
isAnimating: PropTypes.bool,
isChartingActive: PropTypes.bool,
activeChartingLayer: PropTypes.string,
enableDDVZoomAlert: PropTypes.func,
enableDDVLocationAlert: PropTypes.func,
isDDVLocationAlertPresent: PropTypes.bool,
isDDVZoomAlertPresent: PropTypes.bool,
openZoomAlertModal: PropTypes.func,
};
34 changes: 34 additions & 0 deletions web/js/modules/alerts/actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {
ACTIVATE_DDV_ZOOM_ALERT,
ACTIVATE_DDV_LOCATION_ALERT,
DEACTIVATE_DDV_LOCATION_ALERT,
DEACTIVATE_DDV_ZOOM_ALERT,
} from './constants';

export function enableDDVZoomAlert(title) {
return {
type: ACTIVATE_DDV_ZOOM_ALERT,
title,
};
}

export function enableDDVLocationAlert(title) {
return {
type: ACTIVATE_DDV_LOCATION_ALERT,
title,
};
}

export function disableDDVZoomAlert(title) {
return {
type: DEACTIVATE_DDV_ZOOM_ALERT,
title,
};
}

export function disableDDVLocationAlert(title) {
return {
type: DEACTIVATE_DDV_LOCATION_ALERT,
title,
};
}
4 changes: 4 additions & 0 deletions web/js/modules/alerts/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ export const DISABLE_VECTOR_ZOOM_ALERT = 'ALERTS/DISABLE_VECTOR_ZOOM_ALERT';
export const ACTIVATE_VECTOR_ZOOM_ALERT = 'ALERTS/ACTIVATE_VECTOR_ZOOM_ALERT';
export const DISABLE_VECTOR_EXCEEDED_ALERT = 'ALERTS/DISABLE_VECTOR_EXCEEDED_ALERT';
export const ACTIVATE_VECTOR_EXCEEDED_ALERT = 'ALERTS/ACTIVATE_VECTOR_EXCEEDED_ALERT';
export const ACTIVATE_DDV_ZOOM_ALERT = 'ALERTS/ACTIVATE_DDV_ZOOM_ALERT';
export const ACTIVATE_DDV_LOCATION_ALERT = 'ALERTS/ACTIVATE_DDV_LOCATION_ALERT';
export const DEACTIVATE_DDV_ZOOM_ALERT = 'ALERTS/DEACTIVATE_DDV_ZOOM_ALERT';
export const DEACTIVATE_DDV_LOCATION_ALERT = 'ALERTS/DEACTIVATE_DDV_LOCATION_ALERT';

export const MODAL_PROPERTIES = {
eventModalProps: {
Expand Down
Loading

0 comments on commit 778e88d

Please sign in to comment.