Skip to content

Commit

Permalink
Programatic download/export for workflow history (#546)
Browse files Browse the repository at this point in the history
* handle export for cross origin

* lint fix

* fix href for export btn

* remove wrong query params to the export get

* change export link to use onclick

* fix blob content

* parse status query param to int (#544)

Co-authored-by: Assem Hafez <assem.a.hafez@gmail.com>

* move chai-spies to dev dependecies

* fix lint

* preserve event target reference in the promise context

* fix lint

---------

Co-authored-by: Assem Hafez <137278762+Assem-Uber@users.noreply.github.com>
  • Loading branch information
Assem-Hafez and Assem-Uber committed Mar 27, 2024
1 parent 9bc4e2f commit f42e164
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 18 deletions.
23 changes: 18 additions & 5 deletions client/containers/workflow-history/component.vue
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ import {
SelectInput,
} from '~components';
import { httpService } from '~services';
export default {
name: 'history',
data() {
Expand Down Expand Up @@ -88,7 +90,6 @@ export default {
'workflowHistoryEventHighlightList',
'workflowHistoryEventHighlightListEnabled',
'workflowId',
'origin',
],
created() {
this.onResizeWindow = debounce(() => {
Expand Down Expand Up @@ -314,6 +315,21 @@ export default {
});
}
},
exportHistory(e) {
const target = e.target;
httpService.get(this.baseAPIURL + '/export').then(historyJson => {
const blob = new Blob([JSON.stringify(historyJson)], {
type: 'application/json',
});
target.href = window.URL.createObjectURL(blob);
target.download = this.exportFilename;
target.click();
});
return false;
},
},
watch: {
eventId(eventId) {
Expand Down Expand Up @@ -398,10 +414,7 @@ export default {
class="show-timeline-btn"
>{{ graphView === GRAPH_VIEW_TIMELINE ? 'hide' : 'show' }} timeline</a
>
<a
class="export"
:href="origin + baseAPIURL + '/export'"
:download="exportFilename"
<a class="export" href="#" @click.once.prevent="exportHistory"
>Export</a
>
</div>
Expand Down
2 changes: 0 additions & 2 deletions client/containers/workflow-history/connector.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,9 @@

import { connect } from 'vuex-connect';
import { WORKFLOW_EXECUTION_PENDING_TASK_COUNT } from '../workflow/getter-types';
import { DOMAIN_CROSS_ORIGIN } from '../domain/getter-types';

const gettersToProps = {
pendingTaskCount: WORKFLOW_EXECUTION_PENDING_TASK_COUNT,
origin: DOMAIN_CROSS_ORIGIN,
};

const stateToProps = {
Expand Down
1 change: 1 addition & 0 deletions client/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ chai.should();
chai.use(require('chai-dom'));
chai.use(require('chai-string'));
chai.use(require('chai-things'));
chai.use(require('chai-spies'));

require('nathanboktae-browser-test-utils');

Expand Down
8 changes: 8 additions & 0 deletions client/test/scenario.js
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,14 @@ Scenario.prototype.withFullHistory = function withFullHistory(events, options) {
.withHistory(parsedEvents.slice(third + third), false, options);
};

Scenario.prototype.withExportHistory = function withExportHistory(events) {
const jsonHistoryEvents = getFixture('history.emailRun1', events);

this.api.getOnce(`${this.execApiBase()}/export`, jsonHistoryEvents);

return this;
};

Scenario.prototype.withQuery = function withQuery(query) {
this.api.getOnce(
`${this.execApiBase()}/query`,
Expand Down
26 changes: 15 additions & 11 deletions client/test/workflow.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -505,13 +505,13 @@ describe('Workflow', () => {
...o,
});

scenario.withFullHistory(opts.events);
scenario.withFullHistory(opts.events).withExportHistory(opts.events);

const historyEl = await scenario
.render(opts.attach)
.waitUntilExists('section.execution.ready');

return [historyEl, scenario];
return [historyEl, scenario, opts];
}
it('should pick default view format from localstorage if exists ', async function test() {
localStorage.setItem('ci-test:history-viewing-format', 'json');
Expand Down Expand Up @@ -570,19 +570,23 @@ describe('Workflow', () => {
});

it('should allow downloading the full history via export', async function test() {
const [, scenario] = await historyTest(this.test);
const [, scenario, opts] = await historyTest(this.test);
const exportEl = await scenario.vm.$el.waitUntilExists(
'section.history .controls a.export'
);
const downloadLink = 'javascript:void(0);'; //prevent createing a redirectable link

exportEl.should.have.attr(
'href',
'http://localhost:8090/api/domains/ci-test/workflows/email-daily-summaries/emailRun1/export'
);
exportEl.should.have.attr(
'download',
'email daily summaries - emailRun1.json'
);
chai.spy.on(window.URL, 'createObjectURL', () => downloadLink);
exportEl.trigger('click');

await retry(() => {
window.URL.createObjectURL.should.have.been.called();
exportEl.should.have.attr('href', downloadLink);
exportEl.should.have.attr(
'download',
'email daily summaries - emailRun1.json'
);
});
});

describe('Compact View', function describeTest() {
Expand Down
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
"babel-jest": "^24.9.0",
"chai": "^4.1.2",
"chai-dom": "^1.7.0",
"chai-spies": "^1.1.0",
"chai-string": "^1.5.0",
"chai-things": "^0.2.0",
"eslint": "^7.32.0",
Expand Down

0 comments on commit f42e164

Please sign in to comment.