Skip to content

Commit

Permalink
Enable support for exporting 1D and 2D dataset slices.
Browse files Browse the repository at this point in the history
  • Loading branch information
mandrew9 authored and axelboc committed Apr 13, 2023
1 parent 2e90ea3 commit 47bdbd7
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 6 deletions.
14 changes: 10 additions & 4 deletions app/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Suspense, useEffect, useState } from 'react';
import { Suspense, useEffect, useState, useMemo } from 'react';
import { useEventListener } from '@react-hookz/web';
import { FileInfo, Message } from './models';
import { isFileInfoMessage } from './utils';
Expand All @@ -7,6 +7,7 @@ import { ErrorBoundary } from 'react-error-boundary';

function App() {
const [fileInfo, setFileInfo] = useState<FileInfo>();
const [vscode, setVsCodeApi] = useState<VsCodeApi>();

useEventListener(window, 'message', (evt: MessageEvent<Message>) => {
const { data: message } = evt;
Expand All @@ -15,9 +16,14 @@ function App() {
}
});

useMemo(() => {
setVsCodeApi(acquireVsCodeApi());
}, [])

useEffect(() => {
const vscode = acquireVsCodeApi();
vscode.postMessage({ type: 'ready' });
if (vscode) {
vscode.postMessage({ type: 'ready' });
}
}, []);

if (!fileInfo) {
Expand All @@ -27,7 +33,7 @@ function App() {
return (
<ErrorBoundary fallbackRender={({ error }) => <p>{error.message}</p>}>
<Suspense fallback={<>Loading...</>}>
<Viewer fileInfo={fileInfo} />
<Viewer fileInfo={fileInfo} vscode={vscode} />
</Suspense>
</ErrorBoundary>
);
Expand Down
63 changes: 61 additions & 2 deletions app/Viewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import { MAX_SIZE_IN_BYTES } from './utils';

interface Props {
fileInfo: FileInfo;
vscode: VsCodeApi | undefined;
}

function Viewer(props: Props) {
const { fileInfo } = props;
const { fileInfo, vscode } = props;

if (fileInfo.size >= MAX_SIZE_IN_BYTES) {
throw new Error(
Expand All @@ -23,7 +24,65 @@ function Viewer(props: Props) {
}, [fileInfo]);

return (
<H5WasmProvider filename={fileInfo.name} buffer={buffer}>
<H5WasmProvider filename={fileInfo.name} buffer={buffer}
getExportURL={(format, dataset, selection, value) => {
if (format === 'csv') {
// Async function that will be called when the user clicks on a `CSV` export menu entry
return async () => {
// Generate CSV string from `value` array
let csv = '';
let dims = [];

// Record all dataset dimensions with cardinality greater than one,
// accounting for subset selection if applicable
if (selection) {
let subsets = selection.split(',')
for (let i = 0; i < subsets.length; i++) {
// Because of the user interface, all slices will either be
// the full array length or a single value
if (subsets[i] === ':' && dataset.shape[i] > 1) {
dims.push(dataset.shape[i])
}
}
} else {
dataset.shape.forEach((val) => {
if (val > 1) dims.push(val)
})
}

// Only provide special handling for 2D dataset outputs
if (dims.length == 2) {
let k = 0
for (let i = 0; i < dims[0]; i++) {
for (let j = 0; j < dims[1] - 1; j++) {
csv += `${value[k].toString()}, `
k++
}

csv += `${value[k].toString()}\n`
k++
}
} else {
value.forEach((val) => {
csv += `${val.toString()}\n`
})
}

const finalCsv = csv.slice(0, -1);

if (vscode) {
vscode.postMessage({
type: 'export',
data: finalCsv,
label: selection
})
}

// Return CSV string as Blob so it can be downloaded
return new Blob([csv]);
};
}
}}>
<App />
</H5WasmProvider>
);
Expand Down
14 changes: 14 additions & 0 deletions src/H5WebViewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import {
CustomDocument,
CustomReadonlyEditorProvider,
ExtensionContext,
window,
Uri,
Webview,
WebviewPanel,
workspace,
} from 'vscode';
import { join, basename } from 'path';
import { writeFileSync } from 'fs';

export default class H5WebViewer
implements CustomReadonlyEditorProvider<CustomDocument>
Expand Down Expand Up @@ -49,6 +51,18 @@ export default class H5WebViewer
size,
},
});
} else if (evt.type === 'export') {
const filename = await window.showSaveDialog({
filters: {
'CSV files (*.csv)': ['csv']
}
})

if (!filename) {
return
}

writeFileSync(filename.fsPath, evt.data)
}
});
}
Expand Down

0 comments on commit 47bdbd7

Please sign in to comment.