Skip to content

Commit

Permalink
EDSC-3797: Added an option for concatenation for custom downloads via…
Browse files Browse the repository at this point in the history
… Harmony (#1693)

* EDSC-3797: made initial implementation of the code

* EDSC-3797: added tests.

* EDSC-3797: supportsConcat test

* EDSC-3797: fixed up the issues for default stuff and added the necessary tests.

* small fix

* fix

* EDSC-3797: changed the newly added gray-text class to use text-muted

* removed console.logs

* EDSC-3797: pushing up changes so that enableConcatenateDownload is not undefined when the lambda job is created.

* removed console.log

* EDSC-3797: added tests to make sure behavior is consistent when aggregation exists but concatenate does not.

* Fixed buildAccessMethods test

* EDSC-3797: re-added deleted test

* removed console.log

* EDSC-3797: addresses Matthew's comments

* EDSC-3797: changed the wording on the description of the concatenation test for constructing the orderPayload

* EDSC-3797: slight change to one of the test descriptions

* EDSC-3797: added encoder and decoder for concatenateDownload.

* EDSC-3797: added tests to check concatenate Download variable in the url works as expected.

* EDSC-3797: set enabledConcatenateDownload to be equal to the defaultConcatenate initially.

* Update static/src/js/util/accessMethods/__tests__/defaultConcatenation.test.js

Co-authored-by: Ed Olivares <34591886+eudoroolivares2016@users.noreply.github.com>

* EDSC-3797: reverted certain variables

* EDSC-3797: updated the wording and moved around tests to match best practices.

* spelling mistake fix

---------

Co-authored-by: Ed Olivares <34591886+eudoroolivares2016@users.noreply.github.com>
  • Loading branch information
bnp26 and eudoroolivares2016 authored Nov 16, 2023
1 parent 5cd33a3 commit 12f13a6
Show file tree
Hide file tree
Showing 16 changed files with 583 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -693,4 +693,115 @@ describe('constructOrderPayload', () => {
})
})
})

describe('when supportsConcatenation = true and enableConcatenateDownload = true', () => {
test('constructs a payload containing concatenate = true', async () => {
nock(/cmr/)
.matchHeader('Authorization', 'Bearer access-token')
.get('/search/granules.json?point%5B%5D=-77%2C%2034')
.reply(200, {
feed: {
entry: [{
id: 'G10000001-EDSC'
}, {
id: 'G10000005-EDSC'
}]
}
})

const granuleParams = {
point: ['-77, 34']
}

const accessMethod = {
supportsConcatenation: true,
enableConcatenateDownload: true
}

const accessToken = 'access-token'

const response = await constructOrderPayload({
accessMethod,
granuleParams,
accessToken
})

expect(response.getAll('concatenate')).toEqual([
'true'
])
})
})

describe('when supportsConcatenation = false or enableConcatenateDownload = false', () => {
test('constructed payload does not contain concatenate', async () => {
nock(/cmr/)
.matchHeader('Authorization', 'Bearer access-token')
.get('/search/granules.json?point%5B%5D=-77%2C%2034')
.reply(200, {
feed: {
entry: [{
id: 'G10000001-EDSC'
}, {
id: 'G10000005-EDSC'
}]
}
})

const granuleParams = {
point: ['-77, 34']
}

const accessMethod = {
supportsConcatenation: true,
enableConcatenateDownload: false
}

const accessToken = 'access-token'

const response = await constructOrderPayload({
accessMethod,
granuleParams,
accessToken
})

expect(response.getAll('concatenate')).not.toEqual([
'true'
])
})

test('constructed payload does not contain concatenate', async () => {
nock(/cmr/)
.matchHeader('Authorization', 'Bearer access-token')
.get('/search/granules.json?point%5B%5D=-77%2C%2034')
.reply(200, {
feed: {
entry: [{
id: 'G10000001-EDSC'
}, {
id: 'G10000005-EDSC'
}]
}
})

const granuleParams = {
point: ['-77, 34']
}

const accessMethod = {
supportsConcatenation: false
}

const accessToken = 'access-token'

const response = await constructOrderPayload({
accessMethod,
granuleParams,
accessToken
})

expect(response.getAll('concatenate')).not.toEqual([
'true'
])
})
})
})
9 changes: 8 additions & 1 deletion serverless/src/submitHarmonyOrder/constructOrderPayload.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,13 @@ export const constructOrderPayload = async ({
const {
enableTemporalSubsetting,
enableSpatialSubsetting,
enableConcatenateDownload,
mbr,
selectedOutputFormat,
selectedOutputProjection,
supportsBoundingBoxSubsetting,
supportsShapefileSubsetting
supportsShapefileSubsetting,
supportsConcatenation
} = accessMethod

// OGC uses duplicate parameter names for subsetting and the
Expand Down Expand Up @@ -215,6 +217,11 @@ export const constructOrderPayload = async ({
orderPayload.append('outputCrs', selectedOutputProjection)
}

// Adds supportsConcatenation to the payload and it's value
if (supportsConcatenation && enableConcatenateDownload) {
orderPayload.append('concatenate', true)
}

// EDSC-3440: Add skipPreview=true to all Harmony orders
orderPayload.append('skipPreview', true)

Expand Down
75 changes: 68 additions & 7 deletions static/src/js/components/AccessMethod/AccessMethod.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ export class AccessMethod extends Component {
enableTemporalSubsetting = !isRecurring
} = selectedMethod || {}

const {
enableConcatenateDownload
} = selectedMethod || false

const {
enableSpatialSubsetting = !(
boundingBox === undefined
Expand All @@ -73,14 +77,16 @@ export class AccessMethod extends Component {

this.state = {
enableTemporalSubsetting,
enableSpatialSubsetting
enableSpatialSubsetting,
enableConcatenateDownload
}

this.handleAccessMethodSelection = this.handleAccessMethodSelection.bind(this)
this.handleOutputFormatSelection = this.handleOutputFormatSelection.bind(this)
this.handleOutputProjectionSelection = this.handleOutputProjectionSelection.bind(this)
this.handleToggleTemporalSubsetting = this.handleToggleTemporalSubsetting.bind(this)
this.handleToggleSpatialSubsetting = this.handleToggleSpatialSubsetting.bind(this)
this.handleConcatenationSelection = this.handleConcatenationSelection.bind(this)
}

UNSAFE_componentWillReceiveProps() {
Expand Down Expand Up @@ -141,6 +147,25 @@ export class AccessMethod extends Component {
})
}

handleConcatenationSelection(event) {
const { metadata, onUpdateAccessMethod, selectedAccessMethod } = this.props
const { conceptId: collectionId } = metadata

const { target } = event
const { checked } = target

this.setState({ enableConcatenateDownload: checked })

onUpdateAccessMethod({
collectionId,
method: {
[selectedAccessMethod]: {
enableConcatenateDownload: checked
}
}
})
}

handleToggleTemporalSubsetting(event) {
const { metadata, onUpdateAccessMethod, selectedAccessMethod } = this.props
const { conceptId: collectionId } = metadata
Expand Down Expand Up @@ -207,11 +232,6 @@ export class AccessMethod extends Component {
}

render() {
const {
enableTemporalSubsetting,
enableSpatialSubsetting
} = this.state

const {
accessMethods,
index,
Expand Down Expand Up @@ -337,9 +357,17 @@ export class AccessMethod extends Component {
supportsTemporalSubsetting = false,
supportsShapefileSubsetting = false,
supportsBoundingBoxSubsetting = false,
supportsVariableSubsetting = false
supportsVariableSubsetting = false,
supportsConcatenation = false,
defaultConcatenation = false
} = selectedMethod || {}

const {
enableTemporalSubsetting,
enableSpatialSubsetting,
enableConcatenateDownload = defaultConcatenation
} = this.state

const isOpendap = (selectedAccessMethod && selectedAccessMethod === 'opendap')

// Harmony access methods are postfixed with an index given that there can be more than one
Expand Down Expand Up @@ -392,6 +420,7 @@ export class AccessMethod extends Component {
|| supportsBoundingBoxSubsetting
|| supportedOutputFormatOptions.length > 0
|| supportedOutputProjectionOptions.length > 0
|| supportsConcatenation
|| (form && isActive)

const {
Expand Down Expand Up @@ -496,6 +525,38 @@ export class AccessMethod extends Component {
</ProjectPanelSection>
)
}
{
supportsConcatenation && (
<ProjectPanelSection
customHeadingTag="h4"
heading="Combine Data"
intro="Select from available operations to combine the data."
nested
>
<Form.Group controlId="input__concatinate-subsetting" className="mb-0">
<Form.Check
id="input__concatinate-subsetting"
type="checkbox"
label={
(
<div>
<span className="mb-1 d-block">
Enable Concatenation
</span>
<span className="mb-1 d-block text-muted">
Data will be concatenated along a newly created dimension
</span>
</div>
)
}
checked={enableConcatenateDownload}
disabled={isRecurring}
onChange={this.handleConcatenationSelection}
/>
</Form.Group>
</ProjectPanelSection>
)
}
{
supportsTemporalSubsetting && (
<ProjectPanelSection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1065,7 +1065,7 @@ describe('AccessMethod component', () => {

const checkbox = screen.getByRole('checkbox')
await user.click(checkbox)
expect(screen.getByRole('checkbox').checked).toEqual(true)
expect(checkbox.checked).toEqual(true)
})

test('calls onUpdateAccessMethod', async () => {
Expand Down Expand Up @@ -1140,6 +1140,89 @@ describe('AccessMethod component', () => {
expect(screen.getByText(/using the harmony-service-name/)).toBeInTheDocument()
})
})

describe('when the service type is `Harmony` and concatenation is available', () => {
test('the `Combine Data` option is avaialable when concatenation service is true', () => {
const collectionId = 'collectionId'
const serviceName = 'harmony-service-name'
setup({
accessMethods: {
harmony0: {
isValid: true,
type: 'Harmony',
name: serviceName,
supportsConcatenation: true,
defaultConcatenation: true
}
},
metadata: {
conceptId: collectionId
},
selectedAccessMethod: 'harmony0'
})

expect(screen.getByText(/The requested data will be processed/)).toBeInTheDocument()
expect(screen.getByText(/Combine Data/)).toBeInTheDocument()
expect(screen.getByRole('checkbox').checked).toEqual(true)
})

test('when the `Combine Data` option is clicked, the enableConcatenateDownload changes', async () => {
const user = userEvent.setup()
const collectionId = 'collectionId'
const serviceName = 'harmony-service-name'
const { onUpdateAccessMethod } = setup({
accessMethods: {
harmony0: {
isValid: true,
type: 'Harmony',
name: serviceName,
supportsConcatenation: true,
defaultConcatenation: false
}
},
metadata: {
conceptId: collectionId
},
selectedAccessMethod: 'harmony0'
})

expect(screen.getByText(/The requested data will be processed/)).toBeInTheDocument()
expect(screen.getByText(/Combine Data/)).toBeInTheDocument()
await user.click(screen.getByRole('checkbox'))

expect(onUpdateAccessMethod).toHaveBeenCalledTimes(1)
expect(onUpdateAccessMethod).toHaveBeenCalledWith({
collectionId: 'collectionId',
method: { harmony0: { enableConcatenateDownload: true } }
})

expect(screen.getByRole('checkbox').checked).toEqual(true)
})
})

describe('when the service type is `Harmony` and concatenation is unavailable', () => {
test('when the `Combine Data` option is clicked, the enableConcatenateDownload changes', async () => {
const collectionId = 'collectionId'
const serviceName = 'harmony-service-name'
setup({
accessMethods: {
harmony0: {
isValid: true,
type: 'Harmony',
name: serviceName,
supportsConcatenation: false,
enableConcatenateDownload: false
}
},
metadata: {
conceptId: collectionId
},
selectedAccessMethod: 'harmony0'
})

expect(screen.queryAllByText(/Combine Data/)).toHaveLength(0)
})
})
})
})
})
Loading

0 comments on commit 12f13a6

Please sign in to comment.