From 78da7657a2e8ba28a0ec4ed25d335721f65e350d Mon Sep 17 00:00:00 2001 From: Jeremy Sampson Date: Thu, 26 Oct 2023 11:04:18 -0600 Subject: [PATCH] v2.5.2 (#69) * fix AOP prov step handling, performance, selection limit * handle render, initialization of filters * fix styling of prov data message in AOP workflow * prepare v2.5.2 --- .../DownloadDataContext.d.ts | 8 + .../DownloadDataContext.js | 177 +- .../DownloadStepForm/DownloadStepForm.d.ts | 4 +- .../DownloadStepForm/DownloadStepForm.js | 1539 ++++++++-------- lib/remoteAssets/drupal-header.html.d.ts | 2 +- lib/remoteAssets/drupal-header.html.js | 2 +- package-lock.json | 4 +- package.json | 2 +- .../DownloadDataContext.jsx | 175 +- .../DownloadStepForm/DownloadStepForm.jsx | 1607 +++++++++-------- .../__snapshots__/DownloadStepForm.jsx.snap | 4 +- .../remoteAssets/drupal-header.html.js | 2 +- src/sampleData/DP1.30010.001.json | 1345 ++++++++++---- 13 files changed, 2876 insertions(+), 1995 deletions(-) diff --git a/lib/components/DownloadDataContext/DownloadDataContext.d.ts b/lib/components/DownloadDataContext/DownloadDataContext.d.ts index 8384bf69..b66e6804 100644 --- a/lib/components/DownloadDataContext/DownloadDataContext.d.ts +++ b/lib/components/DownloadDataContext/DownloadDataContext.d.ts @@ -45,7 +45,9 @@ export function getTestableItems(): { s3FileFetches: {}; s3FileFetchProgress: number; s3Files: { + maxNumFilesSelected: number; value: never[]; + valueMap: {}; cachedValues: never[]; validValues: never[]; isValid: boolean; @@ -192,7 +194,9 @@ declare function useDownloadDataState(): { s3FileFetches: {}; s3FileFetchProgress: number; s3Files: { + maxNumFilesSelected: number; value: never[]; + valueMap: {}; cachedValues: never[]; validValues: never[]; isValid: boolean; @@ -272,7 +276,9 @@ declare function useDownloadDataState(): { s3FileFetches: {}; s3FileFetchProgress: number; s3Files: { + maxNumFilesSelected: number; value: never[]; + valueMap: {}; cachedValues: never[]; validValues: never[]; isValid: boolean; @@ -356,8 +362,10 @@ declare namespace DEFAULT_STATE { export const s3FileFetches: {}; export const s3FileFetchProgress: number; export namespace s3Files { + export const maxNumFilesSelected: number; const value_1: never[]; export { value_1 as value }; + export const valueMap: {}; export const cachedValues: never[]; export const validValues: never[]; export const isValid: boolean; diff --git a/lib/components/DownloadDataContext/DownloadDataContext.js b/lib/components/DownloadDataContext/DownloadDataContext.js index 943de145..1693c1db 100644 --- a/lib/components/DownloadDataContext/DownloadDataContext.js +++ b/lib/components/DownloadDataContext/DownloadDataContext.js @@ -124,7 +124,9 @@ var DEFAULT_STATE = { s3FileFetchProgress: 0, // Number to track progress of batch fetches for s3 files s3Files: { + maxNumFilesSelected: 60000, value: [], + valueMap: {}, cachedValues: [], // Where all fetched file records are cached validValues: [], @@ -284,7 +286,7 @@ var newStateIsValid = function newStateIsValid(key, value) { if (!VALIDATABLE_STATE_KEYS.includes(key)) { return false; } - var idList = []; + var idList = {}; switch (key) { case 'sites': return newStateIsAllowable(key, value) && Array.isArray(validValues) && value.length > 0 && value.every(function (site) { @@ -298,11 +300,11 @@ var newStateIsValid = function newStateIsValid(key, value) { })) { return false; } - idList = validValues.map(function (fileObj) { - return fileObj.url; + validValues.forEach(function (fileObj) { + idList[fileObj.url] = true; }); return newStateIsAllowable(key, value) && value.length > 0 && value.every(function (id) { - return idList.includes(id); + return idList[id] || false; }); default: return newStateIsAllowable(key, value) && (!Array.isArray(validValues) || validValues.includes(value)); @@ -523,15 +525,50 @@ var getInitialStateFromProps = function getInitialStateFromProps(props) { // Done! return initialState; }; -var getS3FilesFilteredFileCount = function getS3FilesFilteredFileCount(state) { - return state.s3Files.validValues.filter(function (row) { - return Object.keys(state.s3Files.filters).every(function (col) { +var getS3FilesFilterFunction = function getS3FilesFilterFunction(state) { + return function (row) { + var allowValue = true; + var hasProvisionalDataStep = state.requiredSteps.some(function (step) { + return step.key === 'provisionalData'; + }); + var excludeProvisionalData = hasProvisionalDataStep && state.provisionalData.value === 'exclude'; + if (excludeProvisionalData) { + allowValue = (0, _typeUtil.isStringNonEmpty)(row.release) && !_ReleaseService.default.isNonRelease(row.release); + } + var matchesFilters = Object.keys(state.s3Files.filters).every(function (col) { if (col === 'name') { return !state.s3Files.filters.name.length || row.name.includes(state.s3Files.filters.name); } return !state.s3Files.filters[col].length || state.s3Files.filters[col].includes(row[col]); }); - }).length; + return matchesFilters && allowValue; + }; +}; +var getS3FilesFilteredFileCount = function getS3FilesFilteredFileCount(state) { + var filtered = state.s3Files.validValues.filter(getS3FilesFilterFunction(state)); + return filtered.length; +}; +var calcS3FilesSummaryState = function calcS3FilesSummaryState(previousState, action) { + var newState = _extends({}, previousState); + var s3FilesIdx = newState.requiredSteps.findIndex(function (step) { + return step.key === 's3Files'; + }); + // If we didn't already update the total size then recalculate it + if (action.type !== 'setIndividualS3FileSelected') { + newState.s3Files.totalSize = newState.s3Files.value.map(function (id) { + return newState.s3Files.bytesByUrl[id]; + }).reduce(function (a, b) { + return a + b; + }, 0); + } + // Step is only complete when there's a selection that's not too big + newState.s3Files.estimatedPostSize = estimatePostSize(newState.s3Files, newState.sites); + newState.s3Files.isValid = newState.s3Files.value.length > 0 && newState.s3Files.estimatedPostSize < _manifestUtil.MAX_POST_BODY_SIZE; + newState.requiredSteps[s3FilesIdx].isComplete = newState.s3Files.isValid; + newState.allStepsComplete = newState.requiredSteps.every(function (step) { + return step.isComplete || step.isComplete === null; + }); + return newState; }; // Generate a new full state object with a new value and isValid boolean for the @@ -558,44 +595,61 @@ var getAndValidateNewS3FilesState = function getAndValidateNewS3FilesState(previ return newState; } newState.s3Files.value = action.value; + newState.s3Files.valueMap = {}; + if ((0, _typeUtil.existsNonEmpty)(newState.s3Files.value)) { + newState.s3Files.value.forEach(function (value) { + newState.s3Files.valueMap[value] = true; + }); + } break; case 'setValidatableValue': if (!newStateIsAllowable(action.key, action.value)) { return newState; } newState.s3Files.value = action.value; + newState.s3Files.valueMap = {}; + if ((0, _typeUtil.existsNonEmpty)(newState.s3Files.value)) { + newState.s3Files.value.forEach(function (value) { + newState.s3Files.valueMap[value] = true; + }); + } newState.s3Files.validValues.forEach(function (file, idx) { - newState.s3Files.validValues[idx].tableData.checked = newState.s3Files.value.includes(file.url); + newState.s3Files.validValues[idx].tableData.checked = newState.s3Files.valueMap[file.url] || false; }); break; case 'setS3FilesValueSelectAll': newState.s3Files.value = newState.s3Files.validValues.map(function (file) { return file.url; }); + newState.s3Files.valueMap = {}; + if ((0, _typeUtil.existsNonEmpty)(newState.s3Files.value)) { + newState.s3Files.value.forEach(function (value) { + newState.s3Files.valueMap[value] = true; + }); + } newState.s3Files.validValues.forEach(function (file, idx) { newState.s3Files.validValues[idx].tableData.checked = true; }); break; case 'setS3FilesValueSelectNone': newState.s3Files.value = []; + newState.s3Files.valueMap = {}; newState.s3Files.validValues.forEach(function (file, idx) { newState.s3Files.validValues[idx].tableData.checked = false; }); break; case 'setS3FilesValueSelectFiltered': - newState.s3Files.value = newState.s3Files.validValues.filter(function (row) { - return Object.keys(newState.s3Files.filters).every(function (col) { - if (col === 'name') { - return !newState.s3Files.filters.name.length || row.name.includes(newState.s3Files.filters.name); // eslint-disable-line max-len - } - - return !newState.s3Files.filters[col].length || newState.s3Files.filters[col].includes(row[col]); // eslint-disable-line max-len - }); - }).map(function (file) { + newState.s3Files.value = newState.s3Files.validValues.filter(getS3FilesFilterFunction(newState)).map(function (file) { return file.url; }); + newState.s3Files.valueMap = {}; + if ((0, _typeUtil.existsNonEmpty)(newState.s3Files.value)) { + newState.s3Files.value.forEach(function (value) { + newState.s3Files.valueMap[value] = true; + }); + } newState.s3Files.validValues.forEach(function (file, idx) { - newState.s3Files.validValues[idx].tableData.checked = newState.s3Files.value.includes(file.url); // eslint-disable-line max-len + newState.s3Files.validValues[idx].tableData.checked = newState.s3Files.valueMap[file.url] || false; // eslint-disable-line max-len }); break; @@ -611,36 +665,21 @@ var getAndValidateNewS3FilesState = function getAndValidateNewS3FilesState(previ // just add/subtract the size of the file specified if (action.selected) { newState.s3Files.value.push(action.url); + newState.s3Files.valueMap[action.url] = true; newState.s3Files.totalSize += newState.s3Files.bytesByUrl[action.url]; } else { if (newState.s3Files.value.indexOf(action.url) === -1) { return newState; } newState.s3Files.value.splice(newState.s3Files.value.indexOf(action.url), 1); + delete newState.s3Files.valueMap[action.url]; newState.s3Files.totalSize -= newState.s3Files.bytesByUrl[action.url]; } break; default: return newState; } - - // If we didn't already update the total size then recalculate it - if (action.type !== 'setIndividualS3FileSelected') { - newState.s3Files.totalSize = newState.s3Files.value.map(function (id) { - return newState.s3Files.bytesByUrl[id]; - }).reduce(function (a, b) { - return a + b; - }, 0); - } - - // Step is only complete when there's a selection that's not too big - newState.s3Files.estimatedPostSize = estimatePostSize(newState.s3Files, newState.sites); - newState.s3Files.isValid = newState.s3Files.value.length > 0 && newState.s3Files.estimatedPostSize < _manifestUtil.MAX_POST_BODY_SIZE; - newState.requiredSteps[s3FilesIdx].isComplete = newState.s3Files.isValid; - newState.allStepsComplete = newState.requiredSteps.every(function (step) { - return step.isComplete || step.isComplete === null; - }); - return newState; + return calcS3FilesSummaryState(newState, action); }; // Generate new s3Files.validValues and s3Files filter values in state. @@ -689,31 +728,29 @@ var regenerateS3FilesFiltersAndValidValues = function regenerateS3FilesFiltersAn }).map(function (file) { return _extends({}, file, { tableData: { - checked: updated.s3Files.value.includes(file.url) + checked: updated.s3Files.valueMap[file.url] || false } }); }); // If cachedValues and validValues differ in size then rebuild valueLookups for // filters, adjust filter selections to suit, and regenerate filtered file count. var filterKeys = Object.keys(updated.s3Files.valueLookups || {}); - if (updated.s3Files.validValues.length < updated.s3Files.cachedValues.length) { - filterKeys.forEach(function (key) { - updated.s3Files.valueLookups[key] = {}; - }); - updated.s3Files.validValues.forEach(function (file) { - filterKeys.forEach(function (lookup) { - if (typeof file[lookup] === 'undefined') { - return; - } - updated.s3Files.valueLookups[lookup][file[lookup]] = file[lookup] || '(none)'; - }); + filterKeys.forEach(function (key) { + updated.s3Files.valueLookups[key] = {}; + }); + updated.s3Files.validValues.forEach(function (file) { + filterKeys.forEach(function (lookup) { + if (typeof file[lookup] === 'undefined') { + return; + } + updated.s3Files.valueLookups[lookup][file[lookup]] = file[lookup] || '(none)'; }); - filterKeys.forEach(function (key) { - updated.s3Files.filters[key] = updated.s3Files.filters[key].filter(function (filterVal) { - return Object.keys(updated.s3Files.valueLookups[key]).includes(filterVal); - }); + }); + filterKeys.forEach(function (key) { + updated.s3Files.filters[key] = updated.s3Files.filters[key].filter(function (filterVal) { + return Object.keys(updated.s3Files.valueLookups[key]).includes(filterVal); }); - } + }); updated.s3Files.filteredFileCount = getS3FilesFilteredFileCount(updated); // Create an action to send to the reducer helper to set an updated value and revalidate. var action = { @@ -753,6 +790,38 @@ var getAndValidateNewState = function getAndValidateNewState(previousState, acti value: action.value, isValid: valueIsValid }); + var hasProvDataStep = newState.requiredSteps.some(function (step) { + return step.key === 'provisionalData'; + }); + var hasS3FilesStep = newState.requiredSteps.some(function (step) { + return step.key === 's3Files'; + }); + if (hasProvDataStep && hasS3FilesStep && action.key === 'provisionalData') { + if (action.value === 'exclude') { + // Go through validValues, uncheck any provisional when set to exclude + if ((0, _typeUtil.existsNonEmpty)(newState.s3Files.validValues)) { + newState.s3Files.value = []; + newState.s3Files.valueMap = {}; + newState.s3Files.validValues = newState.s3Files.validValues.map(function (value) { + var isProv = _ReleaseService.default.isProv(value.release); + if (isProv) { + return _extends({}, value, { + tableData: _extends({}, value.tableData, { + checked: false + }) + }); + } + if (value.tableData.checked) { + newState.s3Files.value.push(value.url); + newState.s3Files.valueMap[value.url] = true; + } + return value; + }); + newState = calcS3FilesSummaryState(newState, action); + } + } + newState.s3Files.filteredFileCount = getS3FilesFilteredFileCount(newState); + } newState.requiredSteps = previousState.requiredSteps.map(function (step) { var requiredStateKeys = ALL_STEPS[step.key] ? ALL_STEPS[step.key].requiredStateKeys : []; return step.isComplete === null ? _extends({}, step) : _extends({}, step, { diff --git a/lib/components/DownloadStepForm/DownloadStepForm.d.ts b/lib/components/DownloadStepForm/DownloadStepForm.d.ts index 977bc0e4..978ae11c 100644 --- a/lib/components/DownloadStepForm/DownloadStepForm.d.ts +++ b/lib/components/DownloadStepForm/DownloadStepForm.d.ts @@ -1,4 +1,5 @@ -declare function DownloadStepForm(props: any): any; +export default DownloadStepForm; +declare function DownloadStepForm(props: any): JSX.Element | null; declare namespace DownloadStepForm { namespace propTypes { const stepKey: PropTypes.Validator; @@ -15,5 +16,4 @@ declare namespace DownloadStepForm { export { renderDownloadButton_1 as renderDownloadButton }; } } -export default DownloadStepForm; import PropTypes from "prop-types"; diff --git a/lib/components/DownloadStepForm/DownloadStepForm.js b/lib/components/DownloadStepForm/DownloadStepForm.js index 19a30903..79317655 100644 --- a/lib/components/DownloadStepForm/DownloadStepForm.js +++ b/lib/components/DownloadStepForm/DownloadStepForm.js @@ -4,7 +4,7 @@ function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" = Object.defineProperty(exports, "__esModule", { value: true }); -exports.default = DownloadStepForm; +exports.default = void 0; var _react = _interopRequireWildcard(require("react")); var _propTypes = _interopRequireDefault(require("prop-types")); var _lodash = require("lodash"); @@ -149,7 +149,56 @@ var dataUsageAndCitationPoliciesLink = /*#__PURE__*/_react.default.createElement href: _RouteService.default.getDataPoliciesPath(), "data-gtm": "download-data-dialog.policies-link" }, "Data Usage and Citation Policies"); -function DownloadStepForm(props) { +var renderStepSummary = { + sitesAndDateRange: function sitesAndDateRange(classes, state) { + var sites = state.sites.value; + var dateRange = state.dateRange.value; + var sitesPlural = sites.length > 1 ? 's' : ''; + var getYearMonthMoment = function getYearMonthMoment(yearMonth) { + return (0, _moment.default)("".concat(yearMonth, "-01")); + }; + var startDateRange = "".concat(getYearMonthMoment(dateRange[0]).format('MMM YYYY')); + var endDateRange = "".concat(getYearMonthMoment(dateRange[1]).format('MMM YYYY')); + var humanDateRange = "".concat(startDateRange, " - ").concat(endDateRange); + var siteChipLabel = "".concat(sites.length, " site").concat(sitesPlural, " \u2014 ").concat(humanDateRange); + return /*#__PURE__*/_react.default.createElement(_SiteChip.default, { + size: "large", + variant: "default", + label: siteChipLabel + }); + }, + documentation: function documentation(classes, state) { + var documentation = state.documentation.value; + return /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "body2", + className: classes.summaryText + }, "".concat(documentation.charAt(0).toUpperCase()).concat(documentation.substring(1))); + }, + packageType: function packageType(classes, state) { + var packageType = state.packageType.value; + return /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "body2", + className: classes.summaryText + }, "".concat(packageType.charAt(0).toUpperCase()).concat(packageType.substring(1))); + }, + provisionalData: function provisionalData(classes, state) { + var provisionalData = state.provisionalData.value; + return /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "body2", + className: classes.summaryText + }, "".concat(provisionalData.charAt(0).toUpperCase()).concat(provisionalData.substring(1))); + }, + s3Files: function s3Files(classes, state) { + var _state$s3Files = state.s3Files, + files = _state$s3Files.value, + totalSize = _state$s3Files.totalSize; + return /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "body2", + className: classes.summaryText + }, "".concat(files.length, " file").concat(files.length === 1 ? '' : 's', " (").concat((0, _manifestUtil.formatBytes)(totalSize), " uncompressed)")); + } +}; +var DownloadStepForm = function DownloadStepForm(props) { var classes = useStyles(_Theme.default); var stepKey = props.stepKey, changeToStep = props.changeToStep, @@ -184,769 +233,767 @@ function DownloadStepForm(props) { value: newValue }); }; - var renderStepSummary = { - sitesAndDateRange: function sitesAndDateRange() { - var sites = state.sites.value; - var dateRange = state.dateRange.value; - var sitesPlural = sites.length > 1 ? 's' : ''; - var getYearMonthMoment = function getYearMonthMoment(yearMonth) { - return (0, _moment.default)("".concat(yearMonth, "-01")); - }; - var humanDateRange = "".concat(getYearMonthMoment(dateRange[0]).format('MMM YYYY'), " - ").concat(getYearMonthMoment(dateRange[1]).format('MMM YYYY')); - var siteChipLabel = "".concat(sites.length, " site").concat(sitesPlural, " \u2014 ").concat(humanDateRange); - return /*#__PURE__*/_react.default.createElement(_SiteChip.default, { - size: "large", - variant: "default", - label: siteChipLabel - }); - }, - documentation: function documentation() { - var documentation = state.documentation.value; - return /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "body2", - className: classes.summaryText - }, "".concat(documentation.charAt(0).toUpperCase()).concat(documentation.substring(1))); - }, - packageType: function packageType() { - var packageType = state.packageType.value; - return /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "body2", - className: classes.summaryText - }, "".concat(packageType.charAt(0).toUpperCase()).concat(packageType.substring(1))); - }, - provisionalData: function provisionalData() { - var provisionalData = state.provisionalData.value; - return /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "body2", - className: classes.summaryText - }, "".concat(provisionalData.charAt(0).toUpperCase()).concat(provisionalData.substring(1))); - }, - s3Files: function s3Files() { - var _state$s3Files = state.s3Files, - files = _state$s3Files.value, - totalSize = _state$s3Files.totalSize; - return /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "body2", - className: classes.summaryText - }, "".concat(files.length, " file").concat(files.length === 1 ? '' : 's', " (").concat((0, _manifestUtil.formatBytes)(totalSize), " uncompressed)")); - } - }; - var renderStepForm = { - /** - SITES AND DATE RANGE - */ - sitesAndDateRange: function sitesAndDateRange() { - var requiredSteps = state.requiredSteps, - provisionalData = state.provisionalData; - var hasProvisionalDataStep = requiredSteps.some(function (step) { - return step.key === 'provisionalData'; - }); - var excludeProvisionalData = hasProvisionalDataStep && provisionalData.value === 'exclude'; - return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, !excludeProvisionalData ? null : /*#__PURE__*/_react.default.createElement(_InfoMessageCard.default, { - title: "Provisional Data", - messageContent: /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "body1" - }, "Provisional data are currently being excluded from the download package. To make those data available, include those data from within the Provisional Data step.") - }), /*#__PURE__*/_react.default.createElement(_DataProductAvailability.default, { - "data-selenium": "download-data-dialog.step-form.sites-and-date-range", - delineateRelease: delineateAvaRelease - })); - }, - /** - DOCUMENTATION - */ - documentation: function documentation() { - var neonFaqLink = /*#__PURE__*/_react.default.createElement(_Link.default, { - target: "_blank", - href: _RouteService.default.getFaqPath(), - "data-gtm": "download-data-dialog.neon-faq-link" - }, "NEON FAQ"); - var knbLink = _ExternalHost.default.renderExternalHostLink('https://eml.ecoinformatics.org', 'KNB', 'KNB', state.productData.productCode); - var _state$documentation = state.documentation, - value = _state$documentation.value, - validValues = _state$documentation.validValues; - return /*#__PURE__*/_react.default.createElement(_Grid.default, { - container: true, - spacing: 2, - alignItems: "flex-start", - "data-selenium": "download-data-dialog.step-form.documentation" - }, /*#__PURE__*/_react.default.createElement(_Grid.default, { - item: true, - xs: 12, - md: 6 - }, /*#__PURE__*/_react.default.createElement(_FormControl.default, { - component: "fieldset" - }, /*#__PURE__*/_react.default.createElement(_RadioGroup.default, { - "aria-label": "Documentation", - name: "documentation", - value: value || '', - onChange: function onChange(e) { - setState('documentation', e.target.value); - changeToNextUncompletedStep(); - } - }, /*#__PURE__*/_react.default.createElement(_FormControlLabel.default, { - className: classes.radio, - value: validValues[0], - control: /*#__PURE__*/_react.default.createElement(_Radio.default, null), - label: /*#__PURE__*/_react.default.createElement("div", { - className: classes.radioLabel - }, /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "h6" - }, "Include"), /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "body2" - }, "Include relevant documents for this Data Product")) - }), /*#__PURE__*/_react.default.createElement(_FormControlLabel.default, { - className: classes.radio, - value: validValues[1], - control: /*#__PURE__*/_react.default.createElement(_Radio.default, null), - label: /*#__PURE__*/_react.default.createElement("div", { - className: classes.radioLabel - }, /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "h6" - }, "Exclude"), /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "body2" - }, "Data only, no relevant documents for this Data Product")) - })))), /*#__PURE__*/_react.default.createElement(_Grid.default, { - item: true, - xs: 12, - md: 6 - }, /*#__PURE__*/_react.default.createElement(_Card.default, { - style: { - marginTop: _Theme.default.spacing(1.5) - } - }, /*#__PURE__*/_react.default.createElement(_CardContent.default, { - className: classes.startFlex - }, /*#__PURE__*/_react.default.createElement(_Info.default, { - fontSize: "large", - className: classes.calloutIcon - }), /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "body1" - }, "EML files for this Data Product are included in all downloads. Learn more about EML files in the ", neonFaqLink, " and at ", knbLink, "."))))); - }, - /** - PROVISIONAL DATA - */ - provisionalData: function provisionalData() { - var neonDataRevisionReleaseLink = /*#__PURE__*/_react.default.createElement(_Link.default, { - target: "_blank", - href: _RouteService.default.getDataRevisionsReleasePath(), - "data-gtm": "download-data-dialog.neon-data-revisions-releases-link" - }, "NEON Data Revisions and Releases"); - var _state$provisionalDat = state.provisionalData, - value = _state$provisionalDat.value, - validValues = _state$provisionalDat.validValues; - return /*#__PURE__*/_react.default.createElement(_Grid.default, { - container: true, - spacing: 2, - alignItems: "flex-start", - "data-selenium": "download-data-dialog.step-form.provisional-data" - }, /*#__PURE__*/_react.default.createElement(_Grid.default, { - item: true, - xs: 12, - md: 6 - }, /*#__PURE__*/_react.default.createElement(_FormControl.default, { - component: "fieldset" - }, /*#__PURE__*/_react.default.createElement(_RadioGroup.default, { - "aria-label": "Provisional Data", - name: "provisional-data", - value: value || '', - onChange: function onChange(e) { - setState('provisionalData', e.target.value); - changeToNextUncompletedStep(); - } - }, /*#__PURE__*/_react.default.createElement(_FormControlLabel.default, { - className: classes.radio, - value: validValues[0], - control: /*#__PURE__*/_react.default.createElement(_Radio.default, null), - label: /*#__PURE__*/_react.default.createElement("div", { - className: classes.radioLabel - }, /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "h6" - }, "Include"), /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "body2" - }, "Include provisional data in this download package (", /*#__PURE__*/_react.default.createElement("b", null, "Warning:"), " subject to change and not reproducible)")) - }), /*#__PURE__*/_react.default.createElement(_FormControlLabel.default, { - className: classes.radio, - value: validValues[1], - control: /*#__PURE__*/_react.default.createElement(_Radio.default, null), - label: /*#__PURE__*/_react.default.createElement("div", { - className: classes.radioLabel - }, /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "h6" - }, "Exclude"), /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "body2" - }, "Release data only, no provisional data included in this download package")) - })))), /*#__PURE__*/_react.default.createElement(_Grid.default, { - item: true, - xs: 12, - md: 6 - }, /*#__PURE__*/_react.default.createElement(_Card.default, { - style: { - marginTop: _Theme.default.spacing(1.5) - } - }, /*#__PURE__*/_react.default.createElement(_CardContent.default, { - className: classes.startFlex - }, /*#__PURE__*/_react.default.createElement(_Info.default, { - fontSize: "large", - className: classes.calloutIcon - }), /*#__PURE__*/_react.default.createElement(_Typography.default, { + var renderSitesAndDateRangeStep = function renderSitesAndDateRangeStep() { + var requiredSteps = state.requiredSteps, + provisionalData = state.provisionalData; + var hasProvisionalDataStep = requiredSteps.some(function (step) { + return step.key === 'provisionalData'; + }); + var excludeProvisionalData = hasProvisionalDataStep && provisionalData.value === 'exclude'; + return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, !excludeProvisionalData ? null : /*#__PURE__*/_react.default.createElement(_InfoMessageCard.default, { + title: "Provisional Data", + messageContent: /*#__PURE__*/_react.default.createElement(_Typography.default, { variant: "body1" - }, "Learn more about data product revisions, releases and provisional data at the ", neonDataRevisionReleaseLink, " page."))))); - }, - /** - S3 Files - */ - s3Files: function s3Files() { - var s3FileFetches = state.s3FileFetches, - s3FileFetchProgress = state.s3FileFetchProgress, - requiredSteps = state.requiredSteps, - provisionalData = state.provisionalData; - var _state$s3Files2 = state.s3Files, - selection = _state$s3Files2.value, - validValues = _state$s3Files2.validValues, - valueLookups = _state$s3Files2.valueLookups, - totalSize = _state$s3Files2.totalSize, - estimatedPostSize = _state$s3Files2.estimatedPostSize, - filters = _state$s3Files2.filters, - filteredFileCount = _state$s3Files2.filteredFileCount, - visibleColumns = _state$s3Files2.visibleColumns; - var isLoading = Object.keys(s3FileFetches).some(function (key) { - return ['awaitingFetchCall', 'fetching'].includes(s3FileFetches[key]); - }); - var hasProvisionalDataStep = requiredSteps.some(function (step) { - return step.key === 'provisionalData'; - }); - var excludeProvisionalData = hasProvisionalDataStep && provisionalData.value === 'exclude'; - var appliedValidValues = validValues; - var areProvDataExcluded = false; - if (excludeProvisionalData) { - appliedValidValues = appliedValidValues.filter(function (value) { - var includeValue = (0, _typeUtil.isStringNonEmpty)(value.release) && !_ReleaseService.default.isNonRelease(value.release); - if (!includeValue) { - areProvDataExcluded = true; - } - return includeValue; - }); + }, "Provisional data are currently being excluded from the download package. To make those data available, include those data from within the Provisional Data step.") + }), /*#__PURE__*/_react.default.createElement(_DataProductAvailability.default, { + "data-selenium": "download-data-dialog.step-form.sites-and-date-range", + delineateRelease: delineateAvaRelease + })); + }; + var renderDocumentationStep = function renderDocumentationStep() { + var neonFaqLink = /*#__PURE__*/_react.default.createElement(_Link.default, { + target: "_blank", + href: _RouteService.default.getFaqPath(), + "data-gtm": "download-data-dialog.neon-faq-link" + }, "NEON FAQ"); + var knbLink = _ExternalHost.default.renderExternalHostLink('https://eml.ecoinformatics.org', 'KNB', 'KNB', state.productData.productCode); + var _state$documentation = state.documentation, + value = _state$documentation.value, + validValues = _state$documentation.validValues; + return /*#__PURE__*/_react.default.createElement(_Grid.default, { + container: true, + spacing: 2, + alignItems: "flex-start", + "data-selenium": "download-data-dialog.step-form.documentation" + }, /*#__PURE__*/_react.default.createElement(_Grid.default, { + item: true, + xs: 12, + md: 6 + }, /*#__PURE__*/_react.default.createElement(_FormControl.default, { + component: "fieldset" + }, /*#__PURE__*/_react.default.createElement(_RadioGroup.default, { + "aria-label": "Documentation", + name: "documentation", + value: value || '', + onChange: function onChange(e) { + setState('documentation', e.target.value); + changeToNextUncompletedStep(); } - var columns = [{ - title: 'Site', - field: 'site', - lookup: valueLookups.site, - defaultFilter: filters.site || [], - hidden: !visibleColumns.includes('site') - }, { - title: 'Date', - field: 'yearMonth', - lookup: valueLookups.yearMonth, - defaultFilter: filters.yearMonth || [], - hidden: !visibleColumns.includes('date') - }, { - title: 'Visit', - field: 'visit', - lookup: valueLookups.visit, - defaultFilter: filters.visit || [], - hidden: !visibleColumns.includes('visit') - }, { - title: 'Name', - field: 'name', - defaultFilter: filters.name || '', - hidden: !visibleColumns.includes('name') - }, { - title: 'Type', - field: 'type', - lookup: valueLookups.type, - defaultFilter: filters.type || [], - hidden: !visibleColumns.includes('type') - }, { - title: 'Size', - field: 'size', - filtering: false, - removable: false, - render: function render(row) { - return (0, _manifestUtil.formatBytes)(row.size); - } - }]; - var debouncedFilterDispatch = (0, _lodash.debounce)(function (filter, value) { - dispatch({ - type: 'setS3FilesFilterValue', - filter: filter, - value: value - }); - }, 200); - var noFiltersApplied = Object.keys(filters).every(function (col) { - return !filters[col].length; - }); - /* eslint-disable react/jsx-one-expression-per-line */ - var postSizeError = estimatedPostSize >= _manifestUtil.MAX_POST_BODY_SIZE ? /*#__PURE__*/_react.default.createElement(_Grid.default, { - item: true, - xs: 12 - }, /*#__PURE__*/_react.default.createElement(_Card.default, { - style: { - marginBottom: _Theme.default.spacing(2), - backgroundColor: _Theme.COLORS.GOLD[300] - } - }, /*#__PURE__*/_react.default.createElement(_CardContent.default, { - className: classes.startFlex, - style: { - justifyContent: 'center' - } - }, /*#__PURE__*/_react.default.createElement(_Warning.default, { - fontSize: "large", - className: classes.calloutIcon, - style: { - color: _Theme.COLORS.GOLD[800] - } - }), /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "body1" - }, "Too many files requested! Current selection will make an estimated ", /*#__PURE__*/_react.default.createElement("b", null, (0, _manifestUtil.formatBytes)(estimatedPostSize)), " request; max size is ", /*#__PURE__*/_react.default.createElement("b", null, (0, _manifestUtil.formatBytes)(_manifestUtil.MAX_POST_BODY_SIZE)), ". Please select fewer files in order to proceed.")))) : null; - var components = { - Container: _Box.default, - Toolbar: function Toolbar(toolbarProps) { - return /*#__PURE__*/_react.default.createElement(_Grid.default, { - container: true, - spacing: 2, - alignItems: "flex-start", - style: { - marginBottom: '24px' - } - }, /*#__PURE__*/_react.default.createElement(_Grid.default, { - item: true, - xs: 12, - md: 6 - }, /*#__PURE__*/_react.default.createElement("div", { - style: { - marginBottom: _Theme.default.spacing(1) - } - }, /*#__PURE__*/_react.default.createElement(_ToggleButtonGroup.default, { - size: "small", - value: visibleColumns, - onChange: function onChange(event, newVisibleColumns) { - return dispatch({ - type: 'setS3FilesVisibleColumns', - visibleColumns: newVisibleColumns - }); - }, - "aria-label": "show and hide columns", - "data-selenium": "download-data-dialog.s3-files.show-hide-columns-button-group" - }, /*#__PURE__*/_react.default.createElement(_ToggleButton.default, { - value: "label", - className: classes.showColumnsLabel, - disabled: true - }, "Show Columns:"), /*#__PURE__*/_react.default.createElement(_ToggleButton.default, { - value: "site" - }, "Site"), /*#__PURE__*/_react.default.createElement(_ToggleButton.default, { - value: "visit" - }, "Visit"), /*#__PURE__*/_react.default.createElement(_ToggleButton.default, { - value: "date" - }, "Date"), /*#__PURE__*/_react.default.createElement(_ToggleButton.default, { - value: "name" - }, "Name"), /*#__PURE__*/_react.default.createElement(_ToggleButton.default, { - value: "type" - }, "Type"))), /*#__PURE__*/_react.default.createElement("div", { - style: { - marginBottom: _Theme.default.spacing(1) - } - }, /*#__PURE__*/_react.default.createElement(_Button.default, { - "data-selenium": "download-data-dialog.s3-files.select-all-button", - size: "small", - color: "primary", - variant: "outlined", - onClick: function onClick() { - dispatch({ - type: 'setS3FilesValueSelectAll' - }); - }, - disabled: isLoading || !appliedValidValues.length, - style: { - whiteSpace: 'nowrap' - } - }, /*#__PURE__*/_react.default.createElement(_DoneAll.default, { - fontSize: "small", - style: { - marginRight: _Theme.default.spacing(1) - } - }), "Select All (", isLoading ? '…' : appliedValidValues.length, ")"), /*#__PURE__*/_react.default.createElement(_Button.default, { - "data-selenium": "download-data-dialog.s3-files.select-none-button", - size: "small", - color: "primary", - variant: "outlined", - onClick: function onClick() { - dispatch({ - type: 'setS3FilesValueSelectNone' - }); - }, - disabled: isLoading || !appliedValidValues.length, - style: { - marginLeft: _Theme.default.spacing(1), - whiteSpace: 'nowrap' - } - }, /*#__PURE__*/_react.default.createElement(_Clear.default, { - fontSize: "small", - style: { - marginRight: _Theme.default.spacing(1) - } - }), "Select None")), /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_Button.default, { - "data-selenium": "download-data-dialog.s3-files.select-filtered-button", - size: "small", - color: "primary", - variant: "outlined", - onClick: function onClick() { - dispatch({ - type: 'setS3FilesValueSelectFiltered' - }); - }, - disabled: noFiltersApplied || isLoading, - style: { - whiteSpace: 'nowrap' - } - }, /*#__PURE__*/_react.default.createElement(_FilterList.default, { - fontSize: "small", - style: { - marginRight: _Theme.default.spacing(1) - } - }), "Select Filtered", noFiltersApplied ? '' : " (".concat(isLoading ? '…' : filteredFileCount, ")")), /*#__PURE__*/_react.default.createElement(_Button.default, { - "data-selenium": "download-data-dialog.s3-files.clear-filters-button", - size: "small", - color: "primary", - variant: "outlined", - disabled: noFiltersApplied || isLoading, - onClick: function onClick() { - dispatch({ - type: 'clearS3FilesFilterValues' - }); - }, - style: { - marginLeft: _Theme.default.spacing(1), - whiteSpace: 'nowrap' - } - }, /*#__PURE__*/_react.default.createElement(_DeleteSweep.default, { - fontSize: "small", - style: { - marginRight: _Theme.default.spacing(1) - } - }), "Clear Filters"))), /*#__PURE__*/_react.default.createElement(_Grid.default, { - item: true, - xs: 12, - md: 6 - }, /*#__PURE__*/_react.default.createElement(_materialTable.MTableToolbar, toolbarProps)), postSizeError); - }, - FilterRow: function FilterRow(filterRowProps) { - return /*#__PURE__*/_react.default.createElement(_materialTable.MTableFilterRow, _extends({}, filterRowProps, { - onFilterChanged: function onFilterChanged(columnId, value) { - var onFilterChanged = filterRowProps.onFilterChanged; - onFilterChanged(columnId, value); - var filter = columns[columnId].field; - var current = filters[filter]; - if (filter === 'name' && value !== current) { - debouncedFilterDispatch(filter, value); - return; - } - if (current && (value.length !== current.length || value.some(function (v) { - return !current.includes(v); - }))) { - dispatch({ - type: 'setS3FilesFilterValue', - filter: filter, - value: value - }); - } - } - })); - } - }; - /* eslint-enable react/jsx-one-expression-per-line */ - var localization = { - pagination: { - labelRowsSelect: 'files' - }, - toolbar: { - nRowsSelected: "{0} file".concat(selection.length === 1 ? '' : 's', " selected (").concat((0, _manifestUtil.formatBytes)(totalSize), " uncompressed)") - }, - body: { - emptyDataSourceMessage: 'No files to display. Select more sites, broaden date range, or broaden search / filters.' - } - }; - return appliedValidValues.length || isLoading ? /*#__PURE__*/_react.default.createElement("div", { - className: classes.fileTable, - id: "s3Files-selection-table-container" - }, /*#__PURE__*/_react.default.createElement(_materialTable.default, { - icons: _MaterialTableIcons.default, - components: components, - columns: columns, - data: appliedValidValues, - localization: localization, - options: { - selection: true, - showSelectAllCheckbox: false, - padding: 'dense', - filtering: true, - columnsButton: false, - pageSize: 10, - pageSizeOptions: [5, 10, 50, 100], - showTitle: false, - search: false, - isLoading: isLoading - }, - onSelectionChange: function onSelectionChange(rows, file) { - dispatch({ - type: 'setIndividualS3FileSelected', - url: file.url, - selected: file.tableData.checked - }); - } - }), /*#__PURE__*/_react.default.createElement("div", { - className: classes.loadingOverlay, - style: { - display: isLoading ? 'block' : 'none' - } + }, /*#__PURE__*/_react.default.createElement(_FormControlLabel.default, { + className: classes.radio, + value: validValues[0], + control: /*#__PURE__*/_react.default.createElement(_Radio.default, null), + label: /*#__PURE__*/_react.default.createElement("div", { + className: classes.radioLabel }, /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "h6", - style: { - marginBottom: _Theme.default.spacing(4) - } - }, "Loading files (".concat(Math.floor(s3FileFetchProgress || 0), "%)...")), /*#__PURE__*/_react.default.createElement(_CircularProgress.default, { - variant: "determinate", - value: s3FileFetchProgress - }))) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, !excludeProvisionalData || !areProvDataExcluded ? null : /*#__PURE__*/_react.default.createElement(_InfoMessageCard.default, { - title: "Provisional Data", - messageContent: /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "body1" - }, "Provisional data are currently being excluded from selection. To make those data available for selection, include those data from within the Provisional Data step.") - }), /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "subtitle1", - style: { - marginTop: _Theme.default.spacing(3) - } - }, "Select sites and date range in order to generate a list of files to choose from.")); - }, - /** - PACKAGE TYPE - */ - packageType: function packageType() { - var _state$packageType = state.packageType, - value = _state$packageType.value, - validValues = _state$packageType.validValues; - var _state$productData = state.productData, - productBasicDescription = _state$productData.productBasicDescription, - productExpandedDescription = _state$productData.productExpandedDescription; - if (!productBasicDescription) { - productBasicDescription = 'Includes the data product, summary statistics, expanded uncertainty, and final quality flag'; + variant: "h6" + }, "Include"), /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "body2" + }, "Include relevant documents for this Data Product")) + }), /*#__PURE__*/_react.default.createElement(_FormControlLabel.default, { + className: classes.radio, + value: validValues[1], + control: /*#__PURE__*/_react.default.createElement(_Radio.default, null), + label: /*#__PURE__*/_react.default.createElement("div", { + className: classes.radioLabel + }, /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "h6" + }, "Exclude"), /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "body2" + }, "Data only, no relevant documents for this Data Product")) + })))), /*#__PURE__*/_react.default.createElement(_Grid.default, { + item: true, + xs: 12, + md: 6 + }, /*#__PURE__*/_react.default.createElement(_Card.default, { + style: { + marginTop: _Theme.default.spacing(1.5) } - if (!productExpandedDescription) { - productExpandedDescription = 'Includes the basic package information plus quality metrics for all of the quality assessment and quality control analysis'; + }, /*#__PURE__*/_react.default.createElement(_CardContent.default, { + className: classes.startFlex + }, /*#__PURE__*/_react.default.createElement(_Info.default, { + fontSize: "large", + className: classes.calloutIcon + }), /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "body1" + }, "EML files for this Data Product are included in all downloads. Learn more about EML files in the ", neonFaqLink, " and at ", knbLink, "."))))); + }; + var renderProvisionalDataStep = function renderProvisionalDataStep() { + var neonDataRevisionReleaseLink = /*#__PURE__*/_react.default.createElement(_Link.default, { + target: "_blank", + href: _RouteService.default.getDataRevisionsReleasePath(), + "data-gtm": "download-data-dialog.neon-data-revisions-releases-link" + }, "NEON Data Revisions and Releases"); + var _state$provisionalDat = state.provisionalData, + value = _state$provisionalDat.value, + validValues = _state$provisionalDat.validValues; + return /*#__PURE__*/_react.default.createElement(_Grid.default, { + container: true, + spacing: 2, + alignItems: "flex-start", + "data-selenium": "download-data-dialog.step-form.provisional-data" + }, /*#__PURE__*/_react.default.createElement(_Grid.default, { + item: true, + xs: 12, + md: 6 + }, /*#__PURE__*/_react.default.createElement(_FormControl.default, { + component: "fieldset" + }, /*#__PURE__*/_react.default.createElement(_RadioGroup.default, { + "aria-label": "Provisional Data", + name: "provisional-data", + value: value || '', + onChange: function onChange(e) { + setState('provisionalData', e.target.value); + changeToNextUncompletedStep(); } - return /*#__PURE__*/_react.default.createElement(_FormControl.default, { - "data-selenium": "download-data-dialog.step-form.package-type", - component: "fieldset" - }, /*#__PURE__*/_react.default.createElement(_RadioGroup.default, { - "aria-label": "Package Type", - name: "package-type", - value: value || '', - onChange: function onChange(e) { - setState('packageType', e.target.value); - changeToNextUncompletedStep(); - } - }, /*#__PURE__*/_react.default.createElement(_FormControlLabel.default, { - className: classes.radio, - value: validValues[0], - control: /*#__PURE__*/_react.default.createElement(_Radio.default, null), - label: /*#__PURE__*/_react.default.createElement("div", { - className: classes.radioLabel - }, /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "h6" - }, "Basic"), /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "body2" - }, productBasicDescription)) - }), /*#__PURE__*/_react.default.createElement(_FormControlLabel.default, { - className: classes.radio, - value: validValues[1], - control: /*#__PURE__*/_react.default.createElement(_Radio.default, null), - label: /*#__PURE__*/_react.default.createElement("div", { - className: classes.radioLabel - }, /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "h6" - }, "Expanded"), /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "body2" - }, productExpandedDescription)) - }))); - }, - /** - EXTERNAL LINKS - EXCLUSIVE HOSTING - */ - externalExclusive: function externalExclusive() { - var externalHost = _ExternalHost.default.getByProductCode(state.productData.productCode); - if (!externalHost) { - return null; + }, /*#__PURE__*/_react.default.createElement(_FormControlLabel.default, { + className: classes.radio, + value: validValues[0], + control: /*#__PURE__*/_react.default.createElement(_Radio.default, null), + label: /*#__PURE__*/_react.default.createElement("div", { + className: classes.radioLabel + }, /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "h6" + }, "Include"), /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "body2" + }, "Include provisional data in this download package (", /*#__PURE__*/_react.default.createElement("b", null, "Warning:"), " subject to change and not reproducible)")) + }), /*#__PURE__*/_react.default.createElement(_FormControlLabel.default, { + className: classes.radio, + value: validValues[1], + control: /*#__PURE__*/_react.default.createElement(_Radio.default, null), + label: /*#__PURE__*/_react.default.createElement("div", { + className: classes.radioLabel + }, /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "h6" + }, "Exclude"), /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "body2" + }, "Release data only, no provisional data included in this download package")) + })))), /*#__PURE__*/_react.default.createElement(_Grid.default, { + item: true, + xs: 12, + md: 6 + }, /*#__PURE__*/_react.default.createElement(_Card.default, { + style: { + marginTop: _Theme.default.spacing(1.5) } - var hostLink = externalHost.renderLink(state.productData.productCode); - var availableSiteCodes = (state.productData.siteCodes || []).map(function (site) { - return site.siteCode; + }, /*#__PURE__*/_react.default.createElement(_CardContent.default, { + className: classes.startFlex + }, /*#__PURE__*/_react.default.createElement(_Info.default, { + fontSize: "large", + className: classes.calloutIcon + }), /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "body1" + }, "Learn more about data product revisions, releases and provisional data at ", neonDataRevisionReleaseLink, "."))))); + }; + var renderS3FilesStep = function renderS3FilesStep() { + var s3FileFetches = state.s3FileFetches, + s3FileFetchProgress = state.s3FileFetchProgress, + requiredSteps = state.requiredSteps, + provisionalData = state.provisionalData; + var _state$s3Files2 = state.s3Files, + selection = _state$s3Files2.value, + validValues = _state$s3Files2.validValues, + valueLookups = _state$s3Files2.valueLookups, + totalSize = _state$s3Files2.totalSize, + estimatedPostSize = _state$s3Files2.estimatedPostSize, + filters = _state$s3Files2.filters, + filteredFileCount = _state$s3Files2.filteredFileCount, + visibleColumns = _state$s3Files2.visibleColumns, + maxNumFilesSelected = _state$s3Files2.maxNumFilesSelected; + var isLoading = Object.keys(s3FileFetches).some(function (key) { + return ['awaitingFetchCall', 'fetching'].includes(s3FileFetches[key]); + }); + var hasProvisionalDataStep = requiredSteps.some(function (step) { + return step.key === 'provisionalData'; + }); + var excludeProvisionalData = hasProvisionalDataStep && provisionalData.value === 'exclude'; + var appliedValidValues = validValues; + var areProvDataExcluded = false; + if (excludeProvisionalData) { + appliedValidValues = appliedValidValues.filter(function (value) { + var includeValue = (0, _typeUtil.isStringNonEmpty)(value.release) && !_ReleaseService.default.isNonRelease(value.release); + if (!includeValue) { + areProvDataExcluded = true; + } + return includeValue; }); - var externalHostProduct = _ExternalHost.default.getProductSpecificInfo(state.productData.productCode); - var allowNoAvailability = (0, _typeUtil.exists)(externalHostProduct) && externalHostProduct.allowNoAvailability === true; - var noData = !(0, _typeUtil.existsNonEmpty)(availableSiteCodes); - var noLinks = allowNoAvailability && noData; - var blurb; - if (noLinks) { - blurb = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, "Data for this product is not currently available for download through the NEON Data Portal. Please use this link to access data for this product for a particular site from ", hostLink, "."); - } else { - blurb = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, "Data for this product is not currently available for download through the NEON Data Portal. Please use the links below to access data for this product for a particular site from the ", hostLink, "."); + } + var allowSelectAll = appliedValidValues.length <= maxNumFilesSelected; + var allowSelectFiltered = filteredFileCount <= maxNumFilesSelected; + var columns = [{ + title: 'Site', + field: 'site', + lookup: valueLookups.site, + defaultFilter: filters.site || [], + hidden: !visibleColumns.includes('site'), + render: function render(row) { + return row.site; } - return /*#__PURE__*/_react.default.createElement("div", { - "data-selenium": "download-data-dialog.step-form.external-links.".concat(externalHost.id.toLowerCase()) - }, /*#__PURE__*/_react.default.createElement(_InfoMessageCard.default, { - title: "External Host", - messageContent: /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "subtitle2" - }, blurb) - }), noLinks ? null : /*#__PURE__*/_react.default.createElement(_ExternalHostProductSpecificLinks.default, { - productCode: state.productData.productCode, - siteCodes: availableSiteCodes - })); - }, - /** - POLICIES - */ - policies: function policies() { - var agreed = state.policies.value; - var checkbox = /*#__PURE__*/_react.default.createElement(_Checkbox.default, { - color: "primary", - value: "policies", - checked: agreed, - disabled: agreed, - onChange: function onChange() { - setState('policies', true); - changeToNextUncompletedStep(); - } + }, { + title: 'Date', + field: 'yearMonth', + lookup: valueLookups.yearMonth, + defaultFilter: filters.yearMonth || [], + hidden: !visibleColumns.includes('date'), + render: function render(row) { + return row.yearMonth; + } + }, { + title: 'Visit', + field: 'visit', + lookup: valueLookups.visit, + defaultFilter: filters.visit || [], + hidden: !visibleColumns.includes('visit'), + render: function render(row) { + return row.visit; + } + }, { + title: 'Name', + field: 'name', + defaultFilter: filters.name || '', + hidden: !visibleColumns.includes('name'), + render: function render(row) { + return row.name; + } + }, { + title: 'Type', + field: 'type', + lookup: valueLookups.type, + defaultFilter: filters.type || [], + hidden: !visibleColumns.includes('type'), + render: function render(row) { + return row.type; + } + }, { + title: 'Size', + field: 'size', + filtering: false, + removable: false, + render: function render(row) { + return (0, _manifestUtil.formatBytes)(row.size); + } + }]; + var debouncedFilterDispatch = (0, _lodash.debounce)(function (filter, value) { + dispatch({ + type: 'setS3FilesFilterValue', + filter: filter, + value: value }); - /* eslint-disable react/jsx-one-expression-per-line */ - return /*#__PURE__*/_react.default.createElement("div", { - "data-selenium": "download-data-dialog.step-form.policies" - }, /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "subtitle1", - gutterBottom: true - }, "In order to proceed to download NEON data you must agree to the ", dataUsageAndCitationPoliciesLink, "."), /*#__PURE__*/_react.default.createElement(_FormControlLabel.default, { - control: checkbox, - className: classes.formControlBold, - label: "I agree to the NEON Data Usage and Citation Policies." - })); - /* eslint-enable react/jsx-one-expression-per-line */ - }, - - /** - SUMMARY - */ - summary: function summary() { - var stepSummary = /*#__PURE__*/_react.default.createElement("div", { - "data-selenium": "download-data-dialog.step-form.summary" - }, state.requiredSteps.map(function (step, index) { - if (['summary', 'policies'].includes(step.key)) { - return null; - } - var isComplete = state.requiredSteps[index].isComplete; - return /*#__PURE__*/_react.default.createElement("div", { - key: step.key, - className: classes.stepSummary + }, 200); + var noFiltersApplied = Object.keys(filters).every(function (col) { + return !filters[col].length; + }); + /* eslint-disable react/jsx-one-expression-per-line */ + var postSizeError = estimatedPostSize >= _manifestUtil.MAX_POST_BODY_SIZE ? /*#__PURE__*/_react.default.createElement(_Grid.default, { + item: true, + xs: 12 + }, /*#__PURE__*/_react.default.createElement(_Card.default, { + style: { + marginBottom: _Theme.default.spacing(2), + backgroundColor: _Theme.COLORS.GOLD[300] + } + }, /*#__PURE__*/_react.default.createElement(_CardContent.default, { + className: classes.startFlex, + style: { + justifyContent: 'center' + } + }, /*#__PURE__*/_react.default.createElement(_Warning.default, { + fontSize: "large", + className: classes.calloutIcon, + style: { + color: _Theme.COLORS.GOLD[800] + } + }), /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "body1" + }, "Too many files requested! Current selection will make an estimated ", /*#__PURE__*/_react.default.createElement("b", null, (0, _manifestUtil.formatBytes)(estimatedPostSize)), " request; max size is ", /*#__PURE__*/_react.default.createElement("b", null, (0, _manifestUtil.formatBytes)(_manifestUtil.MAX_POST_BODY_SIZE)), ". Please select fewer files in order to proceed.")))) : null; + /* eslint-disable react/jsx-one-expression-per-line */ + var tooManyFilesWarning = !allowSelectAll && !allowSelectFiltered ? /*#__PURE__*/_react.default.createElement(_Grid.default, { + item: true, + xs: 12 + }, /*#__PURE__*/_react.default.createElement(_Card.default, { + style: { + marginBottom: _Theme.default.spacing(2), + backgroundColor: _Theme.COLORS.GOLD[300] + } + }, /*#__PURE__*/_react.default.createElement(_CardContent.default, { + className: classes.startFlex, + style: { + justifyContent: 'center' + } + }, /*#__PURE__*/_react.default.createElement(_Warning.default, { + fontSize: "large", + className: classes.calloutIcon, + style: { + color: _Theme.COLORS.GOLD[800] + } + }), /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "body1" + }, "Too many files available for bulk selection. Please narrow your selection by selecting fewer sites, a more restrictive date range, or a more restrictive set of filters.")))) : null; + var filterButtonLoadingLabel = " (".concat(isLoading ? '…' : filteredFileCount, ")"); + var filterButtonLabel = noFiltersApplied ? '' : filterButtonLoadingLabel; + var components = { + Container: _Box.default, + Toolbar: function Toolbar(toolbarProps) { + return /*#__PURE__*/_react.default.createElement(_Grid.default, { + container: true, + spacing: 2, + alignItems: "flex-start", + style: { + marginBottom: '24px' + } + }, /*#__PURE__*/_react.default.createElement(_Grid.default, { + item: true, + xs: 12, + md: 6 }, /*#__PURE__*/_react.default.createElement("div", { - role: "button", - tabIndex: 0, - className: classes.stepSummaryHeader, + style: { + marginBottom: _Theme.default.spacing(1) + } + }, /*#__PURE__*/_react.default.createElement(_ToggleButtonGroup.default, { + size: "small", + value: visibleColumns, + onChange: function onChange(event, newVisibleColumns) { + return dispatch({ + type: 'setS3FilesVisibleColumns', + visibleColumns: newVisibleColumns + }); + }, + "aria-label": "show and hide columns", + "data-selenium": "download-data-dialog.s3-files.show-hide-columns-button-group" + }, /*#__PURE__*/_react.default.createElement(_ToggleButton.default, { + value: "label", + className: classes.showColumnsLabel, + disabled: true + }, "Show Columns:"), /*#__PURE__*/_react.default.createElement(_ToggleButton.default, { + value: "site" + }, "Site"), /*#__PURE__*/_react.default.createElement(_ToggleButton.default, { + value: "visit" + }, "Visit"), /*#__PURE__*/_react.default.createElement(_ToggleButton.default, { + value: "date" + }, "Date"), /*#__PURE__*/_react.default.createElement(_ToggleButton.default, { + value: "name" + }, "Name"), /*#__PURE__*/_react.default.createElement(_ToggleButton.default, { + value: "type" + }, "Type"))), /*#__PURE__*/_react.default.createElement("div", { + style: { + marginBottom: _Theme.default.spacing(1) + } + }, /*#__PURE__*/_react.default.createElement(_Button.default, { + "data-selenium": "download-data-dialog.s3-files.select-all-button", + size: "small", + color: "primary", + variant: "outlined", onClick: function onClick() { - return changeToStep(index); + dispatch({ + type: 'setS3FilesValueSelectAll' + }); }, - onKeyPress: function onKeyPress() { - return changeToStep(index); + disabled: isLoading || !appliedValidValues.length || !allowSelectAll, + style: { + whiteSpace: 'nowrap' } - }, /*#__PURE__*/_react.default.createElement(_Chip.default, { - color: isComplete ? 'primary' : 'default', - label: index + 1, - className: classes.summaryChip - }), /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "h6", + }, /*#__PURE__*/_react.default.createElement(_DoneAll.default, { + fontSize: "small", style: { - flexGrow: 1 + marginRight: _Theme.default.spacing(1) } - }, _DownloadDataContext.default.ALL_STEPS[step.key].label)), /*#__PURE__*/_react.default.createElement("div", { - className: classes.stepSummaryContent - }, isComplete ? renderStepSummary[step.key]() : /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "body2", - className: classes.summaryTextIncomplete - }, "Incomplete"))); - }), /*#__PURE__*/_react.default.createElement("div", { - key: "download", - className: classes.stepSummary - }, renderDownloadButton())); - var downloadAndExploreLink = /*#__PURE__*/_react.default.createElement(_Link.default, { - target: "_blank", - href: _RouteService.default.getDownloadExplorePath(), - "data-gtm": "download-data-dialog.download-and-explore-link" - }, "Download and Explore NEON Data"); - var downloadAndExploreCallout = /*#__PURE__*/_react.default.createElement(_Card.default, { - style: { - margin: _Theme.default.spacing(0.5, 0, 3, 0) - }, - "data-selenium": "download-data-dialog.step-form.summary.download-and-explore" - }, /*#__PURE__*/_react.default.createElement(_CardContent.default, { - className: classes.startFlex - }, /*#__PURE__*/_react.default.createElement(_Explore.default, { - fontSize: "large", - className: classes.calloutIcon - }), /*#__PURE__*/_react.default.createElement(_Typography.default, { - variant: "subtitle2" - }, "Tip: Check out our ", downloadAndExploreLink, " tutorial. This tutorial will explain how our neonUtilities package can be used to unzip and join data tables with just a few lines of code."))); - var fileNamingConventionsLink = /*#__PURE__*/_react.default.createElement(_Link.default, { - target: "_blank", - href: _RouteService.default.getFileNamingConventionsPath(), - "data-gtm": "download-data-dialog.file-naming-conventions-link" - }, "NEON File Naming Conventions"); - var fileNamingCallout = /*#__PURE__*/_react.default.createElement(_Card.default, { - style: { - margin: _Theme.default.spacing(0.5, 0, 3, 0) - }, - "data-selenium": "download-data-dialog.step-form.summary.file-naming" - }, /*#__PURE__*/_react.default.createElement(_CardContent.default, { - className: classes.startFlex - }, /*#__PURE__*/_react.default.createElement(_Description.default, { - fontSize: "large", - className: classes.calloutIcon - }), /*#__PURE__*/_react.default.createElement(_Typography.default, { + }), "Select All (", isLoading ? '…' : appliedValidValues.length, ")"), /*#__PURE__*/_react.default.createElement(_Button.default, { + "data-selenium": "download-data-dialog.s3-files.select-none-button", + size: "small", + color: "primary", + variant: "outlined", + onClick: function onClick() { + dispatch({ + type: 'setS3FilesValueSelectNone' + }); + }, + disabled: isLoading || !appliedValidValues.length, + style: { + marginLeft: _Theme.default.spacing(1), + whiteSpace: 'nowrap' + } + }, /*#__PURE__*/_react.default.createElement(_Clear.default, { + fontSize: "small", + style: { + marginRight: _Theme.default.spacing(1) + } + }), "Select None")), /*#__PURE__*/_react.default.createElement("div", null, /*#__PURE__*/_react.default.createElement(_Button.default, { + "data-selenium": "download-data-dialog.s3-files.select-filtered-button", + size: "small", + color: "primary", + variant: "outlined", + onClick: function onClick() { + dispatch({ + type: 'setS3FilesValueSelectFiltered' + }); + }, + disabled: noFiltersApplied || isLoading || !allowSelectFiltered, + style: { + whiteSpace: 'nowrap' + } + }, /*#__PURE__*/_react.default.createElement(_FilterList.default, { + fontSize: "small", + style: { + marginRight: _Theme.default.spacing(1) + } + }), "Select Filtered", filterButtonLabel), /*#__PURE__*/_react.default.createElement(_Button.default, { + "data-selenium": "download-data-dialog.s3-files.clear-filters-button", + size: "small", + color: "primary", + variant: "outlined", + disabled: noFiltersApplied || isLoading, + onClick: function onClick() { + dispatch({ + type: 'clearS3FilesFilterValues' + }); + }, + style: { + marginLeft: _Theme.default.spacing(1), + whiteSpace: 'nowrap' + } + }, /*#__PURE__*/_react.default.createElement(_DeleteSweep.default, { + fontSize: "small", + style: { + marginRight: _Theme.default.spacing(1) + } + }), "Clear Filters"))), /*#__PURE__*/_react.default.createElement(_Grid.default, { + item: true, + xs: 12, + md: 6 + }, /*#__PURE__*/_react.default.createElement(_materialTable.MTableToolbar, toolbarProps)), postSizeError, tooManyFilesWarning, !excludeProvisionalData || !areProvDataExcluded ? null : /*#__PURE__*/_react.default.createElement("div", { + style: { + marginLeft: '8px', + marginRight: '8px', + width: '100%' + } + }, /*#__PURE__*/_react.default.createElement(_InfoMessageCard.default, { + title: "Provisional Data", + messageContent: /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "body1" + }, "Provisional data are currently being excluded from selection. To make those data available for selection, include those data from within the Provisional Data step.") + }))); + }, + FilterRow: function FilterRow(filterRowProps) { + return /*#__PURE__*/_react.default.createElement(_materialTable.MTableFilterRow, _extends({}, filterRowProps, { + onFilterChanged: function onFilterChanged(columnId, value) { + var onFilterChanged = filterRowProps.onFilterChanged; + onFilterChanged(columnId, value); + var filter = columns[columnId].field; + var current = filters[filter]; + if (filter === 'name' && value !== current) { + debouncedFilterDispatch(filter, value); + return; + } + if (current && (value.length !== current.length || value.some(function (v) { + return !current.includes(v); + }))) { + dispatch({ + type: 'setS3FilesFilterValue', + filter: filter, + value: value + }); + } + } + })); + } + }; + /* eslint-enable react/jsx-one-expression-per-line */ + var localization = { + pagination: { + labelRowsSelect: 'files' + }, + toolbar: { + nRowsSelected: "{0} file".concat(selection.length === 1 ? '' : 's', " selected (").concat((0, _manifestUtil.formatBytes)(totalSize), " uncompressed)") + }, + body: { + emptyDataSourceMessage: 'No files to display. Select more sites, broaden date range, or broaden search / filters.' + } + }; + return appliedValidValues.length || isLoading ? /*#__PURE__*/_react.default.createElement("div", { + className: classes.fileTable, + id: "s3Files-selection-table-container" + }, /*#__PURE__*/_react.default.createElement(_materialTable.default, { + icons: _MaterialTableIcons.default, + components: components, + columns: columns, + data: appliedValidValues, + localization: localization, + options: { + selection: true, + showSelectAllCheckbox: false, + padding: 'dense', + filtering: true, + columnsButton: false, + pageSize: 10, + pageSizeOptions: [5, 10, 50, 100], + showTitle: false, + search: false, + isLoading: isLoading + }, + onSelectionChange: function onSelectionChange(rows, file) { + dispatch({ + type: 'setIndividualS3FileSelected', + url: file.url, + selected: file.tableData.checked + }); + } + }), /*#__PURE__*/_react.default.createElement("div", { + className: classes.loadingOverlay, + style: { + display: isLoading ? 'block' : 'none' + } + }, /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "h6", + style: { + marginBottom: _Theme.default.spacing(4) + } + }, "Loading files (".concat(Math.floor(s3FileFetchProgress || 0), "%)...")), /*#__PURE__*/_react.default.createElement(_CircularProgress.default, { + variant: "determinate", + value: s3FileFetchProgress + }))) : /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "subtitle1", + style: { + marginTop: _Theme.default.spacing(3) + } + }, "Select sites and date range in order to generate a list of files to choose from."); + }; + var renderPackageTypeStep = function renderPackageTypeStep() { + var _state$packageType = state.packageType, + value = _state$packageType.value, + validValues = _state$packageType.validValues; + var _state$productData = state.productData, + productBasicDescription = _state$productData.productBasicDescription, + productExpandedDescription = _state$productData.productExpandedDescription; + if (!productBasicDescription) { + productBasicDescription = 'Includes the data product, summary statistics, expanded uncertainty, and final quality flag'; + } + if (!productExpandedDescription) { + productExpandedDescription = 'Includes the basic package information plus quality metrics for all of the quality assessment and quality control analysis'; + } + return /*#__PURE__*/_react.default.createElement(_FormControl.default, { + "data-selenium": "download-data-dialog.step-form.package-type", + component: "fieldset" + }, /*#__PURE__*/_react.default.createElement(_RadioGroup.default, { + "aria-label": "Package Type", + name: "package-type", + value: value || '', + onChange: function onChange(e) { + setState('packageType', e.target.value); + changeToNextUncompletedStep(); + } + }, /*#__PURE__*/_react.default.createElement(_FormControlLabel.default, { + className: classes.radio, + value: validValues[0], + control: /*#__PURE__*/_react.default.createElement(_Radio.default, null), + label: /*#__PURE__*/_react.default.createElement("div", { + className: classes.radioLabel + }, /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "h6" + }, "Basic"), /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "body2" + }, productBasicDescription)) + }), /*#__PURE__*/_react.default.createElement(_FormControlLabel.default, { + className: classes.radio, + value: validValues[1], + control: /*#__PURE__*/_react.default.createElement(_Radio.default, null), + label: /*#__PURE__*/_react.default.createElement("div", { + className: classes.radioLabel + }, /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "h6" + }, "Expanded"), /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "body2" + }, productExpandedDescription)) + }))); + }; + var renderExternalExclusiveStep = function renderExternalExclusiveStep() { + var externalHost = _ExternalHost.default.getByProductCode(state.productData.productCode); + if (!externalHost) { + return null; + } + var hostLink = externalHost.renderLink(state.productData.productCode); + var availableSiteCodes = (state.productData.siteCodes || []).map(function (site) { + return site.siteCode; + }); + var externalHostProduct = _ExternalHost.default.getProductSpecificInfo(state.productData.productCode); + var allowNoAvailability = (0, _typeUtil.exists)(externalHostProduct) && externalHostProduct.allowNoAvailability === true; + var noData = !(0, _typeUtil.existsNonEmpty)(availableSiteCodes); + var noLinks = allowNoAvailability && noData; + var blurb; + if (noLinks) { + blurb = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, "Data for this product is not currently available for download through the NEON Data Portal. Please use this link to access data for this product for a particular site from ", hostLink, "."); + } else { + blurb = /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, "Data for this product is not currently available for download through the NEON Data Portal. Please use the links below to access data for this product for a particular site from the ", hostLink, "."); + } + return /*#__PURE__*/_react.default.createElement("div", { + "data-selenium": "download-data-dialog.step-form.external-links.".concat(externalHost.id.toLowerCase()) + }, /*#__PURE__*/_react.default.createElement(_InfoMessageCard.default, { + title: "External Host", + messageContent: /*#__PURE__*/_react.default.createElement(_Typography.default, { variant: "subtitle2" - }, "Files in this download will follow ", fileNamingConventionsLink, "."))); - var citationProductCode = ''; - var citationRelease; - if (state.productData && state.productData.productCode) { - citationProductCode = state.productData.productCode; + }, blurb) + }), noLinks ? null : /*#__PURE__*/_react.default.createElement(_ExternalHostProductSpecificLinks.default, { + productCode: state.productData.productCode, + siteCodes: availableSiteCodes + })); + }; + var renderPoliciesStep = function renderPoliciesStep() { + var agreed = state.policies.value; + var checkbox = /*#__PURE__*/_react.default.createElement(_Checkbox.default, { + color: "primary", + value: "policies", + checked: agreed, + disabled: agreed, + onChange: function onChange() { + setState('policies', true); + changeToNextUncompletedStep(); } - if (state.release && state.release.value) { - citationRelease = state.release.value; + }); + /* eslint-disable react/jsx-one-expression-per-line */ + return /*#__PURE__*/_react.default.createElement("div", { + "data-selenium": "download-data-dialog.step-form.policies" + }, /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "subtitle1", + gutterBottom: true + }, "In order to proceed to download NEON data you must agree to the ", dataUsageAndCitationPoliciesLink, "."), /*#__PURE__*/_react.default.createElement(_FormControlLabel.default, { + control: checkbox, + className: classes.formControlBold, + label: "I agree to the NEON Data Usage and Citation Policies." + })); + /* eslint-enable react/jsx-one-expression-per-line */ + }; + + var renderSummaryStep = function renderSummaryStep() { + var stepSummary = /*#__PURE__*/_react.default.createElement("div", { + "data-selenium": "download-data-dialog.step-form.summary" + }, state.requiredSteps.map(function (step, index) { + if (['summary', 'policies'].includes(step.key)) { + return null; } - var citationCallout = /*#__PURE__*/_react.default.createElement(_Card.default, { - style: { - margin: _Theme.default.spacing(0.5, 0, 3, 0) + var isComplete = state.requiredSteps[index].isComplete; + return /*#__PURE__*/_react.default.createElement("div", { + key: step.key, + className: classes.stepSummary + }, /*#__PURE__*/_react.default.createElement("div", { + role: "button", + tabIndex: 0, + className: classes.stepSummaryHeader, + onClick: function onClick() { + return changeToStep(index); }, - "data-selenium": "download-data-dialog.step-form.summary.citation" - }, /*#__PURE__*/_react.default.createElement(_CardContent.default, null, /*#__PURE__*/_react.default.createElement(_DataProductCitation.default, { - showQuoteIcon: true, - productCode: citationProductCode, - release: citationRelease - }))); - return /*#__PURE__*/_react.default.createElement(_Grid.default, { - container: true, - spacing: 2, - alignItems: "flex-start" - }, /*#__PURE__*/_react.default.createElement(_Grid.default, { - item: true, - xs: 12, - md: 6 - }, stepSummary), /*#__PURE__*/_react.default.createElement(_Grid.default, { - item: true, - xs: 12, - md: 6 - }, downloadAndExploreCallout, fileNamingCallout, citationCallout)); + onKeyPress: function onKeyPress() { + return changeToStep(index); + } + }, /*#__PURE__*/_react.default.createElement(_Chip.default, { + color: isComplete ? 'primary' : 'default', + label: index + 1, + className: classes.summaryChip + }), /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "h6", + style: { + flexGrow: 1 + } + }, _DownloadDataContext.default.ALL_STEPS[step.key].label)), /*#__PURE__*/_react.default.createElement("div", { + className: classes.stepSummaryContent + }, isComplete ? renderStepSummary[step.key](classes, state) : /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "body2", + className: classes.summaryTextIncomplete + }, "Incomplete"))); + }), /*#__PURE__*/_react.default.createElement("div", { + key: "download", + className: classes.stepSummary + }, renderDownloadButton())); + var downloadAndExploreLink = /*#__PURE__*/_react.default.createElement(_Link.default, { + target: "_blank", + href: _RouteService.default.getDownloadExplorePath(), + "data-gtm": "download-data-dialog.download-and-explore-link" + }, "Download and Explore NEON Data"); + var downloadAndExploreCallout = /*#__PURE__*/_react.default.createElement(_Card.default, { + style: { + margin: _Theme.default.spacing(0.5, 0, 3, 0) + }, + "data-selenium": "download-data-dialog.step-form.summary.download-and-explore" + }, /*#__PURE__*/_react.default.createElement(_CardContent.default, { + className: classes.startFlex + }, /*#__PURE__*/_react.default.createElement(_Explore.default, { + fontSize: "large", + className: classes.calloutIcon + }), /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "subtitle2" + }, "Tip: Check out our ", downloadAndExploreLink, " tutorial. This tutorial will explain how our neonUtilities package can be used to unzip and join data tables with just a few lines of code."))); + var fileNamingConventionsLink = /*#__PURE__*/_react.default.createElement(_Link.default, { + target: "_blank", + href: _RouteService.default.getFileNamingConventionsPath(), + "data-gtm": "download-data-dialog.file-naming-conventions-link" + }, "NEON File Naming Conventions"); + var fileNamingCallout = /*#__PURE__*/_react.default.createElement(_Card.default, { + style: { + margin: _Theme.default.spacing(0.5, 0, 3, 0) + }, + "data-selenium": "download-data-dialog.step-form.summary.file-naming" + }, /*#__PURE__*/_react.default.createElement(_CardContent.default, { + className: classes.startFlex + }, /*#__PURE__*/_react.default.createElement(_Description.default, { + fontSize: "large", + className: classes.calloutIcon + }), /*#__PURE__*/_react.default.createElement(_Typography.default, { + variant: "subtitle2" + }, "Files in this download will follow ", fileNamingConventionsLink, "."))); + var citationProductCode = ''; + var citationRelease; + if ((0, _typeUtil.exists)(state.productData) && (0, _typeUtil.isStringNonEmpty)(state.productData.productCode)) { + citationProductCode = state.productData.productCode; + } + if ((0, _typeUtil.exists)(state.release) && (0, _typeUtil.isStringNonEmpty)(state.release.value)) { + citationRelease = state.release.value; + } + var citationCallout = /*#__PURE__*/_react.default.createElement(_Card.default, { + style: { + margin: _Theme.default.spacing(0.5, 0, 3, 0) + }, + "data-selenium": "download-data-dialog.step-form.summary.citation" + }, /*#__PURE__*/_react.default.createElement(_CardContent.default, null, /*#__PURE__*/_react.default.createElement(_DataProductCitation.default, { + showQuoteIcon: true, + productCode: citationProductCode, + release: citationRelease + }))); + return /*#__PURE__*/_react.default.createElement(_Grid.default, { + container: true, + spacing: 2, + alignItems: "flex-start" + }, /*#__PURE__*/_react.default.createElement(_Grid.default, { + item: true, + xs: 12, + md: 6 + }, stepSummary), /*#__PURE__*/_react.default.createElement(_Grid.default, { + item: true, + xs: 12, + md: 6 + }, downloadAndExploreCallout, fileNamingCallout, citationCallout)); + }; + var renderStepForm = function renderStepForm() { + switch (stepKey) { + case 'sitesAndDateRange': + return renderSitesAndDateRangeStep(); + case 'documentation': + return renderDocumentationStep(); + case 'provisionalData': + return renderProvisionalDataStep(); + case 's3Files': + return renderS3FilesStep(); + case 'packageType': + return renderPackageTypeStep(); + case 'externalExclusive': + return renderExternalExclusiveStep(); + case 'policies': + return renderPoliciesStep(); + case 'summary': + return renderSummaryStep(); + default: + return null; } }; - return renderStepForm[stepKey] ? renderStepForm[stepKey]() : null; -} + return renderStepForm(); +}; DownloadStepForm.propTypes = { stepKey: _propTypes.default.oneOf(Object.keys(_DownloadDataContext.default.ALL_STEPS)).isRequired, changeToStep: _propTypes.default.func, @@ -959,4 +1006,6 @@ DownloadStepForm.defaultProps = { renderDownloadButton: function renderDownloadButton() { return null; } -}; \ No newline at end of file +}; +var _default = DownloadStepForm; +exports.default = _default; \ No newline at end of file diff --git a/lib/remoteAssets/drupal-header.html.d.ts b/lib/remoteAssets/drupal-header.html.d.ts index 0daccb8f..3a2c31d8 100644 --- a/lib/remoteAssets/drupal-header.html.d.ts +++ b/lib/remoteAssets/drupal-header.html.d.ts @@ -1,2 +1,2 @@ -declare const _default: "\n
\n
\n \n \n \n
\n \n\n
\n
\n
\n
\n \n \n \n\n\n \n\n
\n
\n \n
\n
\n

Search

\n \n\n
\n \n \n
\n
\n \n\n \n
\n
\n\n\n
\n\n
\n\n
\n\n
\n \n\n
\n
\n
\n
\n
\n\n\n"; +declare const _default: "\n
\n
\n \n \n \n
\n \n\n
\n
\n
\n
\n \n \n \n\n\n \n\n
\n
\n \n
\n
\n

Search

\n \n\n
\n \n \n
\n
\n \n\n \n
\n
\n\n\n
\n\n
\n\n
\n\n
\n \n\n
\n
\n
\n
\n
\n\n\n"; export default _default; diff --git a/lib/remoteAssets/drupal-header.html.js b/lib/remoteAssets/drupal-header.html.js index 24b853ac..e0cb9629 100644 --- a/lib/remoteAssets/drupal-header.html.js +++ b/lib/remoteAssets/drupal-header.html.js @@ -5,5 +5,5 @@ Object.defineProperty(exports, "__esModule", { }); exports.default = void 0; var html; -var _default = html = "\n
\n
\n \n \n \n
\n \n\n
\n
\n
\n
\n \n \n \n\n\n \n\n
\n
\n \n
\n
\n

Search

\n \n\n
\n \n \n
\n
\n \n\n \n
\n
\n\n\n
\n\n
\n\n
\n\n
\n \n\n
\n
\n
\n
\n
\n\n\n"; +var _default = html = "\n
\n
\n \n \n \n
\n \n\n
\n
\n
\n
\n \n \n \n\n\n \n\n
\n
\n \n
\n
\n

Search

\n \n\n
\n \n \n
\n
\n \n\n \n
\n
\n\n\n
\n\n
\n\n
\n\n
\n \n\n
\n
\n
\n
\n
\n\n\n"; exports.default = _default; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index d3ad3788..98c58774 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "portal-core-components", - "version": "2.5.1", + "version": "2.5.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "portal-core-components", - "version": "2.5.1", + "version": "2.5.2", "dependencies": { "@date-io/moment": "^1.3.13", "@fortawesome/fontawesome-svg-core": "^6.4.0", diff --git a/package.json b/package.json index 87500714..d5dcddbc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "portal-core-components", - "version": "2.5.1", + "version": "2.5.2", "main": "./lib/index.js", "private": true, "homepage": "http://localhost:3010/core-components", diff --git a/src/lib_components/components/DownloadDataContext/DownloadDataContext.jsx b/src/lib_components/components/DownloadDataContext/DownloadDataContext.jsx index 6fd17fdd..d4e92dad 100644 --- a/src/lib_components/components/DownloadDataContext/DownloadDataContext.jsx +++ b/src/lib_components/components/DownloadDataContext/DownloadDataContext.jsx @@ -123,7 +123,9 @@ const DEFAULT_STATE = { s3FileFetches: {}, // Where we keep individual fetch status for each site+yearMonth s3FileFetchProgress: 0, // Number to track progress of batch fetches for s3 files s3Files: { + maxNumFilesSelected: 60_000, value: [], + valueMap: {}, cachedValues: [], // Where all fetched file records are cached validValues: [], // Subset of cached values in scope of current sites and date range values isValid: false, @@ -304,7 +306,7 @@ const newStateIsAllowable = (key, value) => { // to be used in building a download manifest. const newStateIsValid = (key, value, validValues = []) => { if (!VALIDATABLE_STATE_KEYS.includes(key)) { return false; } - let idList = []; + const idList = {}; switch (key) { case 'sites': return ( @@ -327,11 +329,13 @@ const newStateIsValid = (key, value, validValues = []) => { typeof f === 'object' && f !== null && typeof f.url === 'string' && f.url.length )) ) { return false; } - idList = validValues.map((fileObj) => fileObj.url); + validValues.forEach((fileObj) => { + idList[fileObj.url] = true; + }); return ( newStateIsAllowable(key, value) && value.length > 0 - && value.every((id) => idList.includes(id)) + && value.every((id) => idList[id] || false) ); default: return ( @@ -548,14 +552,50 @@ const getInitialStateFromProps = (props) => { return initialState; }; -const getS3FilesFilteredFileCount = (state) => state.s3Files.validValues.filter((row) => ( - Object.keys(state.s3Files.filters).every((col) => { +const getS3FilesFilterFunction = (state) => (row) => { + let allowValue = true; + const hasProvisionalDataStep = state.requiredSteps.some((step) => ( + (step.key === 'provisionalData') + )); + const excludeProvisionalData = hasProvisionalDataStep + && (state.provisionalData.value === 'exclude'); + if (excludeProvisionalData) { + allowValue = isStringNonEmpty(row.release) && !ReleaseService.isNonRelease(row.release); + } + const matchesFilters = Object.keys(state.s3Files.filters).every((col) => { if (col === 'name') { return (!state.s3Files.filters.name.length || row.name.includes(state.s3Files.filters.name)); } return (!state.s3Files.filters[col].length || state.s3Files.filters[col].includes(row[col])); - }) -)).length; + }); + return matchesFilters && allowValue; +}; + +const getS3FilesFilteredFileCount = (state) => { + const filtered = state.s3Files.validValues.filter(getS3FilesFilterFunction(state)); + return filtered.length; +}; + +const calcS3FilesSummaryState = (previousState, action) => { + const newState = { ...previousState }; + const s3FilesIdx = newState.requiredSteps.findIndex((step) => step.key === 's3Files'); + // If we didn't already update the total size then recalculate it + if (action.type !== 'setIndividualS3FileSelected') { + newState.s3Files.totalSize = newState.s3Files.value + .map((id) => newState.s3Files.bytesByUrl[id]) + .reduce((a, b) => a + b, 0); + } + // Step is only complete when there's a selection that's not too big + newState.s3Files.estimatedPostSize = estimatePostSize(newState.s3Files, newState.sites); + newState.s3Files.isValid = ( + newState.s3Files.value.length > 0 + && newState.s3Files.estimatedPostSize < MAX_POST_BODY_SIZE + ); + newState.requiredSteps[s3FilesIdx].isComplete = newState.s3Files.isValid; + newState.allStepsComplete = newState.requiredSteps + .every((step) => step.isComplete || step.isComplete === null); + return newState; +}; // Generate a new full state object with a new value and isValid boolean for the // s3Files key. This is separate from other keys supported by getAndValidateNewState @@ -574,6 +614,12 @@ const getAndValidateNewS3FilesState = (previousState, action, broadcast = false) return newState; } newState.s3Files.value = action.value; + newState.s3Files.valueMap = {}; + if (existsNonEmpty(newState.s3Files.value)) { + newState.s3Files.value.forEach((value) => { + newState.s3Files.valueMap[value] = true; + }); + } break; case 'setValidatableValue': @@ -581,13 +627,25 @@ const getAndValidateNewS3FilesState = (previousState, action, broadcast = false) return newState; } newState.s3Files.value = action.value; + newState.s3Files.valueMap = {}; + if (existsNonEmpty(newState.s3Files.value)) { + newState.s3Files.value.forEach((value) => { + newState.s3Files.valueMap[value] = true; + }); + } newState.s3Files.validValues.forEach((file, idx) => { - newState.s3Files.validValues[idx].tableData.checked = newState.s3Files.value.includes(file.url); + newState.s3Files.validValues[idx].tableData.checked = newState.s3Files.valueMap[file.url] || false; }); break; case 'setS3FilesValueSelectAll': newState.s3Files.value = newState.s3Files.validValues.map((file) => file.url); + newState.s3Files.valueMap = {}; + if (existsNonEmpty(newState.s3Files.value)) { + newState.s3Files.value.forEach((value) => { + newState.s3Files.valueMap[value] = true; + }); + } newState.s3Files.validValues.forEach((file, idx) => { newState.s3Files.validValues[idx].tableData.checked = true; }); @@ -595,6 +653,7 @@ const getAndValidateNewS3FilesState = (previousState, action, broadcast = false) case 'setS3FilesValueSelectNone': newState.s3Files.value = []; + newState.s3Files.valueMap = {}; newState.s3Files.validValues.forEach((file, idx) => { newState.s3Files.validValues[idx].tableData.checked = false; }); @@ -602,15 +661,16 @@ const getAndValidateNewS3FilesState = (previousState, action, broadcast = false) case 'setS3FilesValueSelectFiltered': newState.s3Files.value = newState.s3Files.validValues - .filter((row) => Object.keys(newState.s3Files.filters).every((col) => { - if (col === 'name') { - return (!newState.s3Files.filters.name.length || row.name.includes(newState.s3Files.filters.name)); // eslint-disable-line max-len - } - return (!newState.s3Files.filters[col].length || newState.s3Files.filters[col].includes(row[col])); // eslint-disable-line max-len - })) + .filter(getS3FilesFilterFunction(newState)) .map((file) => file.url); + newState.s3Files.valueMap = {}; + if (existsNonEmpty(newState.s3Files.value)) { + newState.s3Files.value.forEach((value) => { + newState.s3Files.valueMap[value] = true; + }); + } newState.s3Files.validValues.forEach((file, idx) => { - newState.s3Files.validValues[idx].tableData.checked = newState.s3Files.value.includes(file.url); // eslint-disable-line max-len + newState.s3Files.validValues[idx].tableData.checked = newState.s3Files.valueMap[file.url] || false; // eslint-disable-line max-len }); break; @@ -622,10 +682,12 @@ const getAndValidateNewS3FilesState = (previousState, action, broadcast = false) // just add/subtract the size of the file specified if (action.selected) { newState.s3Files.value.push(action.url); + newState.s3Files.valueMap[action.url] = true; newState.s3Files.totalSize += newState.s3Files.bytesByUrl[action.url]; } else { if (newState.s3Files.value.indexOf(action.url) === -1) { return newState; } newState.s3Files.value.splice(newState.s3Files.value.indexOf(action.url), 1); + delete newState.s3Files.valueMap[action.url]; newState.s3Files.totalSize -= newState.s3Files.bytesByUrl[action.url]; } break; @@ -633,25 +695,7 @@ const getAndValidateNewS3FilesState = (previousState, action, broadcast = false) default: return newState; } - - // If we didn't already update the total size then recalculate it - if (action.type !== 'setIndividualS3FileSelected') { - newState.s3Files.totalSize = newState.s3Files.value - .map((id) => newState.s3Files.bytesByUrl[id]) - .reduce((a, b) => a + b, 0); - } - - // Step is only complete when there's a selection that's not too big - newState.s3Files.estimatedPostSize = estimatePostSize(newState.s3Files, newState.sites); - newState.s3Files.isValid = ( - newState.s3Files.value.length > 0 - && newState.s3Files.estimatedPostSize < MAX_POST_BODY_SIZE - ); - newState.requiredSteps[s3FilesIdx].isComplete = newState.s3Files.isValid; - newState.allStepsComplete = newState.requiredSteps - .every((step) => step.isComplete || step.isComplete === null); - - return newState; + return calcS3FilesSummaryState(newState, action); }; // Generate new s3Files.validValues and s3Files filter values in state. @@ -696,26 +740,24 @@ const regenerateS3FilesFiltersAndValidValues = (state) => { )) .map((file) => ({ ...file, - tableData: { checked: updated.s3Files.value.includes(file.url) }, + tableData: { checked: updated.s3Files.valueMap[file.url] || false }, })); // If cachedValues and validValues differ in size then rebuild valueLookups for // filters, adjust filter selections to suit, and regenerate filtered file count. const filterKeys = Object.keys(updated.s3Files.valueLookups || {}); - if (updated.s3Files.validValues.length < updated.s3Files.cachedValues.length) { - filterKeys.forEach((key) => { - updated.s3Files.valueLookups[key] = {}; - }); - updated.s3Files.validValues.forEach((file) => { - filterKeys.forEach((lookup) => { - if (typeof file[lookup] === 'undefined') { return; } - updated.s3Files.valueLookups[lookup][file[lookup]] = file[lookup] || '(none)'; - }); - }); - filterKeys.forEach((key) => { - updated.s3Files.filters[key] = updated.s3Files.filters[key] - .filter((filterVal) => Object.keys(updated.s3Files.valueLookups[key]).includes(filterVal)); + filterKeys.forEach((key) => { + updated.s3Files.valueLookups[key] = {}; + }); + updated.s3Files.validValues.forEach((file) => { + filterKeys.forEach((lookup) => { + if (typeof file[lookup] === 'undefined') { return; } + updated.s3Files.valueLookups[lookup][file[lookup]] = file[lookup] || '(none)'; }); - } + }); + filterKeys.forEach((key) => { + updated.s3Files.filters[key] = updated.s3Files.filters[key] + .filter((filterVal) => Object.keys(updated.s3Files.valueLookups[key]).includes(filterVal)); + }); updated.s3Files.filteredFileCount = getS3FilesFilteredFileCount(updated); // Create an action to send to the reducer helper to set an updated value and revalidate. const action = { @@ -744,7 +786,7 @@ const getAndValidateNewState = (previousState, action, broadcast = false) => { if (action.key === 's3Files') { return getAndValidateNewS3FilesState(previousState, action, broadcast); } - const newState = { ...previousState, broadcast }; + let newState = { ...previousState, broadcast }; const valueIsValid = newStateIsValid( action.key, action.value, @@ -755,6 +797,39 @@ const getAndValidateNewState = (previousState, action, broadcast = false) => { value: action.value, isValid: valueIsValid, }; + const hasProvDataStep = newState.requiredSteps.some((step) => step.key === 'provisionalData'); + const hasS3FilesStep = newState.requiredSteps.some((step) => step.key === 's3Files'); + if (hasProvDataStep + && hasS3FilesStep + && (action.key === 'provisionalData') + ) { + if (action.value === 'exclude') { + // Go through validValues, uncheck any provisional when set to exclude + if (existsNonEmpty(newState.s3Files.validValues)) { + newState.s3Files.value = []; + newState.s3Files.valueMap = {}; + newState.s3Files.validValues = newState.s3Files.validValues.map((value) => { + const isProv = ReleaseService.isProv(value.release); + if (isProv) { + return { + ...value, + tableData: { + ...value.tableData, + checked: false, + }, + }; + } + if (value.tableData.checked) { + newState.s3Files.value.push(value.url); + newState.s3Files.valueMap[value.url] = true; + } + return value; + }); + newState = calcS3FilesSummaryState(newState, action); + } + } + newState.s3Files.filteredFileCount = getS3FilesFilteredFileCount(newState); + } newState.requiredSteps = previousState.requiredSteps.map((step) => { const requiredStateKeys = ALL_STEPS[step.key] ? ALL_STEPS[step.key].requiredStateKeys : []; return step.isComplete === null diff --git a/src/lib_components/components/DownloadStepForm/DownloadStepForm.jsx b/src/lib_components/components/DownloadStepForm/DownloadStepForm.jsx index 97b16edc..4f260228 100644 --- a/src/lib_components/components/DownloadStepForm/DownloadStepForm.jsx +++ b/src/lib_components/components/DownloadStepForm/DownloadStepForm.jsx @@ -146,7 +146,55 @@ const dataUsageAndCitationPoliciesLink = ( ); -export default function DownloadStepForm(props) { +const renderStepSummary = { + sitesAndDateRange: (classes, state) => { + const { value: sites } = state.sites; + const { value: dateRange } = state.dateRange; + const sitesPlural = sites.length > 1 ? 's' : ''; + const getYearMonthMoment = (yearMonth) => moment(`${yearMonth}-01`); + const startDateRange = `${getYearMonthMoment(dateRange[0]).format('MMM YYYY')}`; + const endDateRange = `${getYearMonthMoment(dateRange[1]).format('MMM YYYY')}`; + const humanDateRange = `${startDateRange} - ${endDateRange}`; + const siteChipLabel = `${sites.length} site${sitesPlural} — ${humanDateRange}`; + return ( + + ); + }, + documentation: (classes, state) => { + const { value: documentation } = state.documentation; + return ( + + {`${documentation.charAt(0).toUpperCase()}${documentation.substring(1)}`} + + ); + }, + packageType: (classes, state) => { + const { value: packageType } = state.packageType; + return ( + + {`${packageType.charAt(0).toUpperCase()}${packageType.substring(1)}`} + + ); + }, + provisionalData: (classes, state) => { + const { value: provisionalData } = state.provisionalData; + return ( + + {`${provisionalData.charAt(0).toUpperCase()}${provisionalData.substring(1)}`} + + ); + }, + s3Files: (classes, state) => { + const { value: files, totalSize } = state.s3Files; + return ( + + {`${files.length} file${files.length === 1 ? '' : 's'} (${formatBytes(totalSize)} uncompressed)`} + + ); + }, +}; + +const DownloadStepForm = (props) => { const classes = useStyles(Theme); const { @@ -175,822 +223,803 @@ export default function DownloadStepForm(props) { value: newValue, }); - const renderStepSummary = { - sitesAndDateRange: () => { - const { value: sites } = state.sites; - const { value: dateRange } = state.dateRange; - const sitesPlural = sites.length > 1 ? 's' : ''; - const getYearMonthMoment = (yearMonth) => moment(`${yearMonth}-01`); - const humanDateRange = `${getYearMonthMoment(dateRange[0]).format('MMM YYYY')} - ${getYearMonthMoment(dateRange[1]).format('MMM YYYY')}`; - const siteChipLabel = `${sites.length} site${sitesPlural} — ${humanDateRange}`; - return ( - - ); - }, - documentation: () => { - const { value: documentation } = state.documentation; - return ( - - {`${documentation.charAt(0).toUpperCase()}${documentation.substring(1)}`} - - ); - }, - packageType: () => { - const { value: packageType } = state.packageType; - return ( - - {`${packageType.charAt(0).toUpperCase()}${packageType.substring(1)}`} - - ); - }, - provisionalData: () => { - const { value: provisionalData } = state.provisionalData; - return ( - - {`${provisionalData.charAt(0).toUpperCase()}${provisionalData.substring(1)}`} - - ); - }, - s3Files: () => { - const { value: files, totalSize } = state.s3Files; - return ( - - {`${files.length} file${files.length === 1 ? '' : 's'} (${formatBytes(totalSize)} uncompressed)`} - - ); - }, - }; - - const renderStepForm = { - /** - SITES AND DATE RANGE - */ - sitesAndDateRange: () => { - const { requiredSteps, provisionalData } = state; - const hasProvisionalDataStep = requiredSteps.some((step) => ( - (step.key === 'provisionalData') - )); - const excludeProvisionalData = hasProvisionalDataStep && (provisionalData.value === 'exclude'); - return ( - <> - {!excludeProvisionalData ? null : ( - - Provisional data are currently being excluded from the download package. - To make those data available, include those data from within the - Provisional Data step. - - )} - /> - )} - { + const { requiredSteps, provisionalData } = state; + const hasProvisionalDataStep = requiredSteps.some((step) => ( + (step.key === 'provisionalData') + )); + const excludeProvisionalData = hasProvisionalDataStep && (provisionalData.value === 'exclude'); + return ( + <> + {!excludeProvisionalData ? null : ( + + Provisional data are currently being excluded from the download package. + To make those data available, include those data from within the + Provisional Data step. + + )} /> - - ); - }, + )} + + + ); + }; - /** - DOCUMENTATION - */ - documentation: () => { - const neonFaqLink = ( - - NEON FAQ - - ); - const knbLink = ExternalHost.renderExternalHostLink( - 'https://eml.ecoinformatics.org', - 'KNB', - 'KNB', - state.productData.productCode, - ); - const { value, validValues } = state.documentation; - return ( - - - - { - setState('documentation', e.target.value); - changeToNextUncompletedStep(); - }} - > - } - label={( -
- Include - - Include relevant documents for this Data Product - -
- )} - /> - } - label={( -
- Exclude - - Data only, no relevant documents for this Data Product - -
- )} - /> -
-
-
- - - - - - {/* eslint-disable react/jsx-one-expression-per-line */} - EML files for this Data Product are included in all downloads. - Learn more about EML files in the {neonFaqLink} and at {knbLink}. - {/* eslint-enable react/jsx-one-expression-per-line */} - - - - + const renderDocumentationStep = () => { + const neonFaqLink = ( + + NEON FAQ + + ); + const knbLink = ExternalHost.renderExternalHostLink( + 'https://eml.ecoinformatics.org', + 'KNB', + 'KNB', + state.productData.productCode, + ); + const { value, validValues } = state.documentation; + return ( + + + + { + setState('documentation', e.target.value); + changeToNextUncompletedStep(); + }} + > + } + label={( +
+ Include + + Include relevant documents for this Data Product + +
+ )} + /> + } + label={( +
+ Exclude + + Data only, no relevant documents for this Data Product + +
+ )} + /> +
+
- ); - }, - - /** - PROVISIONAL DATA - */ - provisionalData: () => { - const neonDataRevisionReleaseLink = ( - - NEON Data Revisions and Releases - - ); - const { value, validValues } = state.provisionalData; - return ( - - - - { - setState('provisionalData', e.target.value); - changeToNextUncompletedStep(); - }} - > - } - label={( -
- Include - - {/* eslint-disable react/jsx-one-expression-per-line */} - Include provisional data in this download package - (Warning: subject to change and not reproducible) - {/* eslint-enable react/jsx-one-expression-per-line */} - -
- )} - /> - } - label={( -
- Exclude - - Release data only, no provisional data included in this download package - -
- )} - /> -
-
-
- - - - - - {/* eslint-disable react/jsx-one-expression-per-line */} - Learn more about data product revisions, releases and provisional data - at the {neonDataRevisionReleaseLink} page. - {/* eslint-enable react/jsx-one-expression-per-line */} - - - - + + + + + + {/* eslint-disable react/jsx-one-expression-per-line */} + EML files for this Data Product are included in all downloads. + Learn more about EML files in the {neonFaqLink} and at {knbLink}. + {/* eslint-enable react/jsx-one-expression-per-line */} + + + - ); - }, +
+ ); + }; - /** - S3 Files - */ - s3Files: () => { - const { - s3FileFetches, - s3FileFetchProgress, - requiredSteps, - provisionalData, - } = state; - const { - value: selection, - validValues, - valueLookups, - totalSize, - estimatedPostSize, - filters, - filteredFileCount, - visibleColumns, - } = state.s3Files; - const isLoading = Object.keys(s3FileFetches) - .some((key) => ['awaitingFetchCall', 'fetching'].includes(s3FileFetches[key])); - const hasProvisionalDataStep = requiredSteps.some((step) => ( - (step.key === 'provisionalData') - )); - const excludeProvisionalData = hasProvisionalDataStep && (provisionalData.value === 'exclude'); - let appliedValidValues = validValues; - let areProvDataExcluded = false; - if (excludeProvisionalData) { - appliedValidValues = appliedValidValues.filter((value) => { - const includeValue = isStringNonEmpty(value.release) - && !ReleaseService.isNonRelease(value.release); - if (!includeValue) { - areProvDataExcluded = true; - } - return includeValue; - }); - } - const columns = [ - { - title: 'Site', - field: 'site', - lookup: valueLookups.site, - defaultFilter: filters.site || [], - hidden: !visibleColumns.includes('site'), - }, - { - title: 'Date', - field: 'yearMonth', - lookup: valueLookups.yearMonth, - defaultFilter: filters.yearMonth || [], - hidden: !visibleColumns.includes('date'), - }, - { - title: 'Visit', - field: 'visit', - lookup: valueLookups.visit, - defaultFilter: filters.visit || [], - hidden: !visibleColumns.includes('visit'), - }, - { - title: 'Name', - field: 'name', - defaultFilter: filters.name || '', - hidden: !visibleColumns.includes('name'), - }, - { - title: 'Type', - field: 'type', - lookup: valueLookups.type, - defaultFilter: filters.type || [], - hidden: !visibleColumns.includes('type'), - }, - { - title: 'Size', - field: 'size', - filtering: false, - removable: false, - render: (row) => formatBytes(row.size), - }, - ]; - const debouncedFilterDispatch = debounce((filter, value) => { - dispatch({ type: 'setS3FilesFilterValue', filter, value }); - }, 200); - const noFiltersApplied = Object.keys(filters).every((col) => !filters[col].length); - /* eslint-disable react/jsx-one-expression-per-line */ - const postSizeError = (estimatedPostSize >= MAX_POST_BODY_SIZE) ? ( - - - - { + const neonDataRevisionReleaseLink = ( + + NEON Data Revisions and Releases + + ); + const { value, validValues } = state.provisionalData; + return ( + + + + { + setState('provisionalData', e.target.value); + changeToNextUncompletedStep(); + }} + > + } + label={( +
+ Include + + {/* eslint-disable react/jsx-one-expression-per-line */} + Include provisional data in this download package + (Warning: subject to change and not reproducible) + {/* eslint-enable react/jsx-one-expression-per-line */} + +
+ )} + /> + } + label={( +
+ Exclude + + Release data only, no provisional data included in this download package + +
+ )} /> +
+
+
+ + + + - Too many files requested! Current selection will make an - estimated {formatBytes(estimatedPostSize)} request; max - size is {formatBytes(MAX_POST_BODY_SIZE)}. - Please select fewer files in order to proceed. + {/* eslint-disable react/jsx-one-expression-per-line */} + Learn more about data product revisions, releases and provisional data + at {neonDataRevisionReleaseLink}. + {/* eslint-enable react/jsx-one-expression-per-line */} - ) : null; - const components = { - Container: Box, - Toolbar: (toolbarProps) => ( - - -
- dispatch({ - type: 'setS3FilesVisibleColumns', - visibleColumns: newVisibleColumns, - })} - aria-label="show and hide columns" - data-selenium="download-data-dialog.s3-files.show-hide-columns-button-group" - > - - Show Columns: - - - Site - - - Visit - - - Date - - - Name - - - Type - - -
-
- - -
-
- - -
-
- - - - {postSizeError} -
- ), - FilterRow: (filterRowProps) => ( - { - const { onFilterChanged } = filterRowProps; - onFilterChanged(columnId, value); - const filter = columns[columnId].field; - const current = filters[filter]; - if (filter === 'name' && value !== current) { - debouncedFilterDispatch(filter, value); - return; - } - if ( - current - && (value.length !== current.length || value.some((v) => !current.includes(v))) - ) { - dispatch({ type: 'setS3FilesFilterValue', filter, value }); - } - }} - /> - ), - }; - /* eslint-enable react/jsx-one-expression-per-line */ - const localization = { - pagination: { - labelRowsSelect: 'files', - }, - toolbar: { - nRowsSelected: `{0} file${selection.length === 1 ? '' : 's'} selected (${formatBytes(totalSize)} uncompressed)`, - }, - body: { - emptyDataSourceMessage: 'No files to display. Select more sites, broaden date range, or broaden search / filters.', - }, - }; - return (appliedValidValues.length || isLoading) ? ( -
- { - dispatch({ - type: 'setIndividualS3FileSelected', - url: file.url, - selected: file.tableData.checked, - }); - }} - /> -
- - {`Loading files (${Math.floor(s3FileFetchProgress || 0)}%)...`} - - -
-
- ) : ( - <> - {!excludeProvisionalData || !areProvDataExcluded ? null : ( - - Provisional data are currently being excluded from selection. - To make those data available for selection, include those data from within the - Provisional Data step. - - )} - /> - )} - - Select sites and date range in order to generate a list of files to choose from. - - - ); - }, +
+ ); + }; - /** - PACKAGE TYPE - */ - packageType: () => { - const { value, validValues } = state.packageType; - let { productBasicDescription, productExpandedDescription } = state.productData; - if (!productBasicDescription) { - productBasicDescription = 'Includes the data product, summary statistics, expanded uncertainty, and final quality flag'; - } - if (!productExpandedDescription) { - productExpandedDescription = 'Includes the basic package information plus quality metrics for all of the quality assessment and quality control analysis'; - } - return ( - - { - setState('packageType', e.target.value); - changeToNextUncompletedStep(); - }} - > - } - label={( -
- Basic - - {productBasicDescription} - -
- )} + const renderS3FilesStep = () => { + const { + s3FileFetches, + s3FileFetchProgress, + requiredSteps, + provisionalData, + } = state; + const { + value: selection, + validValues, + valueLookups, + totalSize, + estimatedPostSize, + filters, + filteredFileCount, + visibleColumns, + maxNumFilesSelected, + } = state.s3Files; + const isLoading = Object.keys(s3FileFetches) + .some((key) => ['awaitingFetchCall', 'fetching'].includes(s3FileFetches[key])); + const hasProvisionalDataStep = requiredSteps.some((step) => ( + (step.key === 'provisionalData') + )); + const excludeProvisionalData = hasProvisionalDataStep && (provisionalData.value === 'exclude'); + let appliedValidValues = validValues; + let areProvDataExcluded = false; + if (excludeProvisionalData) { + appliedValidValues = appliedValidValues.filter((value) => { + const includeValue = isStringNonEmpty(value.release) + && !ReleaseService.isNonRelease(value.release); + if (!includeValue) { + areProvDataExcluded = true; + } + return includeValue; + }); + } + const allowSelectAll = (appliedValidValues.length <= maxNumFilesSelected); + const allowSelectFiltered = (filteredFileCount <= maxNumFilesSelected); + const columns = [ + { + title: 'Site', + field: 'site', + lookup: valueLookups.site, + defaultFilter: filters.site || [], + hidden: !visibleColumns.includes('site'), + render: (row) => row.site, + }, + { + title: 'Date', + field: 'yearMonth', + lookup: valueLookups.yearMonth, + defaultFilter: filters.yearMonth || [], + hidden: !visibleColumns.includes('date'), + render: (row) => row.yearMonth, + }, + { + title: 'Visit', + field: 'visit', + lookup: valueLookups.visit, + defaultFilter: filters.visit || [], + hidden: !visibleColumns.includes('visit'), + render: (row) => row.visit, + }, + { + title: 'Name', + field: 'name', + defaultFilter: filters.name || '', + hidden: !visibleColumns.includes('name'), + render: (row) => row.name, + }, + { + title: 'Type', + field: 'type', + lookup: valueLookups.type, + defaultFilter: filters.type || [], + hidden: !visibleColumns.includes('type'), + render: (row) => row.type, + }, + { + title: 'Size', + field: 'size', + filtering: false, + removable: false, + render: (row) => formatBytes(row.size), + }, + ]; + const debouncedFilterDispatch = debounce((filter, value) => { + dispatch({ type: 'setS3FilesFilterValue', filter, value }); + }, 200); + const noFiltersApplied = Object.keys(filters).every((col) => !filters[col].length); + /* eslint-disable react/jsx-one-expression-per-line */ + const postSizeError = (estimatedPostSize >= MAX_POST_BODY_SIZE) ? ( + + + + - } - label={( -
- Expanded - - {productExpandedDescription} - -
- )} - /> -
-
- ); - }, - - /** - EXTERNAL LINKS - EXCLUSIVE HOSTING - */ - externalExclusive: () => { - const externalHost = ExternalHost.getByProductCode(state.productData.productCode); - if (!externalHost) { return null; } - const hostLink = externalHost.renderLink(state.productData.productCode); - const availableSiteCodes = (state.productData.siteCodes || []).map((site) => site.siteCode); - const externalHostProduct = ExternalHost.getProductSpecificInfo( - state.productData.productCode, - ); - const allowNoAvailability = exists(externalHostProduct) - && (externalHostProduct.allowNoAvailability === true); - const noData = !existsNonEmpty(availableSiteCodes); - const noLinks = allowNoAvailability && noData; - let blurb; - if (noLinks) { - blurb = ( - <> - {/* eslint-disable react/jsx-one-expression-per-line */} - Data for this product is not currently available for download through - the NEON Data Portal. Please use this link to access data for - this product for a particular site from {hostLink}. - {/* eslint-enable react/jsx-one-expression-per-line */} - - ); - } else { - blurb = ( - <> - {/* eslint-disable react/jsx-one-expression-per-line */} - Data for this product is not currently available for download through - the NEON Data Portal. Please use the links below to access data for - this product for a particular site from the {hostLink}. - {/* eslint-enable react/jsx-one-expression-per-line */} - - ); - } - return ( -
- - {blurb} - - )} - /> - {noLinks ? null : ( - + Too many files requested! Current selection will make an + estimated {formatBytes(estimatedPostSize)} request; max + size is {formatBytes(MAX_POST_BODY_SIZE)}. + Please select fewer files in order to proceed. + + + + + ) : null; + /* eslint-disable react/jsx-one-expression-per-line */ + const tooManyFilesWarning = (!allowSelectAll && !allowSelectFiltered) ? ( + + + + + + Too many files available for bulk selection. + Please narrow your selection by selecting fewer sites, + a more restrictive date range, or a more restrictive set of filters. + + + + + ) : null; + const filterButtonLoadingLabel = ` (${isLoading ? '…' : filteredFileCount})`; + const filterButtonLabel = noFiltersApplied ? '' : filterButtonLoadingLabel; + const components = { + Container: Box, + Toolbar: (toolbarProps) => ( + + +
+ dispatch({ + type: 'setS3FilesVisibleColumns', + visibleColumns: newVisibleColumns, + })} + aria-label="show and hide columns" + data-selenium="download-data-dialog.s3-files.show-hide-columns-button-group" + > + + Show Columns: + + + Site + + + Visit + + + Date + + + Name + + + Type + + +
+
+ + +
+
+ + +
+
+ + + + {postSizeError} + {tooManyFilesWarning} + {!excludeProvisionalData || !areProvDataExcluded ? null : ( +
+ + Provisional data are currently being excluded from selection. + To make those data available for selection, include those data from within the + Provisional Data step. + + )} + /> +
)} +
+ ), + FilterRow: (filterRowProps) => ( + { + const { onFilterChanged } = filterRowProps; + onFilterChanged(columnId, value); + const filter = columns[columnId].field; + const current = filters[filter]; + if (filter === 'name' && value !== current) { + debouncedFilterDispatch(filter, value); + return; + } + if ( + current + && (value.length !== current.length || value.some((v) => !current.includes(v))) + ) { + dispatch({ type: 'setS3FilesFilterValue', filter, value }); + } + }} + /> + ), + }; + /* eslint-enable react/jsx-one-expression-per-line */ + const localization = { + pagination: { + labelRowsSelect: 'files', + }, + toolbar: { + nRowsSelected: `{0} file${selection.length === 1 ? '' : 's'} selected (${formatBytes(totalSize)} uncompressed)`, + }, + body: { + emptyDataSourceMessage: 'No files to display. Select more sites, broaden date range, or broaden search / filters.', + }, + }; + return (appliedValidValues.length || isLoading) ? ( +
+ { + dispatch({ + type: 'setIndividualS3FileSelected', + url: file.url, + selected: file.tableData.checked, + }); + }} + /> +
+ + {`Loading files (${Math.floor(s3FileFetchProgress || 0)}%)...`} + +
- ); - }, +
+ ) : ( + + Select sites and date range in order to generate a list of files to choose from. + + ); + }; - /** - POLICIES - */ - policies: () => { - const { value: agreed } = state.policies; - const checkbox = ( - { - setState('policies', true); + const renderPackageTypeStep = () => { + const { value, validValues } = state.packageType; + let { productBasicDescription, productExpandedDescription } = state.productData; + if (!productBasicDescription) { + productBasicDescription = 'Includes the data product, summary statistics, expanded uncertainty, and final quality flag'; + } + if (!productExpandedDescription) { + productExpandedDescription = 'Includes the basic package information plus quality metrics for all of the quality assessment and quality control analysis'; + } + return ( + + { + setState('packageType', e.target.value); changeToNextUncompletedStep(); }} - /> - ); - /* eslint-disable react/jsx-one-expression-per-line */ - return ( -
- - In order to proceed to download NEON data you must agree to - the {dataUsageAndCitationPoliciesLink}. - + > } + label={( +
+ Basic + + {productBasicDescription} + +
+ )} /> -
- ); - /* eslint-enable react/jsx-one-expression-per-line */ - }, - - /** - SUMMARY - */ - summary: () => { - const stepSummary = ( -
- {state.requiredSteps.map((step, index) => { - if (['summary', 'policies'].includes(step.key)) { return null; } - const { isComplete } = state.requiredSteps[index]; - return ( -
-
changeToStep(index)} - onKeyPress={() => changeToStep(index)} - > - - - {DownloadDataContext.ALL_STEPS[step.key].label} - -
-
- {isComplete ? renderStepSummary[step.key]() : ( - - Incomplete - - )} -
+ } + label={( +
+ Expanded + + {productExpandedDescription} +
- ); - })} -
- {renderDownloadButton()} -
-
- ); - const downloadAndExploreLink = ( - - Download and Explore NEON Data - - ); - const downloadAndExploreCallout = ( - - - - {/* eslint-disable react/jsx-one-expression-per-line */} - - Tip: Check out our {downloadAndExploreLink} tutorial. - This tutorial will explain how our neonUtilities package can - be used to unzip and join data tables with just a few lines of code. - - {/* eslint-enable react/jsx-one-expression-per-line */} - - + )} + /> + + + ); + }; + + const renderExternalExclusiveStep = () => { + const externalHost = ExternalHost.getByProductCode(state.productData.productCode); + if (!externalHost) { return null; } + const hostLink = externalHost.renderLink(state.productData.productCode); + const availableSiteCodes = (state.productData.siteCodes || []).map((site) => site.siteCode); + const externalHostProduct = ExternalHost.getProductSpecificInfo( + state.productData.productCode, + ); + const allowNoAvailability = exists(externalHostProduct) + && (externalHostProduct.allowNoAvailability === true); + const noData = !existsNonEmpty(availableSiteCodes); + const noLinks = allowNoAvailability && noData; + let blurb; + if (noLinks) { + blurb = ( + <> + {/* eslint-disable react/jsx-one-expression-per-line */} + Data for this product is not currently available for download through + the NEON Data Portal. Please use this link to access data for + this product for a particular site from {hostLink}. + {/* eslint-enable react/jsx-one-expression-per-line */} + ); - const fileNamingConventionsLink = ( - - NEON File Naming Conventions - + } else { + blurb = ( + <> + {/* eslint-disable react/jsx-one-expression-per-line */} + Data for this product is not currently available for download through + the NEON Data Portal. Please use the links below to access data for + this product for a particular site from the {hostLink}. + {/* eslint-enable react/jsx-one-expression-per-line */} + ); - const fileNamingCallout = ( - - - - {/* eslint-disable react/jsx-one-expression-per-line */} + } + return ( +
+ - Files in this download will follow {fileNamingConventionsLink}. + {blurb} - {/* eslint-enable react/jsx-one-expression-per-line */} - - - ); - let citationProductCode = ''; - let citationRelease; - if (state.productData && state.productData.productCode) { - citationProductCode = state.productData.productCode; - } - if (state.release && state.release.value) { - citationRelease = state.release.value; - } - const citationCallout = ( - - - - - - ); - return ( - - - {stepSummary} - - - {downloadAndExploreCallout} - {fileNamingCallout} - {citationCallout} - + )} + /> + {noLinks ? null : ( + + )} +
+ ); + }; + + const renderPoliciesStep = () => { + const { value: agreed } = state.policies; + const checkbox = ( + { + setState('policies', true); + changeToNextUncompletedStep(); + }} + /> + ); + /* eslint-disable react/jsx-one-expression-per-line */ + return ( +
+ + In order to proceed to download NEON data you must agree to + the {dataUsageAndCitationPoliciesLink}. + + +
+ ); + /* eslint-enable react/jsx-one-expression-per-line */ + }; + + const renderSummaryStep = () => { + const stepSummary = ( +
+ {state.requiredSteps.map((step, index) => { + if (['summary', 'policies'].includes(step.key)) { return null; } + const { isComplete } = state.requiredSteps[index]; + return ( +
+
changeToStep(index)} + onKeyPress={() => changeToStep(index)} + > + + + {DownloadDataContext.ALL_STEPS[step.key].label} + +
+
+ {isComplete ? renderStepSummary[step.key](classes, state) : ( + + Incomplete + + )} +
+
+ ); + })} +
+ {renderDownloadButton()} +
+
+ ); + const downloadAndExploreLink = ( + + Download and Explore NEON Data + + ); + const downloadAndExploreCallout = ( + + + + {/* eslint-disable react/jsx-one-expression-per-line */} + + Tip: Check out our {downloadAndExploreLink} tutorial. + This tutorial will explain how our neonUtilities package can + be used to unzip and join data tables with just a few lines of code. + + {/* eslint-enable react/jsx-one-expression-per-line */} + + + ); + const fileNamingConventionsLink = ( + + NEON File Naming Conventions + + ); + const fileNamingCallout = ( + + + + {/* eslint-disable react/jsx-one-expression-per-line */} + + Files in this download will follow {fileNamingConventionsLink}. + + {/* eslint-enable react/jsx-one-expression-per-line */} + + + ); + let citationProductCode = ''; + let citationRelease; + if (exists(state.productData) && isStringNonEmpty(state.productData.productCode)) { + citationProductCode = state.productData.productCode; + } + if (exists(state.release) && isStringNonEmpty(state.release.value)) { + citationRelease = state.release.value; + } + const citationCallout = ( + + + + + + ); + return ( + + + {stepSummary} - ); - }, + + {downloadAndExploreCallout} + {fileNamingCallout} + {citationCallout} + + + ); + }; + + const renderStepForm = () => { + switch (stepKey) { + case 'sitesAndDateRange': + return renderSitesAndDateRangeStep(); + case 'documentation': + return renderDocumentationStep(); + case 'provisionalData': + return renderProvisionalDataStep(); + case 's3Files': + return renderS3FilesStep(); + case 'packageType': + return renderPackageTypeStep(); + case 'externalExclusive': + return renderExternalExclusiveStep(); + case 'policies': + return renderPoliciesStep(); + case 'summary': + return renderSummaryStep(); + default: + return null; + } }; - return renderStepForm[stepKey] ? renderStepForm[stepKey]() : null; -} + return renderStepForm(); +}; DownloadStepForm.propTypes = { stepKey: PropTypes.oneOf(Object.keys(DownloadDataContext.ALL_STEPS)).isRequired, @@ -1004,3 +1033,5 @@ DownloadStepForm.defaultProps = { changeToNextUncompletedStep: () => {}, renderDownloadButton: () => null, }; + +export default DownloadStepForm; diff --git a/src/lib_components/components/DownloadStepForm/__tests__/__snapshots__/DownloadStepForm.jsx.snap b/src/lib_components/components/DownloadStepForm/__tests__/__snapshots__/DownloadStepForm.jsx.snap index 620780d4..829d26cc 100644 --- a/src/lib_components/components/DownloadStepForm/__tests__/__snapshots__/DownloadStepForm.jsx.snap +++ b/src/lib_components/components/DownloadStepForm/__tests__/__snapshots__/DownloadStepForm.jsx.snap @@ -678,7 +678,7 @@ exports[`DownloadStepForm Step provisionalData renders correctly 1`] = `

- Learn more about data product revisions, releases and provisional data at the + Learn more about data product revisions, releases and provisional data at NEON Data Revisions and Releases - page. + .

diff --git a/src/lib_components/remoteAssets/drupal-header.html.js b/src/lib_components/remoteAssets/drupal-header.html.js index 15572452..9ce806cf 100644 --- a/src/lib_components/remoteAssets/drupal-header.html.js +++ b/src/lib_components/remoteAssets/drupal-header.html.js @@ -28,7 +28,7 @@ export default html = `
-
+ diff --git a/src/sampleData/DP1.30010.001.json b/src/sampleData/DP1.30010.001.json index ee6bc5fa..c63e43d6 100644 --- a/src/sampleData/DP1.30010.001.json +++ b/src/sampleData/DP1.30010.001.json @@ -11,198 +11,350 @@ "productScienceTeamAbbr": "AOP", "productScienceTeam": "Airborne Observation Platform (AOP)", "productPublicationFormatType": "AOP Data Product Type", - "productAbstract": "The digital camera is part of a suite of instruments on the NEON Airborne Observation Platform (AOP) that also includes a full-waveform, small-footprint LiDAR system and the NEON Imaging Spectrometer. In the orthorectification process, the digital imagery is remapped to the same geographic projection as the LiDAR and imaging spectrometer data that is acquired simultaneously. The resulting images will share the same map projection grid space as the orthorectified spectrometer and LiDAR imagery. Since the digital camera imagery is acquired at higher spatial resolution than the imaging spectrometer data, it can aid in identifying features in the spectrometer images including manmade features (e.g., roads, fence lines, and buildings) that are indicative of land-use change. Level 1 RGB camera images are distributed as one camera frame per GeoTIFF file.\n\nLatency:\nAOP data will be available 60 days after the final collection day at a site. AOP legacy data (those collected in 2013 through 2016) currently has partial availability, and will be completely available by April of 2019.\n\n*Note: Data are being migrated to the data portal. If you don't find the data you are looking for (e.g., from specific sites or years), please request data [here](http://www.neonscience.org/request-airborne-data).", + "productAbstract": "The digital camera is part of a suite of instruments on the NEON Airborne Observation Platform (AOP) that also includes a full-waveform, small-footprint LiDAR system and the NEON Imaging Spectrometer. In the orthorectification process, the digital imagery is remapped to the same geographic projection as the LiDAR and imaging spectrometer data that is acquired simultaneously. The resulting images will share the same map projection grid space as the orthorectified spectrometer and LiDAR imagery. Since the digital camera imagery is acquired at higher spatial resolution than the imaging spectrometer data, it can aid in identifying features in the spectrometer images including manmade features (e.g., roads, fence lines, and buildings) that are indicative of land-use change. Level 1 RGB camera images are distributed as one camera frame per GeoTIFF file.\n\nLatency:\nAOP data will be available 60 days after the final collection day at a site.", "productDesignDescription": "The Level 1 high-resolution RGB orthorectified camera imagery product is a single color camera frame in GeoTIFF raster data format in UTM projection and ITRF00 datum.", "productStudyDescription": "NEON AOP data are planned for yearly collects at all NEON sites at 90% of maximum greenness or greater. Coverage is planned to include at least 95% of NIS Tower Airshed area as well as at least 80% of a minimum 10km x 10 km box around that. All acquisitions are subject to change due to weather conditions as well as program planning changes.", + "productBasicDescription": "Includes the data product as a single orthorectified RGB camera image in GeoTIFF format. An expanded package is not available for this product.", + "productExpandedDescription": "", "productSensor": "NEON Airborne Observation Platform (AOP) High Resolution Digital Camera – Optech Gemini", - "productRemarks": null, - "themes": [ - "Land Use, Land Cover, and Land Processes" - ], + "productRemarks": "", + "themes": ["Land Use, Land Cover, and Land Processes"], "changeLogs": null, - "specs": [ - { - "specId": 1423, - "specNumber": "NEON.DOC.001211vA" - } - ], + "specs": null, "keywords": [ - "airborne", "aerial", - "camera", "photo", + "camera", + "orthophoto", + "airborne", + "orthoimagery", + "red green blue (RGB)", "high resolution", "imagery", - "orthophoto", - "orthoimagery" + "GeoTIFF", + "remote sensing" + ], + "biorepositoryCollections": null, + "releases": [ + { + "release": "RELEASE-2023", + "generationDate": "2023-01-27T12:07:53Z", + "url": "https://cert-data.neonscience.org/api/v0/releases/RELEASE-2023", + "productDoi": { + "generationDate": "2023-01-27T15:41:36Z", + "url": "https://doi.org/10.48443/wbts-hh07" + } + } ], "siteCodes": [ { - "siteCode": "PRIN", - "availableMonths": [ - "2016-04", - "2017-05" - ], + "siteCode": "ABBY", + "availableMonths": ["2017-06", "2018-07", "2019-07", "2021-07"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/PRIN/2016-04", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/PRIN/2017-05" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/ABBY/2017-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/ABBY/2018-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/ABBY/2019-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/ABBY/2021-07" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": ["2017-06", "2018-07", "2019-07", "2021-07"] + } ] }, { - "siteCode": "WOOD", - "availableMonths": [ - "2016-06", - "2017-06" - ], + "siteCode": "ARIK", + "availableMonths": ["2017-05", "2020-06", "2021-06", "2022-07"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/WOOD/2016-06", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/WOOD/2017-06" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/ARIK/2017-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/ARIK/2020-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/ARIK/2021-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/ARIK/2022-07" + ], + "availableReleases": [ + { "release": "PROVISIONAL", "availableMonths": ["2022-07"] }, + { + "release": "RELEASE-2023", + "availableMonths": ["2017-05", "2020-06", "2021-06"] + } ] }, { - "siteCode": "TALL", - "availableMonths": [ - "2016-05", - "2017-05", - "2018-04" - ], + "siteCode": "BARR", + "availableMonths": ["2017-07", "2018-07", "2019-07"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/TALL/2016-05", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/TALL/2017-05", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/TALL/2018-04" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/BARR/2017-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/BARR/2018-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/BARR/2019-07" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": ["2017-07", "2018-07", "2019-07"] + } ] }, { - "siteCode": "ARIK", + "siteCode": "BART", "availableMonths": [ - "2017-05" + "2014-06", + "2016-08", + "2017-08", + "2018-08", + "2019-08", + "2022-08" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/ARIK/2017-05" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/BART/2014-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/BART/2016-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/BART/2017-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/BART/2018-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/BART/2019-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/BART/2022-08" + ], + "availableReleases": [ + { "release": "PROVISIONAL", "availableMonths": ["2022-08"] }, + { + "release": "RELEASE-2023", + "availableMonths": [ + "2014-06", + "2016-08", + "2017-08", + "2018-08", + "2019-08" + ] + } ] }, { - "siteCode": "JERC", + "siteCode": "BLAN", "availableMonths": [ - "2014-05", - "2016-09", - "2017-09", - "2018-09" + "2016-08", + "2017-07", + "2019-06", + "2021-08", + "2022-05" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/JERC/2014-05", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/JERC/2016-09", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/JERC/2017-09", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/JERC/2018-09" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/BLAN/2016-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/BLAN/2017-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/BLAN/2019-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/BLAN/2021-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/BLAN/2022-05" + ], + "availableReleases": [ + { "release": "PROVISIONAL", "availableMonths": ["2022-05"] }, + { + "release": "RELEASE-2023", + "availableMonths": ["2016-08", "2017-07", "2019-06", "2021-08"] + } ] }, { - "siteCode": "OSBS", - "availableMonths": [ - "2014-05", - "2016-09", - "2017-09", - "2018-09" - ], + "siteCode": "BLUE", + "availableMonths": ["2017-05"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/OSBS/2014-05", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/OSBS/2016-09", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/OSBS/2017-09", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/OSBS/2018-09" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/BLUE/2017-05" + ], + "availableReleases": [ + { "release": "RELEASE-2023", "availableMonths": ["2017-05"] } ] }, { - "siteCode": "KONZ", - "availableMonths": [ - "2016-07", - "2017-06", - "2018-06" - ], + "siteCode": "BONA", + "availableMonths": ["2017-08", "2018-08", "2019-08", "2021-08"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/KONZ/2016-07", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/KONZ/2017-06", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/KONZ/2018-06" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/BONA/2017-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/BONA/2018-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/BONA/2019-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/BONA/2021-08" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": ["2017-08", "2018-08", "2019-08", "2021-08"] + } ] }, { - "siteCode": "DEJU", + "siteCode": "CLBJ", "availableMonths": [ - "2017-07", - "2018-08" + "2016-04", + "2017-05", + "2018-04", + "2019-04", + "2021-06", + "2022-05" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/DEJU/2017-07", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/DEJU/2018-08" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/CLBJ/2016-04", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/CLBJ/2017-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/CLBJ/2018-04", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/CLBJ/2019-04", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/CLBJ/2021-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/CLBJ/2022-05" + ], + "availableReleases": [ + { "release": "PROVISIONAL", "availableMonths": ["2022-05"] }, + { + "release": "RELEASE-2023", + "availableMonths": [ + "2016-04", + "2017-05", + "2018-04", + "2019-04", + "2021-06" + ] + } ] }, { - "siteCode": "WREF", + "siteCode": "CPER", "availableMonths": [ - "2017-06", - "2018-07" + "2013-06", + "2017-05", + "2020-06", + "2020-09", + "2021-06" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/WREF/2017-06", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/WREF/2018-07" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/CPER/2013-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/CPER/2017-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/CPER/2020-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/CPER/2020-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/CPER/2021-06" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": [ + "2013-06", + "2017-05", + "2020-06", + "2020-09", + "2021-06" + ] + } ] }, { - "siteCode": "MLBS", - "availableMonths": [ - "2015-08", - "2017-08", - "2018-05" - ], + "siteCode": "CUPE", + "availableMonths": ["2018-05"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/MLBS/2015-08", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/MLBS/2017-08", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/MLBS/2018-05" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/CUPE/2018-05" + ], + "availableReleases": [ + { "release": "RELEASE-2023", "availableMonths": ["2018-05"] } ] }, { - "siteCode": "HOPB", + "siteCode": "DCFS", "availableMonths": [ - "2016-08", - "2017-08" + "2016-06", + "2017-06", + "2019-07", + "2020-06", + "2021-06" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/HOPB/2016-08", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/HOPB/2017-08" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DCFS/2016-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DCFS/2017-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DCFS/2019-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DCFS/2020-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DCFS/2021-06" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": [ + "2016-06", + "2017-06", + "2019-07", + "2020-06", + "2021-06" + ] + } ] }, { - "siteCode": "RMNP", - "availableMonths": [ - "2017-07", - "2018-09" - ], + "siteCode": "DEJU", + "availableMonths": ["2017-07", "2018-08", "2019-08", "2021-07"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/RMNP/2017-07", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/RMNP/2018-09" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DEJU/2017-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DEJU/2018-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DEJU/2019-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DEJU/2021-07" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": ["2017-07", "2018-08", "2019-08", "2021-07"] + } ] }, { - "siteCode": "BARR", + "siteCode": "DELA", "availableMonths": [ - "2017-07", - "2018-07" + "2015-07", + "2016-05", + "2017-05", + "2018-04", + "2019-04", + "2021-05" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/BARR/2017-07", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/BARR/2018-07" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DELA/2015-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DELA/2016-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DELA/2017-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DELA/2018-04", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DELA/2019-04", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DELA/2021-05" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": [ + "2015-07", + "2016-05", + "2017-05", + "2018-04", + "2019-04", + "2021-05" + ] + } ] }, { - "siteCode": "OAES", + "siteCode": "DSNY", "availableMonths": [ - "2016-04", - "2017-05", - "2018-04" + "2014-05", + "2016-09", + "2017-09", + "2018-10", + "2019-04", + "2021-09" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/OAES/2016-04", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/OAES/2017-05", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/OAES/2018-04" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DSNY/2014-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DSNY/2016-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DSNY/2017-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DSNY/2018-10", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DSNY/2019-04", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/DSNY/2021-09" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": [ + "2014-05", + "2016-09", + "2017-09", + "2018-10", + "2019-04", + "2021-09" + ] + } ] }, { @@ -211,293 +363,615 @@ "2015-08", "2016-06", "2017-10", - "2018-05" + "2018-05", + "2021-06", + "2022-05" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/GRSM/2015-08", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/GRSM/2016-06", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/GRSM/2017-10", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/GRSM/2018-05" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/GRSM/2015-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/GRSM/2016-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/GRSM/2017-10", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/GRSM/2018-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/GRSM/2021-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/GRSM/2022-05" + ], + "availableReleases": [ + { "release": "PROVISIONAL", "availableMonths": ["2022-05"] }, + { + "release": "RELEASE-2023", + "availableMonths": [ + "2015-08", + "2016-06", + "2017-10", + "2018-05", + "2021-06" + ] + } ] }, { - "siteCode": "SERC", - "availableMonths": [ - "2016-07", - "2017-07", - "2017-08" + "siteCode": "GUAN", + "availableMonths": ["2018-05"], + "availableDataUrls": [ + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/GUAN/2018-05" ], + "availableReleases": [ + { "release": "RELEASE-2023", "availableMonths": ["2018-05"] } + ] + }, + { + "siteCode": "GUIL", + "availableMonths": ["2018-05"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/SERC/2016-07", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/SERC/2017-07", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/SERC/2017-08" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/GUIL/2018-05" + ], + "availableReleases": [ + { "release": "RELEASE-2023", "availableMonths": ["2018-05"] } ] }, { - "siteCode": "YELL", + "siteCode": "HARV", "availableMonths": [ - "2018-07" + "2014-06", + "2016-08", + "2017-08", + "2018-09", + "2019-08", + "2022-08" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/YELL/2018-07" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/HARV/2014-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/HARV/2016-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/HARV/2017-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/HARV/2018-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/HARV/2019-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/HARV/2022-08" + ], + "availableReleases": [ + { "release": "PROVISIONAL", "availableMonths": ["2022-08"] }, + { + "release": "RELEASE-2023", + "availableMonths": [ + "2014-06", + "2016-08", + "2017-08", + "2018-09", + "2019-08" + ] + } ] }, { - "siteCode": "ABBY", - "availableMonths": [ - "2017-06", - "2018-07" + "siteCode": "HEAL", + "availableMonths": ["2017-07", "2018-08", "2019-08", "2021-07"], + "availableDataUrls": [ + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/HEAL/2017-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/HEAL/2018-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/HEAL/2019-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/HEAL/2021-07" ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": ["2017-07", "2018-08", "2019-08", "2021-07"] + } + ] + }, + { + "siteCode": "HOPB", + "availableMonths": ["2016-08", "2017-08", "2019-08"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/ABBY/2017-06", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/ABBY/2018-07" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/HOPB/2016-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/HOPB/2017-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/HOPB/2019-08" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": ["2016-08", "2017-08", "2019-08"] + } ] }, { - "siteCode": "DELA", + "siteCode": "JERC", "availableMonths": [ - "2015-07", - "2016-05", - "2017-05", - "2018-04" + "2014-05", + "2016-09", + "2017-09", + "2018-09", + "2019-09", + "2021-09" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/DELA/2015-07", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/DELA/2016-05", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/DELA/2017-05", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/DELA/2018-04" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/JERC/2014-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/JERC/2016-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/JERC/2017-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/JERC/2018-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/JERC/2019-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/JERC/2021-09" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": [ + "2014-05", + "2016-09", + "2017-09", + "2018-09", + "2019-09", + "2021-09" + ] + } ] }, { - "siteCode": "SOAP", - "availableMonths": [ - "2013-06", - "2017-07", - "2018-06" - ], + "siteCode": "JORN", + "availableMonths": ["2017-08", "2018-08", "2019-08", "2021-08"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/SOAP/2013-06", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/SOAP/2017-07", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/SOAP/2018-06" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/JORN/2017-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/JORN/2018-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/JORN/2019-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/JORN/2021-08" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": ["2017-08", "2018-08", "2019-08", "2021-08"] + } ] }, { - "siteCode": "GUIL", + "siteCode": "KONA", "availableMonths": [ - "2018-05" + "2016-07", + "2017-06", + "2018-06", + "2019-07", + "2020-07" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/GUIL/2018-05" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/KONA/2016-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/KONA/2017-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/KONA/2018-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/KONA/2019-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/KONA/2020-07" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": [ + "2016-07", + "2017-06", + "2018-06", + "2019-07", + "2020-07" + ] + } ] }, { - "siteCode": "SCBI", + "siteCode": "KONZ", "availableMonths": [ "2016-07", - "2017-07" + "2017-06", + "2018-06", + "2019-07", + "2020-07" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/SCBI/2016-07", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/SCBI/2017-07" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/KONZ/2016-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/KONZ/2017-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/KONZ/2018-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/KONZ/2019-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/KONZ/2020-07" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": [ + "2016-07", + "2017-06", + "2018-06", + "2019-07", + "2020-07" + ] + } ] }, { - "siteCode": "DSNY", - "availableMonths": [ - "2014-05", - "2016-09", - "2017-09", - "2018-10" - ], + "siteCode": "LAJA", + "availableMonths": ["2018-05"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/DSNY/2014-05", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/DSNY/2016-09", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/DSNY/2017-09", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/DSNY/2018-10" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/LAJA/2018-05" + ], + "availableReleases": [ + { "release": "RELEASE-2023", "availableMonths": ["2018-05"] } ] }, { - "siteCode": "GUAN", + "siteCode": "LENO", "availableMonths": [ - "2018-05" + "2015-07", + "2016-05", + "2017-05", + "2018-04", + "2019-05", + "2021-05" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/GUAN/2018-05" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/LENO/2015-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/LENO/2016-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/LENO/2017-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/LENO/2018-04", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/LENO/2019-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/LENO/2021-05" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": [ + "2015-07", + "2016-05", + "2017-05", + "2018-04", + "2019-05", + "2021-05" + ] + } ] }, { - "siteCode": "TOOL", - "availableMonths": [ - "2017-07", - "2018-07" - ], + "siteCode": "LIRO", + "availableMonths": ["2017-09", "2020-08", "2022-06"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/TOOL/2017-07", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/TOOL/2018-07" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/LIRO/2017-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/LIRO/2020-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/LIRO/2022-06" + ], + "availableReleases": [ + { "release": "PROVISIONAL", "availableMonths": ["2022-06"] }, + { + "release": "RELEASE-2023", + "availableMonths": ["2017-09", "2020-08"] + } ] }, { "siteCode": "MCDI", - "availableMonths": [ - "2017-06" - ], + "availableMonths": ["2017-06", "2020-07"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/MCDI/2017-06" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/MCDI/2017-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/MCDI/2020-07" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": ["2017-06", "2020-07"] + } ] }, { - "siteCode": "ORNL", - "availableMonths": [ - "2015-08", - "2016-06", - "2017-06", - "2017-09" - ], + "siteCode": "MCRA", + "availableMonths": ["2018-07", "2021-07"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/ORNL/2015-08", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/ORNL/2016-06", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/ORNL/2017-06", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/ORNL/2017-09" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/MCRA/2018-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/MCRA/2021-07" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": ["2018-07", "2021-07"] + } ] }, { - "siteCode": "UKFS", - "availableMonths": [ - "2016-07", - "2017-06", - "2018-06" - ], + "siteCode": "MLBS", + "availableMonths": ["2015-08", "2017-08", "2018-05", "2021-06"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/UKFS/2016-07", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/UKFS/2017-06", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/UKFS/2018-06" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/MLBS/2015-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/MLBS/2017-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/MLBS/2018-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/MLBS/2021-06" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": ["2015-08", "2017-08", "2018-05", "2021-06"] + } ] }, { - "siteCode": "CPER", + "siteCode": "MOAB", "availableMonths": [ - "2013-06", - "2016-04", - "2017-05" + "2017-09", + "2018-08", + "2019-08", + "2020-07", + "2021-04", + "2022-04" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/CPER/2013-06", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/CPER/2016-04", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/CPER/2017-05" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/MOAB/2017-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/MOAB/2018-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/MOAB/2019-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/MOAB/2020-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/MOAB/2021-04", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/MOAB/2022-04" + ], + "availableReleases": [ + { "release": "PROVISIONAL", "availableMonths": ["2022-04"] }, + { + "release": "RELEASE-2023", + "availableMonths": [ + "2017-09", + "2018-08", + "2019-08", + "2020-07", + "2021-04" + ] + } ] }, { - "siteCode": "HEAL", - "availableMonths": [ - "2017-07", - "2018-08" - ], + "siteCode": "NIWO", + "availableMonths": ["2017-09", "2018-08", "2019-08", "2020-08"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/HEAL/2017-07", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/HEAL/2018-08" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/NIWO/2017-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/NIWO/2018-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/NIWO/2019-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/NIWO/2020-08" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": ["2017-09", "2018-08", "2019-08", "2020-08"] + } ] }, { "siteCode": "NOGP", "availableMonths": [ "2016-07", - "2017-06" + "2017-06", + "2019-07", + "2020-06", + "2021-06" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/NOGP/2016-07", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/NOGP/2017-06" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/NOGP/2016-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/NOGP/2017-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/NOGP/2019-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/NOGP/2020-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/NOGP/2021-06" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": [ + "2016-07", + "2017-06", + "2019-07", + "2020-06", + "2021-06" + ] + } ] }, { - "siteCode": "LAJA", + "siteCode": "OAES", "availableMonths": [ - "2018-05" + "2016-04", + "2017-05", + "2018-04", + "2019-04", + "2021-06", + "2022-05" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/LAJA/2018-05" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/OAES/2016-04", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/OAES/2017-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/OAES/2018-04", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/OAES/2019-04", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/OAES/2021-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/OAES/2022-05" + ], + "availableReleases": [ + { "release": "PROVISIONAL", "availableMonths": ["2022-05"] }, + { + "release": "RELEASE-2023", + "availableMonths": [ + "2016-04", + "2017-05", + "2018-04", + "2019-04", + "2021-06" + ] + } ] }, { - "siteCode": "WLOU", - "availableMonths": [ - "2017-09" - ], + "siteCode": "ONAQ", + "availableMonths": ["2017-06", "2019-05", "2021-05", "2022-05"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/WLOU/2017-09" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/ONAQ/2017-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/ONAQ/2019-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/ONAQ/2021-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/ONAQ/2022-05" + ], + "availableReleases": [ + { "release": "PROVISIONAL", "availableMonths": ["2022-05"] }, + { + "release": "RELEASE-2023", + "availableMonths": ["2017-06", "2019-05", "2021-05"] + } ] }, { - "siteCode": "REDB", - "availableMonths": [ - "2017-05" - ], + "siteCode": "ORNL", + "availableMonths": ["2015-08", "2016-06", "2017-09"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/REDB/2017-05" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/ORNL/2015-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/ORNL/2016-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/ORNL/2017-09" + ], + "availableReleases": [ + { + "release": "PROVISIONAL", + "availableMonths": ["2015-08", "2016-06", "2017-09"] + } ] }, { - "siteCode": "LENO", + "siteCode": "OSBS", "availableMonths": [ - "2015-07", - "2016-05", - "2017-05", - "2018-04" + "2014-05", + "2016-09", + "2017-09", + "2018-09", + "2019-04", + "2021-09" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/LENO/2015-07", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/LENO/2016-05", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/LENO/2017-05", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/LENO/2018-04" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/OSBS/2014-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/OSBS/2016-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/OSBS/2017-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/OSBS/2018-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/OSBS/2019-04", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/OSBS/2021-09" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": [ + "2014-05", + "2016-09", + "2017-09", + "2018-09", + "2019-04", + "2021-09" + ] + } ] }, { - "siteCode": "LIRO", - "availableMonths": [ - "2017-09" + "siteCode": "PRIN", + "availableMonths": ["2016-04", "2017-05", "2021-06", "2022-05"], + "availableDataUrls": [ + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/PRIN/2016-04", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/PRIN/2017-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/PRIN/2021-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/PRIN/2022-05" ], + "availableReleases": [ + { "release": "PROVISIONAL", "availableMonths": ["2022-05"] }, + { + "release": "RELEASE-2023", + "availableMonths": ["2016-04", "2017-05", "2021-06"] + } + ] + }, + { + "siteCode": "PUUM", + "availableMonths": ["2019-01", "2020-01"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/LIRO/2017-09" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/PUUM/2019-01", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/PUUM/2020-01" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": ["2019-01", "2020-01"] + } ] }, { - "siteCode": "HARV", - "availableMonths": [ - "2014-06", - "2016-08", - "2017-08", - "2018-09" + "siteCode": "REDB", + "availableMonths": ["2017-05", "2019-05", "2021-05", "2022-05"], + "availableDataUrls": [ + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/REDB/2017-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/REDB/2019-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/REDB/2021-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/REDB/2022-05" ], + "availableReleases": [ + { "release": "PROVISIONAL", "availableMonths": ["2022-05"] }, + { + "release": "RELEASE-2023", + "availableMonths": ["2017-05", "2019-05", "2021-05"] + } + ] + }, + { + "siteCode": "RMNP", + "availableMonths": ["2017-07", "2018-09", "2020-07", "2022-07"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/HARV/2014-06", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/HARV/2016-08", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/HARV/2017-08", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/HARV/2018-09" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/RMNP/2017-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/RMNP/2018-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/RMNP/2020-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/RMNP/2022-07" + ], + "availableReleases": [ + { "release": "PROVISIONAL", "availableMonths": ["2022-07"] }, + { + "release": "RELEASE-2023", + "availableMonths": ["2017-07", "2018-09", "2020-07"] + } ] }, { - "siteCode": "BART", + "siteCode": "SCBI", "availableMonths": [ - "2014-06", - "2016-08", - "2017-08", - "2018-08" + "2016-07", + "2017-07", + "2019-06", + "2021-08", + "2022-05" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/BART/2014-06", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/BART/2016-08", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/BART/2017-08", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/BART/2018-08" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SCBI/2016-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SCBI/2017-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SCBI/2019-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SCBI/2021-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SCBI/2022-05" + ], + "availableReleases": [ + { "release": "PROVISIONAL", "availableMonths": ["2022-05"] }, + { + "release": "RELEASE-2023", + "availableMonths": ["2016-07", "2017-07", "2019-06", "2021-08"] + } ] }, { - "siteCode": "BONA", + "siteCode": "SERC", "availableMonths": [ + "2016-07", + "2017-07", "2017-08", - "2018-08" + "2019-05", + "2021-08", + "2022-05" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/BONA/2017-08", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/BONA/2018-08" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SERC/2016-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SERC/2017-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SERC/2017-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SERC/2019-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SERC/2021-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SERC/2022-05" + ], + "availableReleases": [ + { "release": "PROVISIONAL", "availableMonths": ["2022-05"] }, + { + "release": "RELEASE-2023", + "availableMonths": [ + "2016-07", + "2017-07", + "2017-08", + "2019-05", + "2021-08" + ] + } ] }, { @@ -505,146 +979,321 @@ "availableMonths": [ "2013-06", "2017-03", - "2018-03" + "2018-03", + "2019-03", + "2021-03" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/SJER/2013-06", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/SJER/2017-03", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/SJER/2018-03" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SJER/2013-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SJER/2017-03", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SJER/2018-03", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SJER/2019-03", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SJER/2021-03" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": [ + "2013-06", + "2017-03", + "2018-03", + "2019-03", + "2021-03" + ] + } ] }, { - "siteCode": "STEI", + "siteCode": "SOAP", "availableMonths": [ - "2016-09", - "2017-08" + "2013-06", + "2017-07", + "2018-06", + "2019-06", + "2021-07" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/STEI/2016-09", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/STEI/2017-08" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SOAP/2013-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SOAP/2017-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SOAP/2018-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SOAP/2019-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SOAP/2021-07" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": [ + "2013-06", + "2017-07", + "2018-06", + "2019-06", + "2021-07" + ] + } ] }, { - "siteCode": "JORN", - "availableMonths": [ - "2017-08", - "2018-08" + "siteCode": "SRER", + "availableMonths": ["2017-08", "2018-08", "2019-09", "2021-09"], + "availableDataUrls": [ + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SRER/2017-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SRER/2018-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SRER/2019-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SRER/2021-09" ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": ["2017-08", "2018-08", "2019-09", "2021-09"] + } + ] + }, + { + "siteCode": "STEI", + "availableMonths": ["2016-09", "2017-08", "2020-08", "2022-06"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/JORN/2017-08", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/JORN/2018-08" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/STEI/2016-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/STEI/2017-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/STEI/2020-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/STEI/2022-06" + ], + "availableReleases": [ + { + "release": "PROVISIONAL", + "availableMonths": ["2017-08", "2022-06"] + }, + { + "release": "RELEASE-2023", + "availableMonths": ["2016-09", "2020-08"] + } ] }, { - "siteCode": "MOAB", - "availableMonths": [ - "2017-09", - "2018-08" + "siteCode": "STER", + "availableMonths": ["2013-06", "2017-07", "2021-06", "2022-07"], + "availableDataUrls": [ + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/STER/2013-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/STER/2017-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/STER/2021-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/STER/2022-07" ], + "availableReleases": [ + { "release": "PROVISIONAL", "availableMonths": ["2022-07"] }, + { + "release": "RELEASE-2023", + "availableMonths": ["2013-06", "2017-07", "2021-06"] + } + ] + }, + { + "siteCode": "SYCA", + "availableMonths": ["2019-09", "2021-04"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/MOAB/2017-09", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/MOAB/2018-08" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SYCA/2019-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/SYCA/2021-04" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": ["2019-09", "2021-04"] + } ] }, { - "siteCode": "BLAN", + "siteCode": "TALL", "availableMonths": [ - "2016-08", - "2017-07" + "2016-05", + "2017-05", + "2018-04", + "2019-04", + "2021-05" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/BLAN/2016-08", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/BLAN/2017-07" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/TALL/2016-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/TALL/2017-05", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/TALL/2018-04", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/TALL/2019-04", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/TALL/2021-05" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": [ + "2016-05", + "2017-05", + "2018-04", + "2019-04", + "2021-05" + ] + } ] }, { - "siteCode": "STER", + "siteCode": "TEAK", "availableMonths": [ "2013-06", - "2017-07" + "2017-06", + "2018-06", + "2019-06", + "2021-07" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/STER/2013-06", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/STER/2017-07" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/TEAK/2013-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/TEAK/2017-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/TEAK/2018-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/TEAK/2019-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/TEAK/2021-07" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": [ + "2013-06", + "2017-06", + "2018-06", + "2019-06", + "2021-07" + ] + } ] }, { - "siteCode": "ONAQ", - "availableMonths": [ - "2017-06" - ], + "siteCode": "TOOL", + "availableMonths": ["2017-07", "2018-07", "2019-07"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/ONAQ/2017-06" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/TOOL/2017-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/TOOL/2018-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/TOOL/2019-07" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": ["2017-07", "2018-07", "2019-07"] + } ] }, { - "siteCode": "SRER", - "availableMonths": [ - "2017-08", - "2018-08" - ], + "siteCode": "TREE", + "availableMonths": ["2016-09", "2020-08", "2022-06"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/SRER/2017-08", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/SRER/2018-08" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/TREE/2016-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/TREE/2020-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/TREE/2022-06" + ], + "availableReleases": [ + { "release": "PROVISIONAL", "availableMonths": ["2022-06"] }, + { + "release": "RELEASE-2023", + "availableMonths": ["2016-09", "2020-08"] + } ] }, { - "siteCode": "CLBJ", - "availableMonths": [ - "2016-04", - "2017-05", - "2018-04" - ], + "siteCode": "UKFS", + "availableMonths": ["2016-07", "2017-06", "2018-06", "2020-07"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/CLBJ/2016-04", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/CLBJ/2017-05", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/CLBJ/2018-04" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/UKFS/2016-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/UKFS/2017-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/UKFS/2018-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/UKFS/2020-07" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": ["2016-07", "2017-06", "2018-06", "2020-07"] + } ] }, { - "siteCode": "NIWO", - "availableMonths": [ - "2013-07", - "2017-09", - "2018-08" - ], + "siteCode": "UNDE", + "availableMonths": ["2016-09", "2017-09", "2020-08", "2022-06"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/NIWO/2013-07", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/NIWO/2017-09", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/NIWO/2018-08" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/UNDE/2016-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/UNDE/2017-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/UNDE/2020-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/UNDE/2022-06" + ], + "availableReleases": [ + { "release": "PROVISIONAL", "availableMonths": ["2022-06"] }, + { + "release": "RELEASE-2023", + "availableMonths": ["2016-09", "2017-09", "2020-08"] + } ] }, { - "siteCode": "CUPE", - "availableMonths": [ - "2018-05" - ], + "siteCode": "WLOU", + "availableMonths": ["2017-09", "2019-08", "2020-08"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/CUPE/2018-05" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/WLOU/2017-09", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/WLOU/2019-08", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/WLOU/2020-08" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": ["2017-09", "2019-08", "2020-08"] + } ] }, { - "siteCode": "TEAK", + "siteCode": "WOOD", "availableMonths": [ - "2013-06", + "2016-06", "2017-06", - "2018-06" + "2019-07", + "2020-06", + "2021-06" ], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/TEAK/2013-06", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/TEAK/2017-06", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/TEAK/2018-06" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/WOOD/2016-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/WOOD/2017-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/WOOD/2019-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/WOOD/2020-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/WOOD/2021-06" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": [ + "2016-06", + "2017-06", + "2019-07", + "2020-06", + "2021-06" + ] + } ] }, { - "siteCode": "UNDE", - "availableMonths": [ - "2016-09", - "2017-09" + "siteCode": "WREF", + "availableMonths": ["2017-06", "2018-07", "2019-07", "2021-07"], + "availableDataUrls": [ + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/WREF/2017-06", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/WREF/2018-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/WREF/2019-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/WREF/2021-07" ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": ["2017-06", "2018-07", "2019-07", "2021-07"] + } + ] + }, + { + "siteCode": "YELL", + "availableMonths": ["2018-07", "2019-07", "2020-07"], "availableDataUrls": [ - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/UNDE/2016-09", - "https://int-data.neonscience.org/api/v0/data/DP1.30010.001/UNDE/2017-09" + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/YELL/2018-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/YELL/2019-07", + "https://cert-data.neonscience.org/api/v0/data/DP1.30010.001/YELL/2020-07" + ], + "availableReleases": [ + { + "release": "RELEASE-2023", + "availableMonths": ["2018-07", "2019-07", "2020-07"] + } ] } ]