Skip to content

Commit 18a278e

Browse files
authored
Merge pull request #1013 from nasa/develop
v7.1.0: step 9. Create a pull request against the master branch
2 parents 697e099 + 07f6a4f commit 18a278e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+3078
-3268
lines changed

CHANGELOG.md

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,28 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
77

88
## [Unreleased]
99

10-
## [v7.0.0]
10+
## [v7.0.1] - 2021-10-19
11+
12+
### Added
13+
14+
- **CUMULUS-2462**
15+
- Reingest a granule from granule details page is updated to select a workflow execution arn for reingest.
16+
- Batch Reingest and Bulk Reingest Actions are updated to select the workflowName for reingest.
17+
- **CUMULUS-2585**
18+
- Added failed execution step snapshot to execution list
19+
20+
### Changed
21+
22+
- **CUMULUS-NONE**
23+
- update development version of @cumulus/api to v9.7.0 to pick up test fixes.
24+
- update Cypress to latest version 8.6.0
25+
26+
### Fixed
27+
28+
- **CUMULUS-2643**
29+
- Fixed issue with search component that was causing search to be triggered excessively
30+
31+
## [v7.0.0] - 2021-10-04
1132

1233
## Breaking Changes
1334

@@ -991,7 +1012,8 @@ Fix for serving the dashboard through the Cumulus API.
9911012
### Added
9921013

9931014
- Versioning and changelog [CUMULUS-197] by @kkelly51
994-
[Unreleased]: https://github.com/nasa/cumulus-dashboard/compare/v7.0.0...HEAD
1015+
[Unreleased]: https://github.com/nasa/cumulus-dashboard/compare/v7.1.0...HEAD
1016+
[v7.1.0]: https://github.com/nasa/cumulus-dashboard/compare/v7.0.0...v7.1.0
9951017
[v7.0.0]: https://github.com/nasa/cumulus-dashboard/compare/v6.0.0...v7.0.0
9961018
[v6.0.0]: https://github.com/nasa/cumulus-dashboard/compare/v5.0.0...v6.0.0
9971019
[v5.0.0]: https://github.com/nasa/cumulus-dashboard/compare/v4.0.0...v5.0.0

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,11 @@ The dashboard uses node v12.18.0. To build/run the dashboard on your local machi
114114
We use npm for local package management, to install the requirements:
115115
```bash
116116
$ nvm use
117-
$ npm install
117+
$ npm ci
118118
```
119119

120+
Use `$ npm install` when package.json is updated.
121+
120122
To build a dashboard bundle<sup>[1](#bundlefootnote)</sup>:
121123

122124
```bash
@@ -240,7 +242,7 @@ These are started and stopped with the commands:
240242
$ npm run stop-localstack
241243
```
242244

243-
After these containers are running, you can start a cumulus API locally in a terminal window `npm run serve-api`, the dashboard in another window. `[HIDE_PDR=false SHOW_DISTRIBUTION_API_METRICS=true ESROOT=http://example.com APIROOT=http://localhost:5001] npm run serve` and finally cypress in a third window. `npm run cypress`.
245+
After these containers are running, you can start a cumulus API locally in a terminal window `npm run serve-api`, the dashboard in another window. `[HIDE_PDR=false SHOW_DISTRIBUTION_API_METRICS=true ENABLE_RECOVERY=true ESROOT=http://example.com ES_CLOUDWATCH_TARGET_PATTERN=cwpattern ES_DISTRIBUTION_TARGET_PATTERN=distpattern APIROOT=http://localhost:5001] npm run serve` and finally cypress in a third window. `npm run cypress`.
244246

245247
Once the Docker app is running, If you would like to see sample data you can seed the database. This will load the same sample data into the application that is used during cypress testing.
246248
```bash
@@ -384,6 +386,7 @@ Create and push a new git tag:
384386

385387
```bash
386388
$ git checkout master
389+
$ git pull origin master
387390
$ git tag -a v1.x.x -m "Release 1.x.x"
388391
$ git push origin v1.x.x
389392
```

app/src/css/modules/_modals.scss

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@
173173
}
174174
}
175175

176+
.batch_granules--reingest,
177+
.granule--reingest {
178+
text-align: left;
179+
}
180+
176181
&.bulk_granules {
177182
&.modal-dialog {
178183
overflow-y: initial !important;
@@ -184,8 +189,8 @@
184189

185190
.modal-body {
186191
height: 100px;
187-
overflow-y: auto;
188192
margin-left: 10px;
193+
overflow-y: auto;
189194
text-align: left;
190195
}
191196

app/src/css/modules/_table.scss

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
}
88

99
.table {
10-
width: 100%;
11-
line-height: 1.6em;
12-
overflow-x: scroll;
13-
border-radius: 8px 8px 0px 0px;
14-
scroll-behavior: smooth;
15-
// transform: translate3d(0px, -200px, 0px);
10+
&:not(.sub-table) {
11+
width: 100%;
12+
line-height: 1.6em;
13+
overflow-x: scroll;
14+
border-radius: 8px 8px 0px 0px;
15+
scroll-behavior: smooth;
16+
}
1617

1718
.content-fit {
1819
width: fit-content!important;
@@ -44,7 +45,7 @@
4445
}
4546

4647
.tbody {
47-
.tr {
48+
& > .tr {
4849
border-bottom: 1px solid $lightest-grey;
4950
.td {
5051
font-size: .86em;
@@ -85,6 +86,13 @@
8586
}
8687
}
8788

89+
.sub-table {
90+
.thead .th {
91+
background-color: $background-white;
92+
color: $black;
93+
}
94+
}
95+
8896
.table__header {
8997
display: flex;
9098
align-items: center;

app/src/js/actions/index.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,14 +291,15 @@ export const applyRecoveryWorkflowToGranule = (granuleId) => (dispatch) => dispa
291291
error
292292
}));
293293

294-
export const reingestGranule = (granuleId) => ({
294+
export const reingestGranule = (granuleId, meta) => ({
295295
[CALL_API]: {
296296
type: types.GRANULE_REINGEST,
297297
method: 'PUT',
298298
id: granuleId,
299299
path: `granules/${granuleId}`,
300300
data: {
301-
action: 'reingest'
301+
action: 'reingest',
302+
...meta,
302303
}
303304
}
304305
});
@@ -742,6 +743,7 @@ export const getExecutionStatus = (arn) => ({
742743
[CALL_API]: {
743744
type: types.EXECUTION_STATUS,
744745
method: 'GET',
746+
id: arn,
745747
url: new URL(`executions/status/${arn}`, root).href
746748
}
747749
});
@@ -766,10 +768,11 @@ export const listExecutions = (options) => (dispatch, getState) => {
766768
});
767769
};
768770

769-
export const listExecutionsByGranule = (payload) => ({
771+
export const listExecutionsByGranule = (granuleId, payload) => ({
770772
[CALL_API]: {
771773
type: types.EXECUTIONS_LIST,
772774
method: 'POST',
775+
id: granuleId,
773776
path: 'executions/search-by-granules',
774777
params: { limit: defaultPageLimit },
775778
data: payload
@@ -781,6 +784,20 @@ export const clearExecutionsFilter = (paramKey) => ({ type: types.CLEAR_EXECUTIO
781784
export const searchExecutions = (infix) => ({ type: types.SEARCH_EXECUTIONS, infix });
782785
export const clearExecutionsSearch = () => ({ type: types.CLEAR_EXECUTIONS_SEARCH });
783786

787+
export const getGranulesWorkflows = (payload) => ({
788+
[CALL_API]: {
789+
type: types.WORKFLOWS_FROM_GRANULES,
790+
method: 'POST',
791+
path: 'executions/workflows-by-granules',
792+
params: { limit: 50 },
793+
data: payload
794+
}
795+
});
796+
797+
export const clearGranulesWorkflows = () => ({ type: types.CLEAR_WORKFLOWS_FROM_GRANULES });
798+
799+
export const getGranulesWorkflowsClearError = () => ({ type: types.WORKFLOWS_FROM_GRANULES_CLEAR_ERROR });
800+
784801
export const listOperations = (options) => (dispatch, getState) => {
785802
const timeFilters = fetchCurrentTimeFilters(getState().datepicker);
786803
return dispatch({

app/src/js/actions/types.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,13 @@ export const EXECUTIONS_LIST = 'EXECUTIONS_LIST';
182182
export const EXECUTIONS_LIST_INFLIGHT = 'EXECUTIONS_INFLIGHT';
183183
export const EXECUTIONS_LIST_ERROR = 'EXECUTIONS_LIST_ERROR';
184184

185+
// Granules executions workflows
186+
export const WORKFLOWS_FROM_GRANULES = 'WORKFLOWS_FROM_GRANULES';
187+
export const WORKFLOWS_FROM_GRANULES_INFLIGHT = 'WORKFLOWS_FROM_GRANULES_INFLIGHT';
188+
export const WORKFLOWS_FROM_GRANULES_ERROR = 'WORKFLOWS_FROM_GRANULES_ERROR';
189+
export const WORKFLOWS_FROM_GRANULES_CLEAR_ERROR = 'WORKFLOWS_FROM_GRANULES_CLEAR_ERROR';
190+
export const CLEAR_WORKFLOWS_FROM_GRANULES = 'CLEAR_WORKFLOWS_FROM_GRANULES';
191+
185192
// Operations
186193
export const OPERATIONS = 'OPERATIONS';
187194
export const OPERATIONS_INFLIGHT = 'OPERATIONS_INFLIGHT';

app/src/js/components/AsyncCommands/AsyncCommands.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ AsyncCommand.propTypes = {
138138
disabled: PropTypes.bool,
139139
element: PropTypes.string,
140140
confirmAction: PropTypes.bool,
141-
confirmText: PropTypes.string,
141+
confirmText: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
142142
confirmOptions: PropTypes.array,
143143
postActionText: PropTypes.string
144144
};

app/src/js/components/BatchAsyncCommands/BatchAsyncCommands.js

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,10 @@ export class BatchCommand extends React.Component {
4343
status: null,
4444
modalOptions: null,
4545
errorMessage: null,
46+
meta: {},
4647
};
4748
this.isRunning = false;
49+
this.buildId = this.buildId.bind(this);
4850
this.confirm = this.confirm.bind(this);
4951
this.cancel = this.cancel.bind(this);
5052
this.start = this.start.bind(this);
@@ -55,10 +57,20 @@ export class BatchCommand extends React.Component {
5557
this.isInflight = this.isInflight.bind(this);
5658
this.handleClick = this.handleClick.bind(this);
5759
this.closeModal = this.closeModal.bind(this);
60+
this.updateMeta = this.updateMeta.bind(this);
61+
}
62+
63+
buildId(item) {
64+
return (typeof item === 'string') ? item : item.granuleId;
65+
}
66+
67+
updateMeta(meta) {
68+
this.setState({ meta: { ...this.state.meta, ...meta } });
5869
}
5970

6071
closeModal() {
6172
this.setState({ activeModal: false });
73+
this.setState({ meta: {} });
6274
}
6375

6476
componentDidUpdate() {
@@ -112,18 +124,18 @@ export class BatchCommand extends React.Component {
112124
if (!Array.isArray(selected) || !selected.length || this.isInflight()) { return false; }
113125
const q = queue(CONCURRENCY);
114126
for (let i = 0; i < selected.length; i += 1) {
115-
q.add(this.initAction, selected[i]);
127+
q.add(this.initAction, this.buildId(selected[i]));
116128
}
117129
q.done(this.onComplete);
118130
}
119131

120132
// save a reference to the callback in state, then init the action
121133
initAction(id, callback) {
122134
const { dispatch, action } = this.props;
123-
const { callbacks } = this.state;
135+
const { callbacks, meta } = this.state;
124136
callbacks[id] = callback;
125137
this.setState({ callbacks });
126-
return dispatch(action(id));
138+
return dispatch(action(id, meta));
127139
}
128140

129141
// immediately change the UI to show either success or error
@@ -173,7 +185,7 @@ export class BatchCommand extends React.Component {
173185
if (results && results.length && typeof onSuccess === 'function') { onSuccess(results, errorMessage); }
174186

175187
if (typeof clearError === 'function') {
176-
selected.forEach((id) => dispatch(clearError(id)));
188+
selected.forEach((item) => dispatch(clearError(this.buildId(item))));
177189
}
178190

179191
this.setState({ activeModal: false, completed: 0, errorMessage: null, results: null, status: null });
@@ -187,6 +199,7 @@ export class BatchCommand extends React.Component {
187199
const { selected, history, getModalOptions } = this.props;
188200
if (typeof getModalOptions === 'function') {
189201
const modalOptions = getModalOptions({
202+
onChange: this.updateMeta,
190203
selected,
191204
history,
192205
closeModal: this.closeModal,

app/src/js/components/Collections/granules.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ const CollectionGranules = ({
5151
const view = getView();
5252
const [workflow, setWorkflow] = useState(workflowOptions[0]);
5353
const [workflowMeta, setWorkflowMeta] = useState(defaultWorkflowMeta);
54+
const [selected, setSelected] = useState([]);
5455
const query = generateQuery();
5556
const { dropdowns } = providers;
5657

@@ -102,7 +103,7 @@ const CollectionGranules = ({
102103
},
103104
};
104105

105-
return bulkActions(granules, actionConfig);
106+
return bulkActions(granules, actionConfig, selected);
106107
}
107108

108109
function selectWorkflow(_selector, selectedWorkflow) {
@@ -128,6 +129,13 @@ const CollectionGranules = ({
128129
];
129130
}
130131

132+
function updateSelection(selectedIds, currentSelectedRows) {
133+
const allSelectedRows = selected.concat(currentSelectedRows);
134+
const selectedRows = selectedIds
135+
.map((id) => allSelectedRows.find((g) => id === g.granuleId)).filter(Boolean);
136+
setSelected(selectedRows);
137+
}
138+
131139
return (
132140
<div className="page__component">
133141
<Helmet>
@@ -159,6 +167,7 @@ const CollectionGranules = ({
159167
tableColumns={tableColumns}
160168
filterAction={filterGranules}
161169
filterClear={clearGranulesFilter}
170+
onSelect={updateSelection}
162171
tableId="granules"
163172
>
164173
<Search

0 commit comments

Comments
 (0)