Skip to content
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"linkcheck": "node ./tasks/link-check",
"lint": "run-s lint:js lint:scss",
"lint:scss": "npx stylelint ./web/scss/**/*.scss",
"lint:js": "npx eslint . --quiet",
"lint:js": "npx eslint .",
"preinstall": "node tasks/util/checkNodeVersion.js",
"postinstall": "patch-package && husky",
"start": "node ./tasks/util/start.js",
Expand Down
2 changes: 1 addition & 1 deletion web/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
// Base rule overrides
"no-nested-ternary": "off", // 164 errors across 40 files
"no-shadow": "warn", // 110 errors across 40 files
"max-len": "off", // 315 errors across 109 files
"max-len": "error", // 315 errors across 109 files
"consistent-return": "off", // 95 errors across 58 files
"no-underscore-dangle": "off", // 40 errors across 7 files
"no-param-reassign": [ // 198 errors across 46 files
Expand Down
6 changes: 4 additions & 2 deletions web/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// eslint-disable-next-line import/no-named-as-default
import MapInteractions from './containers/map-interactions/map-interactions';
// Toolbar
import Toolbar from './containers/toolbar';

Check warning on line 13 in web/js/app.js

View workflow job for this annotation

GitHub Actions / macOS-latest, Node 22

Dependency cycle via ./share:17=>../main:26
import Sidebar from './containers/sidebar/sidebar';
// Modal
import Modal from './containers/modal';
Expand Down Expand Up @@ -71,7 +71,8 @@
kioskModeEnabled, notifications, numberOutagesUnseen, e2eModeEnabled, hideNotificationsPopup,
} = this.props;
if (numberOutagesUnseen !== prevProps.numberOutagesUnseen) {
if (numberOutagesUnseen > 0 && !kioskModeEnabled && !e2eModeEnabled && !hideNotificationsPopup) {
if (numberOutagesUnseen > 0 && !kioskModeEnabled
&& !e2eModeEnabled && !hideNotificationsPopup) {
this.openNotification(notifications, numberOutagesUnseen);
}
}
Expand All @@ -85,7 +86,7 @@


// https://css-tricks.com/the-trick-to-viewport-units-on-mobile/
setVhCSSProperty = () => {

Check warning on line 89 in web/js/app.js

View workflow job for this annotation

GitHub Actions / macOS-latest, Node 22

Expected 'this' to be used by class method 'setVhCSSProperty'
const vh = window.innerHeight * 0.01;
document.documentElement.style.setProperty('--vh', `${vh}px`);
};
Expand All @@ -97,7 +98,7 @@
keyPressAction(event.keyCode, event.shiftKey, ctrlOrCmdKey, isInput);
}

getScreenInfo = () => {

Check warning on line 101 in web/js/app.js

View workflow job for this annotation

GitHub Actions / macOS-latest, Node 22

Unused method or property "getScreenInfo" of class "App"
const { setScreenInfoAction } = this.props;
setScreenInfoAction();
};
Expand All @@ -113,7 +114,7 @@
const { config } = self.props;
config.parameters = state;

const main = function() {

Check warning on line 117 in web/js/app.js

View workflow job for this annotation

GitHub Actions / macOS-latest, Node 22

Unexpected unnamed function
// Load any additional scripts as needed
if (config.scripts) {
util.loadScripts(config.scripts);
Expand All @@ -121,7 +122,7 @@

if (Brand.release()) {
// Console build version notifications
console.info(

Check warning on line 125 in web/js/app.js

View workflow job for this annotation

GitHub Actions / macOS-latest, Node 22

Unexpected console statement
`${Brand.NAME
} - Version ${
Brand.VERSION
Expand All @@ -129,7 +130,7 @@
Brand.BUILD_TIMESTAMP}`,
);
} else {
console.warn('Development version');

Check warning on line 133 in web/js/app.js

View workflow job for this annotation

GitHub Actions / macOS-latest, Node 22

Unexpected console statement
}
window.addEventListener('resize', () => {
self.getScreenInfo();
Expand Down Expand Up @@ -165,7 +166,8 @@
<MapInteractions />
<AlertDropdown isTourActive={isTourActive} />
<div>
{isTourActive && (numberOutagesUnseen === 0 || hideNotificationsPopup) && (!isMobile || isEmbedModeActive) ? <Tour /> : null}
{isTourActive && (numberOutagesUnseen === 0
|| hideNotificationsPopup) && (!isMobile || isEmbedModeActive) ? <Tour /> : null}
</div>
<Sidebar />
<div id="layer-modal" className="layer-modal" />
Expand Down
6 changes: 4 additions & 2 deletions web/js/components/animation-widget/gif-button.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ function GifButton(props) {
if (gifDisabled) {
return;
}
const nonDownloadableLayers = hasNonDownloadableLayer ? getNonDownloadableLayers(visibleLayersForProj) : null;
const nonDownloadableLayers = hasNonDownloadableLayer
? getNonDownloadableLayers(visibleLayersForProj) : null;
const paletteStore = lodashCloneDeep(activePalettes);
await getPromise(hasCustomPalettes, 'palette', clearCustoms, 'Notice');
await getPromise(isRotated, 'rotate', clearRotate, 'Reset rotation');
Expand All @@ -85,7 +86,8 @@ function GifButton(props) {
});

onCloseGif = () => {
refreshStateAfterGif(hasCustomPalettes ? paletteStore : undefined, rotation, nonDownloadableLayers);
refreshStateAfterGif(hasCustomPalettes
? paletteStore : undefined, rotation, nonDownloadableLayers);
toggleGif();
};
toggleGif();
Expand Down
10 changes: 5 additions & 5 deletions web/js/components/animation-widget/play-queue.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ const getInitialBufferSize = (numberOfFrames, speed) => {
*
* The buffering logic is as follows:
* - n = 10 + speed (frames per sec)
* - Make at least n requests (assuming there are >= n frames) to determine the avg fetch time for a frame
* - Make at least n requests (assuming there are >= n frames) to determine
* the avg fetch time for a frame
* - While making initial requests, if any return too quickly (e.g. they were cached), keep making
* requests until at least n "real" requests can be made to determine average fetch time
* requests until at least n "real" requests can be made to determine average fetch time
* - Based on how long it took to load the first n, calculate how many additional frames
* need to be pre-loaded, based on avg fetch time and playback speed, in order for playback to begin
* without having to stop to buffer.
*
* need to be pre-loaded, based on avg fetch time and playback speed,
* in order for playback to begin without having to stop to buffer.
*/
class PlayQueue extends React.Component {
constructor(props) {
Expand Down
8 changes: 6 additions & 2 deletions web/js/components/charting/chart-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,8 @@ function ChartComponent (props) {
const yAxisValuesArr = getYAxisValues(data);

/**
* Extracts each key from the provided object & returns the list, removing 'name' from the collection
* Extracts each key from the provided object &
* returns the list,removing 'name' from the collection
* @param {Object} chartData
*/
function getLineNames(obj) {
Expand Down Expand Up @@ -475,7 +476,10 @@ function ChartComponent (props) {
</div>
<div className="charting-disclaimer">
<strong className="charting-disclaimer-pre">Note: </strong>
<span>Numerical analyses performed on imagery should only be used for initial basic exploratory purposes.</span>
<span>
Numerical analyses performed on imagery should only
be used for initial basic exploratory purposes.
</span>
{isTruncated
&& (
<div className="charting-disclaimer-upper">
Expand Down
5 changes: 4 additions & 1 deletion web/js/components/charting/charting-date-selector.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import {

function ChartingDateSelector (props) {
const {
onUpdateStartDate, onUpdateEndDate, timeSpanStartDate, timeSpanEndDate, timeSpanSelection, date, layerStartDate, layerEndDate,
onUpdateStartDate, onUpdateEndDate,
timeSpanStartDate, timeSpanEndDate,
timeSpanSelection, date,
layerStartDate, layerEndDate,
} = props;
const { selected, selectedB } = date;
const startdate = timeSpanStartDate == null ? selected : timeSpanStartDate;
Expand Down
2 changes: 1 addition & 1 deletion web/js/components/charting/charting-info.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ function ChartingInfo(props) {
<div className="charting-info-text">
<p className="charting-info">
The charting feature is available for beta testing and evaluation.&nbsp;
<span class="charting-feedback" onClick={() => sendFeedback(feedbackIsInitiated, isMobile)}>Please send comments and feedback to us.</span>
<span className="charting-feedback" onClick={() => sendFeedback(feedbackIsInitiated, isMobile)}>Please send comments and feedback to us.</span>
</p>
<p className="charting-info">The Charting Tool provides the option to create a line chart for a date range showing change over time, and statistics for a single date (median, mean, minimum, maximum, and standard deviation) for an area of interest.</p>

Expand Down
3 changes: 2 additions & 1 deletion web/js/components/charting/simple-statistics.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ function SimpleStatistics(props) {
<strong>Note:</strong>
<br />
{' '}
Numerical analyses performed on imagery should only be used for initial basic exploratory purposes.
Numerical analyses performed on imagery should
only be used for initial basic exploratory purposes.
</div>
</>
);
Expand Down
3 changes: 2 additions & 1 deletion web/js/components/context-menu/context-menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ function RightClickMenu(props) {
const [toolTipToggleTime, setToolTipToggleTime] = useState(0);
const [formattedCoordinates, setFormattedCoordinates] = useState();
const {
map, proj, unitOfMeasure, onToggleUnits, isCoordinateSearchActive, allMeasurements, measurementIsActive, isMobile,
map, proj, unitOfMeasure, onToggleUnits, isCoordinateSearchActive,
allMeasurements, measurementIsActive, isMobile,
} = props;
const { crs } = proj.selected;
const measurementsInProj = !!(Object.keys(allMeasurements[crs]) || []).length;
Expand Down
3 changes: 2 additions & 1 deletion web/js/components/dateline/datelines.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import { CRS } from '../../modules/map/constants';

function DateLines(props) {
const {
map, proj, date, isCompareActive, mapIsRendered, alwaysShow, hideText, isMobilePhone, isMobileTablet,
map, proj, date, isCompareActive, mapIsRendered,
alwaysShow, hideText, isMobilePhone, isMobileTablet,
} = props;

const [height, setHeight] = useState(0);
Expand Down
6 changes: 5 additions & 1 deletion web/js/components/feature-alert/granuleAlertModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ function GranuleAlertModalBody() {
<Row className="p-3">
<Col>
<p>
Certain imagery visualization layers have narrower and smaller footprints so there isn&apos;t imagery to view at every location across the globe. Some imagery layers also have lower temporal revisit periods meaning there won&apos;t be daily imagery for a specific location on earth. Click on “View Options” in the layer list to access a date picker to locate imagery for your desired location.
Certain imagery visualization layers have narrower and
smaller footprints so there isn&apos;t imagery to view at every location across the
globe. Some imagery layers also have lower temporal revisit periods meaning there
won&apos;t be daily imagery for a specific location on earth. Click on “View Options”
in the layer list to access a date picker to locate imagery for your desired location.
</p>
</Col>
</Row>
Expand Down
17 changes: 14 additions & 3 deletions web/js/components/feature-alert/vector-alert-modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ function VectorAlertModalBody() {
<Col>

<p>
Vector layers identify locations on earth using points, line segments or polygons while raster layers represent locations on earth through a grid of cells or pixels that have associated color values. The vector layers have attribute information that can be examined when a vector feature is clicked. For example, when a point is clicked on in the Dams layer, a table of attributes will appear including the dam name, river, main use, representative capacity, etc.
Vector layers identify locations on earth using points, line segments or polygons while
raster layers represent locations on earth through a grid of cells or pixels that have
associated color values. The vector layers have attribute information that can be
examined when a vector feature is clicked. For example, when a point is clicked on in
the Dams layer, a table of attributes will appear including the dam name, river, main
use, representative capacity, etc.
</p>
</Col>
</Row>
Expand All @@ -32,7 +37,9 @@ function VectorAlertModalBody() {
<Col>

<p>
To speed up map interactions, vector layers that have a vast number of features are rendered as raster images in outer zoom levels. Zoom in to be able to query the vector layer.
To speed up map interactions, vector layers that have a vast number of features are
rendered as raster images in outer zoom levels. Zoom in to be able to query the vector
layer.
</p>
</Col>
</Row>
Expand All @@ -46,7 +53,11 @@ function VectorAlertModalBody() {
<Row className="p-3">
<Col>
<p>
If you see the blue pointer icon next to the layer in the sidebar Layer List, you should be able to click on that layer’s features in order to access attribute information associated with that vector feature. If you see the blue pointer with a red X over it, you are zoomed out too far and the layer is being rendered as a raster, zoom in to be able to examine the attribute information of the vector layer.
If you see the blue pointer icon next to the layer in the sidebar Layer List, you
should be able to click on that layer’s features in order to access attribute
information associated with that vector feature. If you see the blue pointer with a
red X over it, you are zoomed out too far and the layer is being rendered as a raster,
zoom in to be able to examine the attribute information of the vector layer.
</p>
</Col>
<Col>
Expand Down
3 changes: 2 additions & 1 deletion web/js/components/feature-alert/zoomAlertModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ function ZoomAlertModalBody() {
<Row className="p-3">
<Col>
<p>
Imagery for certain layers is dynamically generated and only available when zoomed in. Please zoom in to view this product.
Imagery for certain layers is dynamically generated and only available when zoomed in.
Please zoom in to view this product.
</p>
</Col>
</Row>
Expand Down
6 changes: 4 additions & 2 deletions web/js/components/image-download/global-select.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ function GlobalSelectCheckbox(props) {

const boundingBoxArray = [...geoLatLong[0], ...geoLatLong[1]];
const globalSelected = isEqual(boundingBoxArray, GLOBAL_LAT_LONG_EXTENT);
const [prevExtent, setPrevExtent] = useState(globalSelected ? [-40, -40, 40, 40] : boundingBoxArray);
const [prevExtent, setPrevExtent] = useState(globalSelected ? [-40, -40, 40, 40]
: boundingBoxArray);
const onCheck = () => {
const useExtent = globalSelected ? prevExtent : GLOBAL_LAT_LONG_EXTENT;
setPrevExtent(boundingBoxArray);
Expand All @@ -23,7 +24,8 @@ function GlobalSelectCheckbox(props) {
}, 50);
};

const globalIsNotSelected = GLOBAL_LAT_LONG_EXTENT.some((latLongValue, index) => latLongValue !== boundingBoxArray[index]);
const globalIsNotSelected = GLOBAL_LAT_LONG_EXTENT.some((latLongValue, index) => latLongValue
!== boundingBoxArray[index]);
if (proj !== 'geographic') return null;

return (
Expand Down
30 changes: 24 additions & 6 deletions web/js/components/image-download/image-download-panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,20 @@ function ImageDownloadPanel(props) {
const [currResolution, setResolution] = useState(resolution);
const [debugUrl, setDebugUrl] = useState('');
const [showGranuleWarning, setShowGranuleWarning] = useState(false);
const activePalettes = useSelector((state) => getActivePalettes(state, state.compare.activeString));
const activePalettes = useSelector((state) => getActivePalettes(
state,
state.compare.activeString,
));

useEffect(() => {
const layerList = getLayers();
const granuleDatesMap = new Map(map.getLayers().getArray().map((layer) => [layer.wv.id, layer.wv.granuleDates]));
const layerDefs = layerList.map((def) => ({ ...def, granuleDates: granuleDatesMap.get(def.id) }));
const granuleDatesMap = new Map(map.getLayers().getArray().map((layer) => [
layer.wv.id,
layer.wv.granuleDates,
]));
const layerDefs = layerList.map((def) => ({
...def, granuleDates: granuleDatesMap.get(def.id),
}));
const isTruncated = getTruncatedGranuleDates(layerDefs, date).truncated;

setShowGranuleWarning(isTruncated);
Expand All @@ -74,8 +82,12 @@ function ImageDownloadPanel(props) {
const time = new Date(date.getTime());

const layerList = getLayers();
const granuleDatesMap = new Map(map.getLayers().getArray().map((layer) => [layer.wv.id, layer.wv.granuleDates]));
const layerDefs = layerList.map((def) => ({ ...def, granuleDates: granuleDatesMap.get(def.id) }));
const granuleDatesMap = new Map(map.getLayers().getArray().map((layer) => [
layer.wv.id, layer.wv.granuleDates,
]));
const layerDefs = layerList.map((def) => ({
...def, granuleDates: granuleDatesMap.get(def.id),
}));
const dlURL = getDownloadUrl(
url,
projection,
Expand Down Expand Up @@ -212,7 +224,13 @@ function ImageDownloadPanel(props) {
map={map}
/>
{showGranuleWarning && (
<p>Warning: A snapshot will capture a max. of {GRANULE_LIMIT} granules, additional granules are omitted.</p> // eslint-disable-line react/jsx-one-expression-per-line
<p>
Warning: A snapshot will capture a max. of
{GRANULE_LIMIT}
{' '}
granules, additional
granules are omitted.
</p> // eslint-disable-line react/jsx-one-expression-per-line
)}
<ResTable
width={width}
Expand Down
4 changes: 3 additions & 1 deletion web/js/components/image-download/lat-long-inputs.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ function LatLongSelect(props) {
const boundingBoxArray = [geoLatLong[0][0], geoLatLong[0][1], geoLatLong[1][0], geoLatLong[1][1]];
const [showCoordinates, setShowCoordinates] = useState(false);
const coordText = showCoordinates ? 'Hide Coordinates' : 'Edit Coordinates';
const [minLon, minLat, maxLon, maxLat] = boundingBoxArray.map((coord) => coord.toFixed(4).toString());
const [minLon, minLat, maxLon, maxLat] = boundingBoxArray.map(
(coord) => coord.toFixed(4).toString(),
);

return (
<div className="wv-image-input-case">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ function AnimationTileCheck(props) {
const config = useSelector((state) => state.config, shallowEqual);
const proj = useSelector((state) => state.proj.selected, shallowEqual);
const zoom = useSelector((state) => Math.floor(state.map.ui.selected.getView().getZoom()));
const activeLayers = useSelector((state) => getActiveLayers(state, state.compare.activeString), shallowEqual);
const activeLayers = useSelector(
(state) => getActiveLayers(state, state.compare.activeString),
shallowEqual,
);

const [frameDates, setFrameDates] = useState([]);

Expand Down Expand Up @@ -48,7 +51,13 @@ function AnimationTileCheck(props) {
}, [isPlaying]);

return (
<DateRangeTileCheck frameDates={frameDates} activeLayers={activeLayers} config={config} proj={proj} zoom={zoom} />
<DateRangeTileCheck
frameDates={frameDates}
activeLayers={activeLayers}
config={config}
proj={proj}
zoom={zoom}
/>
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {
LEFT_WING_EXTENT, RIGHT_WING_EXTENT, LEFT_WING_ORIGIN, RIGHT_WING_ORIGIN,
} from '../../../modules/map/constants';

// Layers to be checked for tile availability need to have manually determined content-length thresholds.
// Layers to be checked for tile availability need
// to have manually determined content-length thresholds.
// Any active layers that are not listed in this object will NOT be checked for tile availability.
// This represents a TOTAL content-length for all tiles for a single date for a single layer
// To find a good value for the total content-length:
Expand All @@ -37,7 +38,11 @@ function DateRangeTileCheck(props) {
} = props;

const dispatch = useDispatch();
const toggleCheckedAnimationAvailability = (available) => { dispatch(toggleCheckedAnimationAvailabilityAction(available)); };
const toggleCheckedAnimationAvailability = (available) => {
dispatch(
toggleCheckedAnimationAvailabilityAction(available),
);
};

const calcExtentsFromLimits = (matrixSet, matrixSetLimits, day) => {
let extent;
Expand Down Expand Up @@ -103,7 +108,8 @@ function DateRangeTileCheck(props) {

const { tileMatrices, resolutions, tileSize } = configMatrixSet;
const { origin, extent } = calcExtentsFromLimits(configMatrixSet, matrixSetLimits, null);
const sizes = !tileMatrices ? [] : tileMatrices.map(({ matrixWidth, matrixHeight }) => [matrixWidth, matrixHeight]);
const sizes = !tileMatrices ? [] : tileMatrices.map(({ matrixWidth, matrixHeight }) => [
matrixWidth, matrixHeight]);

const tileGridOptions = {
origin,
Expand Down Expand Up @@ -211,8 +217,10 @@ function DateRangeTileCheck(props) {

layer.dates.forEach((date) => {
if (date.contentLengthSum < threshold) {
const dateStr = date.date.toISOString(); // Convert date to string for use as an object key
uniqueDatesBelowThreshold.add(dateStr); // Add the date to the set. If it's already there, it won't be added again.
// Convert date to string for use as an object key
const dateStr = date.date.toISOString();
// Add the date to the set. If it's already there, it won't be added again.
uniqueDatesBelowThreshold.add(dateStr);
}
});
});
Expand All @@ -222,9 +230,11 @@ function DateRangeTileCheck(props) {
// Calculate how many frames are missing tiles as a percentage
const percentMissing = (framesWithMissingTiles / frameDates.length) * 100;

// If there are less than 40% of frames with missing tiles we dispatch action to allow animation to play
// If there are less than 40% of frames with missing
// tiles we dispatch action to allow animation to play
// Else we do not do anything which means we display static imagery of the first frame
// The imagery at this date should already be satisfactory because the errorTile process has already been completed
// The imagery at this date should already be
// satisfactory because the errorTile process has already been completed
// The percentMissing conditional value is completely arbitrary and can be changed
if (percentMissing < 40) {
console.log('Good Check:', percentMissing, '% ', 'of dates with missing frames');
Expand Down
Loading
Loading