Commit 07e786e0 authored by Alejandro Celaya's avatar Alejandro Celaya Committed by Alejandro Celaya

Render error toast message if an error occurs when exporting annotations

parent 84bef73b
......@@ -4,6 +4,7 @@ import { useRef } from 'preact/hooks';
import { downloadJSONFile } from '../../../shared/download-json-file';
import { withServices } from '../../service-context';
import type { AnnotationsExporter } from '../../services/annotations-exporter';
import type { ToastMessengerService } from '../../services/toast-messenger';
import { useSidebarStore } from '../../store';
import { suggestedFilename } from '../../util/export-annotations';
import LoadingSpinner from './LoadingSpinner';
......@@ -11,6 +12,7 @@ import LoadingSpinner from './LoadingSpinner';
export type ExportAnnotationsProps = {
// injected
annotationsExporter: AnnotationsExporter;
toastMessenger: ToastMessengerService;
};
// TODO: Validate user-entered filename
......@@ -20,7 +22,10 @@ export type ExportAnnotationsProps = {
* Render content for "export" tab panel: allow user to export annotations
* with a specified filename.
*/
function ExportAnnotations({ annotationsExporter }: ExportAnnotationsProps) {
function ExportAnnotations({
annotationsExporter,
toastMessenger,
}: ExportAnnotationsProps) {
const store = useSidebarStore();
const group = store.focusedGroup();
const exportReady = group && !store.isLoading();
......@@ -35,11 +40,15 @@ function ExportAnnotations({ annotationsExporter }: ExportAnnotationsProps) {
}
const exportAnnotations = () => {
try {
const filename = `${inputRef.current!.value}.json`;
const exportData = annotationsExporter.buildExportContent(
exportableAnnotations,
);
downloadJSONFile(exportData, filename);
} catch (e) {
toastMessenger.error('Exporting annotations failed');
}
};
// Naive simple English pluralization
......@@ -90,4 +99,7 @@ function ExportAnnotations({ annotationsExporter }: ExportAnnotationsProps) {
);
}
export default withServices(ExportAnnotations, ['annotationsExporter']);
export default withServices(ExportAnnotations, [
'annotationsExporter',
'toastMessenger',
]);
......@@ -8,6 +8,7 @@ import ExportAnnotations, { $imports } from '../ExportAnnotations';
describe('ExportAnnotations', () => {
let fakeStore;
let fakeAnnotationsExporter;
let fakeToastMessenger;
let fakeDownloadJSONFile;
const fakePrivateGroup = {
......@@ -20,6 +21,7 @@ describe('ExportAnnotations', () => {
mount(
<ExportAnnotations
annotationsExporter={fakeAnnotationsExporter}
toastMessenger={fakeToastMessenger}
{...props}
/>,
);
......@@ -28,6 +30,9 @@ describe('ExportAnnotations', () => {
fakeAnnotationsExporter = {
buildExportContent: sinon.stub().returns({}),
};
fakeToastMessenger = {
error: sinon.stub(),
};
fakeDownloadJSONFile = sinon.stub();
fakeStore = {
countDrafts: sinon.stub().returns(0),
......@@ -107,6 +112,9 @@ describe('ExportAnnotations', () => {
});
describe('export button clicked', () => {
const clickExportButton = wrapper =>
wrapper.find('button[data-testid="export-button"]').simulate('click');
it('builds an export file from the non-draft annotations', () => {
const wrapper = createComponent();
const annotationsToExport = [
......@@ -115,13 +123,14 @@ describe('ExportAnnotations', () => {
];
fakeStore.savedAnnotations.returns(annotationsToExport);
wrapper.find('button[data-testid="export-button"]').simulate('click');
clickExportButton(wrapper);
assert.calledOnce(fakeAnnotationsExporter.buildExportContent);
assert.calledWith(
fakeAnnotationsExporter.buildExportContent,
annotationsToExport,
);
assert.notCalled(fakeToastMessenger.error);
});
it('downloads a file using user-entered filename appended with `.json`', () => {
......@@ -130,7 +139,7 @@ describe('ExportAnnotations', () => {
wrapper.find('input[data-testid="export-filename"]').getDOMNode().value =
'my-filename';
wrapper.find('button[data-testid="export-button"]').simulate('click');
clickExportButton(wrapper);
assert.calledOnce(fakeDownloadJSONFile);
assert.calledWith(
......@@ -139,6 +148,25 @@ describe('ExportAnnotations', () => {
'my-filename.json',
);
});
context('when exporting annotations fails', () => {
it('displays error toast message', () => {
fakeAnnotationsExporter.buildExportContent.throws(
new Error('Error exporting'),
);
const wrapper = createComponent();
clickExportButton(wrapper);
assert.notCalled(fakeDownloadJSONFile);
assert.calledOnce(fakeAnnotationsExporter.buildExportContent);
assert.calledWith(
fakeToastMessenger.error,
'Exporting annotations failed',
);
});
});
});
context('no annotations available to export', () => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment