Skip to content

Commit dd66399

Browse files
committed
feat(Collection Home): add export collection row option
refactored CommitDetails to work directly with VersionInfo props to make the entire Export modal rely on only a VersionInfo for it's backing data. Also added an export e2e test
1 parent 879dd69 commit dd66399

File tree

7 files changed

+86
-61
lines changed

7 files changed

+86
-61
lines changed

app/components/CommitDetails.tsx

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,27 @@
11
import * as React from 'react'
22
import numeral from 'numeral'
33

4-
import { Structure, Commit } from '../models/dataset'
4+
import { VersionInfo } from '../models/store'
55

66
import Icon from './chrome/Icon'
77
import RelativeTimestamp from './RelativeTimestamp'
88

9-
interface CommitDetailsProps {
10-
structure: Structure
11-
commit: Commit
12-
path: string
13-
}
14-
15-
const CommitDetails: React.FunctionComponent<CommitDetailsProps> = (props) => {
16-
const { structure, commit, path } = props
17-
return (
18-
<>
19-
<span className='dataset-details' style={{ marginBottom: '6px' }}><Icon icon='stickyNote' size='sm' color='medium' />{commit.title}</span>
20-
<div className='dataset-details-container'>
21-
<span className='dataset-details'><Icon icon='commit' size='sm' color='medium' /><span title={path}>{path.substring(path.length - 7)}</span></span>
22-
<span className='dataset-details'><Icon icon='clock' size='sm' color='medium' /><RelativeTimestamp timestamp={commit.timestamp}/></span>
23-
<span className='dataset-details'><Icon icon='hdd' size='sm' color='medium' />{numeral(structure.length).format('0.0b')}</span>
24-
<span className='dataset-details'><Icon icon='bars' size='sm' color='medium' />{numeral(structure.entries).format('0,0')} rows</span>
25-
</div>
26-
</>
27-
)
28-
}
9+
const CommitDetails: React.FunctionComponent<VersionInfo> = ({
10+
commitTitle,
11+
commitTime,
12+
bodySize,
13+
bodyRows,
14+
path
15+
}) => (
16+
<>
17+
{commitTitle && <span className='dataset-details' style={{ marginBottom: '6px' }}><Icon icon='stickyNote' size='sm' color='medium' />{commitTitle}</span>}
18+
<div className='dataset-details-container'>
19+
<span className='dataset-details'><Icon icon='commit' size='sm' color='medium' /><span title={path}>{path.substring(path.length - 7)}</span></span>
20+
<span className='dataset-details'><Icon icon='clock' size='sm' color='medium' /><RelativeTimestamp timestamp={commitTime}/></span>
21+
<span className='dataset-details'><Icon icon='hdd' size='sm' color='medium' />{numeral(bodySize).format('0.0b')}</span>
22+
<span className='dataset-details'><Icon icon='bars' size='sm' color='medium' />{numeral(bodyRows).format('0,0')} rows</span>
23+
</div>
24+
</>
25+
)
2926

3027
export default CommitDetails

app/components/collection/DatasetHeader.tsx

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,22 @@ interface DatasetHeaderProps {
1010
commit: Commit
1111
}
1212

13-
const DatasetHeader: React.FunctionComponent<DatasetHeaderProps> = ({ path, structure, commit }) => {
14-
return (
15-
<div className='commit-details-header'>
16-
{
17-
structure && commit && (
18-
<CommitDetails structure={structure} commit={commit} path={path} />
19-
)
20-
}
21-
</div>
22-
)
23-
}
13+
const DatasetHeader: React.FC<DatasetHeaderProps> = ({
14+
path,
15+
structure,
16+
commit
17+
}) => (
18+
<div className='commit-details-header'>
19+
{structure && commit && (
20+
<CommitDetails
21+
bodyRows={structure.entries}
22+
bodySize={structure.length}
23+
commitTime={commit.timestamp}
24+
commitTitle={commit.title}
25+
path={path}
26+
/>
27+
)}
28+
</div>
29+
)
2430

2531
export default DatasetHeader

app/components/collection/collectionHome/TableRowHamburger.tsx

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,30 @@ interface TableRowHamburgerProps {
1313

1414
const TableRowHamburger: React.FC<TableRowHamburgerProps> = ({ data, setModal }) => {
1515
const { username, name, fsiPath } = data
16-
const actions = [{
17-
icon: 'trash',
18-
text: 'Remove',
19-
onClick: () => {
20-
setModal({
21-
type: ModalType.RemoveDataset,
22-
username,
23-
name,
24-
fsiPath
25-
})
16+
const actions = [
17+
{
18+
icon: 'download',
19+
text: 'Export',
20+
onClick: () => {
21+
setModal({
22+
type: ModalType.ExportDataset,
23+
version: data
24+
})
25+
}
26+
},
27+
{
28+
icon: 'trash',
29+
text: 'Remove',
30+
onClick: () => {
31+
setModal({
32+
type: ModalType.RemoveDataset,
33+
username,
34+
name,
35+
fsiPath
36+
})
37+
}
2638
}
27-
}]
39+
]
2840

2941
return (
3042
<Hamburger id={`${data.username}/${data.name}`} data={actions} />

app/components/modals/ExportDataset.tsx

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,8 @@ import React, { useState } from 'react'
22
import classNames from 'classnames'
33

44
import { dismissModal } from '../../actions/ui'
5-
import { Dataset } from '../../../app/models/dataset'
65
import { ExportDatasetModal } from '../../../app/models/modals'
7-
import { QriRef } from '../../models/qriRef'
8-
import {
9-
selectModal,
10-
selectDatasetRef,
11-
selectDataset
12-
} from '../../selections'
6+
import { selectModal } from '../../selections'
137
import { connectComponentToProps } from '../../utils/connectComponentToProps'
148
import exportDatasetVersion from '../../actions/platformSpecific/export.TARGET_PLATFORM'
159

@@ -21,13 +15,11 @@ import RadioInput from '../form/RadioInput'
2115

2216
interface ExportDatasetProps {
2317
modal: ExportDatasetModal
24-
qriRef: QriRef
25-
dataset: Dataset
2618
onDismissed: () => void
2719
}
2820

2921
export const ExportDatasetComponent: React.FC<ExportDatasetProps> = (props: ExportDatasetProps) => {
30-
const { onDismissed, qriRef, dataset: { structure, commit } } = props
22+
const { onDismissed } = props
3123
const { version } = props.modal
3224

3325
const [dismissable, setDismissable] = useState(true)
@@ -75,10 +67,8 @@ export const ExportDatasetComponent: React.FC<ExportDatasetProps> = (props: Expo
7567
<div className='content'>
7668
<div className='export-dataset-info'>
7769
<div className='dialog-text-small'>
78-
<code style={{ marginBottom: '15px' }}>{qriRef.username}/{qriRef.name}</code><br/>
79-
{structure && commit && (
80-
<CommitDetails commit={commit} structure={structure} path={qriRef.path} />
81-
)}
70+
<code style={{ marginBottom: '15px' }}>{version.username}/{version.name}</code><br/>
71+
<CommitDetails {...version} />
8272
</div>
8373
</div>
8474
<div className='mode-picker'>
@@ -117,9 +107,7 @@ export default connectComponentToProps(
117107
(state: any, ownProps: ExportDatasetProps) => {
118108
return {
119109
...ownProps,
120-
modal: selectModal(state),
121-
qriRef: selectDatasetRef(state),
122-
dataset: selectDataset(state)
110+
modal: selectModal(state)
123111
}
124112
},
125113
{

app/main.development.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,11 @@ app.on('ready', () =>
516516
exportUrl = `${BACKEND_URL}/get/${refString}/body.csv`
517517
}
518518
const win = BrowserWindow.getFocusedWindow()
519-
await download(win, exportUrl, { filename, directory })
519+
await download(win, exportUrl, {
520+
filename,
521+
directory,
522+
openFolderWhenDone: true
523+
})
520524
})
521525

522526
ipcMain.on('block-menus', (e, blockMenus) => {

test/e2e/e2e.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,18 @@ describe('Qri End to End tests', function spec () {
478478
await sendKeys('#dataset-name-input', "Enter")
479479
})
480480

481+
it('export CSV version', async () => {
482+
const { click, delay } = utils
483+
484+
const savePath = path.join(backend.dir, 'body.csv')
485+
await fakeDialog.mock([ { method: 'showSaveDialogSync', value: savePath } ])
486+
487+
await click('#export-dataset')
488+
await click('#submit')
489+
await delay(200) // wait to ensure file has time to write
490+
expect(fs.existsSync(savePath)).toEqual(true)
491+
})
492+
481493
// switch between commits
482494
it('switch between commits', async () => {
483495
const {

test/e2e/e2e_test_flows.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ The following flows deal with launching the app for the first time, signing out
113113
- set a good name
114114
- click away to submit
115115

116+
### export a CSV version
117+
- click the header export dataset button: #export-button
118+
- mock the electron save dialog to send to `TEST_TMP_DIR/body.csv`
119+
- click #submit
120+
- check that a file at `TEST_TMP_DIR/body.csv` exists
121+
116122
### switch between commits
117123
- ensure you are at the correct dataset
118124
- click on each commit #HEAD-3 #HEAD-2 #HEAD-1 #HEAD-0

0 commit comments

Comments
 (0)