@openneuro/app 4.11.0 → 4.12.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -5
- package/src/scripts/apm.js +0 -2
- package/src/scripts/dataset/__tests__/__snapshots__/snapshot-container.spec.tsx.snap +48 -68
- package/src/scripts/dataset/download/download-native.js +77 -30
- package/src/scripts/dataset/download/download-query.js +3 -1
- package/src/scripts/dataset/download/native-file-toast.jsx +24 -6
- package/src/scripts/dataset/files/__tests__/file-tree-unloaded-directory.spec.jsx +4 -16
- package/src/scripts/dataset/files/__tests__/file-tree.spec.jsx +104 -33
- package/src/scripts/dataset/files/file-tree-unloaded-directory.jsx +26 -31
- package/src/scripts/dataset/files/file-tree.tsx +158 -0
- package/src/scripts/dataset/files/file.tsx +2 -2
- package/src/scripts/dataset/files/{files.jsx → files.tsx} +21 -12
- package/src/scripts/types/dataset-file.ts +11 -0
- package/src/scripts/dataset/files/__tests__/file-tree-loading.spec.jsx +0 -18
- package/src/scripts/dataset/files/__tests__/flat-to-tree.spec.js +0 -55
- package/src/scripts/dataset/files/file-tree-loading.jsx +0 -65
- package/src/scripts/dataset/files/file-tree.jsx +0 -126
- package/src/scripts/dataset/files/flat-to-tree.js +0 -49
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import PropTypes from 'prop-types'
|
|
3
|
-
import File from './file'
|
|
4
|
-
import UpdateFile from '../mutations/update-file.jsx'
|
|
5
|
-
import DeleteDir from '../mutations/delete-dir.jsx'
|
|
6
|
-
import FileTreeUnloadedDirectory from './file-tree-unloaded-directory.jsx'
|
|
7
|
-
import { Media } from '../../styles/media'
|
|
8
|
-
import { AccordionTab } from '@openneuro/components/accordion'
|
|
9
|
-
|
|
10
|
-
export const sortByFilename = (a, b) => a.filename.localeCompare(b.filename)
|
|
11
|
-
|
|
12
|
-
export const sortByName = (a, b) => a.name.localeCompare(b.name)
|
|
13
|
-
|
|
14
|
-
export const unescapePath = path => path.replace(/:/g, '/')
|
|
15
|
-
|
|
16
|
-
const isTopLevel = dir => !dir.path.includes(':')
|
|
17
|
-
|
|
18
|
-
const FileTree = ({
|
|
19
|
-
datasetId,
|
|
20
|
-
snapshotTag = null,
|
|
21
|
-
path = '',
|
|
22
|
-
name = '',
|
|
23
|
-
files = [],
|
|
24
|
-
directories = [],
|
|
25
|
-
editMode = false,
|
|
26
|
-
defaultExpanded = false,
|
|
27
|
-
datasetPermissions,
|
|
28
|
-
toggleFileToDelete,
|
|
29
|
-
isFileToBeDeleted,
|
|
30
|
-
bulkDeleteButton,
|
|
31
|
-
}) => {
|
|
32
|
-
return (
|
|
33
|
-
<AccordionTab
|
|
34
|
-
className=""
|
|
35
|
-
label={name}
|
|
36
|
-
accordionStyle="file-tree"
|
|
37
|
-
startOpen={defaultExpanded}>
|
|
38
|
-
{editMode && (
|
|
39
|
-
<Media className="filetree-dir-tools" greaterThanOrEqual="medium">
|
|
40
|
-
<span className="filetree-dir">
|
|
41
|
-
<UpdateFile
|
|
42
|
-
datasetId={datasetId}
|
|
43
|
-
path={unescapePath(path)}
|
|
44
|
-
tooltip={`Choose one or more files to be added to ${name}.`}
|
|
45
|
-
multiple>
|
|
46
|
-
<i className="fa fa-plus" /> Add Files
|
|
47
|
-
</UpdateFile>
|
|
48
|
-
<UpdateFile
|
|
49
|
-
datasetId={datasetId}
|
|
50
|
-
path={unescapePath(path)}
|
|
51
|
-
tooltip={`Choose a folder to be added to ${name}. Adding a folder with an existing name will overwrite that folder.`}
|
|
52
|
-
directory>
|
|
53
|
-
<i className="fa fa-plus" /> Add Directory
|
|
54
|
-
</UpdateFile>
|
|
55
|
-
{bulkDeleteButton || (
|
|
56
|
-
<DeleteDir datasetId={datasetId} path={path} name={name} />
|
|
57
|
-
)}
|
|
58
|
-
</span>
|
|
59
|
-
</Media>
|
|
60
|
-
)}
|
|
61
|
-
<ul className="child-files">
|
|
62
|
-
{files.sort(sortByFilename).map((file, index) => (
|
|
63
|
-
<li className="clearfix filetree-item filetree-file" key={index}>
|
|
64
|
-
<File
|
|
65
|
-
id={file.id}
|
|
66
|
-
datasetId={datasetId}
|
|
67
|
-
snapshotTag={snapshotTag}
|
|
68
|
-
path={path}
|
|
69
|
-
size={file.size}
|
|
70
|
-
editMode={editMode}
|
|
71
|
-
toggleFileToDelete={toggleFileToDelete}
|
|
72
|
-
isFileToBeDeleted={isFileToBeDeleted}
|
|
73
|
-
{...file}
|
|
74
|
-
annexKey={file.key}
|
|
75
|
-
datasetPermissions={datasetPermissions}
|
|
76
|
-
/>
|
|
77
|
-
</li>
|
|
78
|
-
))}
|
|
79
|
-
{directories.sort(sortByName).map((dir, index) => {
|
|
80
|
-
if ('files' in dir || 'directories' in dir) {
|
|
81
|
-
// Loaded directory
|
|
82
|
-
return (
|
|
83
|
-
<li className="clearfix filetree-item filetree-dir" key={index}>
|
|
84
|
-
<FileTree
|
|
85
|
-
datasetId={datasetId}
|
|
86
|
-
snapshotTag={snapshotTag}
|
|
87
|
-
editMode={editMode}
|
|
88
|
-
defaultExpanded={isTopLevel(dir)}
|
|
89
|
-
datasetPermissions={datasetPermissions}
|
|
90
|
-
toggleFileToDelete={toggleFileToDelete}
|
|
91
|
-
isFileToBeDeleted={isFileToBeDeleted}
|
|
92
|
-
{...dir}
|
|
93
|
-
/>
|
|
94
|
-
</li>
|
|
95
|
-
)
|
|
96
|
-
} else {
|
|
97
|
-
// Unloaded
|
|
98
|
-
return (
|
|
99
|
-
<li className="clearfix filetree-item filetree-dir" key={index}>
|
|
100
|
-
<FileTreeUnloadedDirectory
|
|
101
|
-
datasetId={datasetId}
|
|
102
|
-
snapshotTag={snapshotTag}
|
|
103
|
-
directory={dir}
|
|
104
|
-
/>
|
|
105
|
-
</li>
|
|
106
|
-
)
|
|
107
|
-
}
|
|
108
|
-
})}
|
|
109
|
-
</ul>
|
|
110
|
-
</AccordionTab>
|
|
111
|
-
)
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
FileTree.propTypes = {
|
|
115
|
-
datasetId: PropTypes.string,
|
|
116
|
-
files: PropTypes.array,
|
|
117
|
-
snapshotTag: PropTypes.string,
|
|
118
|
-
path: PropTypes.string,
|
|
119
|
-
name: PropTypes.string,
|
|
120
|
-
directories: PropTypes.array,
|
|
121
|
-
editMode: PropTypes.bool,
|
|
122
|
-
defaultExpanded: PropTypes.bool,
|
|
123
|
-
datasetPermissions: PropTypes.object,
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export default FileTree
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Takes an array of files and returns a tree representation
|
|
3
|
-
* @param {array} files
|
|
4
|
-
*/
|
|
5
|
-
export const flatToTree = files => {
|
|
6
|
-
const tree = { name: '', files: [], directories: [] }
|
|
7
|
-
for (const file of files) {
|
|
8
|
-
const pathTokens = file.filename.split('/')
|
|
9
|
-
const lastPath = pathTokens.slice(-1).pop()
|
|
10
|
-
if (pathTokens.length === 1) {
|
|
11
|
-
// Top level file or directory stub
|
|
12
|
-
if (file.directory) {
|
|
13
|
-
tree.directories.push({ ...file, name: file.filename })
|
|
14
|
-
} else {
|
|
15
|
-
tree.files.push({ ...file })
|
|
16
|
-
}
|
|
17
|
-
} else {
|
|
18
|
-
// File in a directory
|
|
19
|
-
let directory = tree
|
|
20
|
-
for (const token of pathTokens) {
|
|
21
|
-
if (token === lastPath) {
|
|
22
|
-
// Leaf (file)
|
|
23
|
-
directory.files.push({
|
|
24
|
-
...file,
|
|
25
|
-
filename: lastPath,
|
|
26
|
-
})
|
|
27
|
-
} else {
|
|
28
|
-
const newDir = directory.directories.find(dir => dir.name === token)
|
|
29
|
-
if (newDir) {
|
|
30
|
-
// Already exists, keep going
|
|
31
|
-
directory = newDir
|
|
32
|
-
} else {
|
|
33
|
-
// Create the missing directory
|
|
34
|
-
const createDir = {
|
|
35
|
-
name: token,
|
|
36
|
-
path: `${(directory.path && directory.path + ':') || ''}${token}`,
|
|
37
|
-
files: [],
|
|
38
|
-
directories: [],
|
|
39
|
-
}
|
|
40
|
-
directory.directories.push(createDir)
|
|
41
|
-
directory = createDir
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
tree.directories
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return tree
|
|
49
|
-
}
|