@openneuro/app 4.2.3 → 4.3.0-alpha.0
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/jestsetup.ts +0 -5
- package/package.json +8 -13
- package/src/scripts/common/forms/__tests__/__snapshots__/warn-button.spec.jsx.snap +26 -26
- package/src/scripts/common/forms/__tests__/warn-button.spec.jsx +7 -5
- package/src/scripts/datalad/dataset/dataset-query-fragments.js +6 -0
- package/src/scripts/datalad/subscriptions/__tests__/__snapshots__/files-subscription.spec.jsx.snap +1 -159
- package/src/scripts/datalad/subscriptions/__tests__/files-subscription.spec.jsx +6 -3
- package/src/scripts/errors/errorRoute.jsx +4 -23
- package/src/scripts/faq/__tests__/__snapshots__/faq.spec.jsx.snap +183 -154
- package/src/scripts/faq/__tests__/faq.spec.jsx +3 -3
- package/src/scripts/refactor_2021/admin/admin.jsx +1 -7
- package/src/scripts/refactor_2021/dataset/comments/__tests__/__snapshots__/comments.spec.jsx.snap +12 -110
- package/src/scripts/refactor_2021/dataset/comments/__tests__/comments.spec.jsx +7 -5
- package/src/scripts/refactor_2021/dataset/dataset-query.jsx +2 -4
- package/src/scripts/refactor_2021/dataset/dataset-routes.jsx +6 -11
- package/src/scripts/refactor_2021/dataset/download/__tests__/__snapshots__/download-command-line.spec.jsx.snap +8 -9
- package/src/scripts/refactor_2021/dataset/download/__tests__/__snapshots__/download-link.spec.jsx.snap +46 -1255
- package/src/scripts/refactor_2021/dataset/download/__tests__/__snapshots__/shell-example.spec.jsx.snap +3 -4
- package/src/scripts/refactor_2021/dataset/download/__tests__/download-command-line.spec.jsx +10 -11
- package/src/scripts/refactor_2021/dataset/download/__tests__/download-link.spec.jsx +3 -3
- package/src/scripts/refactor_2021/dataset/download/__tests__/shell-example.spec.jsx +3 -3
- package/src/scripts/refactor_2021/dataset/download/download-command-line.jsx +1 -1
- package/src/scripts/refactor_2021/dataset/draft-container.tsx +6 -23
- package/src/scripts/refactor_2021/dataset/draft-snapshot-routes.tsx +1 -6
- package/src/scripts/refactor_2021/dataset/files/__tests__/__snapshots__/file-tree.spec.jsx.snap +24 -49
- package/src/scripts/refactor_2021/dataset/files/__tests__/__snapshots__/file.spec.jsx.snap +74 -54
- package/src/scripts/refactor_2021/dataset/files/__tests__/file-tree-unloaded-directory.spec.jsx +4 -3
- package/src/scripts/refactor_2021/dataset/files/__tests__/file-tree.spec.jsx +23 -19
- package/src/scripts/refactor_2021/dataset/files/__tests__/file-viewer-type.spec.jsx +5 -3
- package/src/scripts/refactor_2021/dataset/files/__tests__/file.spec.jsx +21 -21
- package/src/scripts/refactor_2021/dataset/files/file.jsx +3 -2
- package/src/scripts/refactor_2021/dataset/files/viewers/__tests__/__snapshots__/file-viewer-json.spec.jsx.snap +85 -60
- package/src/scripts/refactor_2021/dataset/files/viewers/__tests__/file-viewer-json.spec.jsx +5 -5
- package/src/scripts/refactor_2021/dataset/fragments/__tests__/__snapshots__/cancel-button.spec.tsx.snap +14 -6
- package/src/scripts/refactor_2021/dataset/fragments/__tests__/__snapshots__/edit-button.spec.tsx.snap +14 -6
- package/src/scripts/refactor_2021/dataset/fragments/__tests__/__snapshots__/save-button.spec.tsx.snap +14 -6
- package/src/scripts/refactor_2021/dataset/fragments/__tests__/__snapshots__/select-input.spec.tsx.snap +178 -105
- package/src/scripts/refactor_2021/dataset/fragments/__tests__/cancel-button.spec.tsx +3 -3
- package/src/scripts/refactor_2021/dataset/fragments/__tests__/dataset-alert-draft.spec.tsx +72 -0
- package/src/scripts/refactor_2021/dataset/fragments/__tests__/edit-button.spec.tsx +3 -3
- package/src/scripts/refactor_2021/dataset/fragments/__tests__/edit-list.spec.jsx +0 -1
- package/src/scripts/refactor_2021/dataset/fragments/__tests__/save-button.spec.tsx +3 -3
- package/src/scripts/refactor_2021/dataset/fragments/__tests__/select-input.spec.tsx +9 -9
- package/src/scripts/refactor_2021/dataset/fragments/dataset-alert-draft.tsx +79 -0
- package/src/scripts/refactor_2021/dataset/fragments/dataset-alert-version.tsx +24 -0
- package/src/scripts/refactor_2021/dataset/fragments/select-input.tsx +1 -1
- package/src/scripts/refactor_2021/dataset/mutations/__tests__/__snapshots__/deprecate-snapshot.spec.tsx.snap +14 -0
- package/src/scripts/refactor_2021/dataset/mutations/__tests__/__snapshots__/deprecate-version.spec.tsx.snap +14 -0
- package/src/scripts/refactor_2021/dataset/mutations/__tests__/__snapshots__/description.spec.jsx.snap +3 -277
- package/src/scripts/refactor_2021/dataset/mutations/__tests__/deprecate-snapshot.spec.tsx +71 -0
- package/src/scripts/refactor_2021/dataset/mutations/__tests__/deprecate-version.spec.tsx +71 -0
- package/src/scripts/refactor_2021/dataset/mutations/__tests__/description.spec.jsx +22 -9
- package/src/scripts/refactor_2021/dataset/mutations/deprecate-version.tsx +46 -0
- package/src/scripts/refactor_2021/dataset/mutations/description.jsx +1 -1
- package/src/scripts/refactor_2021/dataset/mutations/readme.jsx +1 -1
- package/src/scripts/refactor_2021/dataset/mutations/submit-metadata.jsx +1 -1
- package/src/scripts/refactor_2021/dataset/mutations/undo-deprecate-version.tsx +43 -0
- package/src/scripts/refactor_2021/dataset/mutations/update-file.jsx +15 -19
- package/src/scripts/refactor_2021/dataset/routes/__tests__/__snapshots__/publish.spec.jsx.snap +3 -0
- package/src/scripts/refactor_2021/dataset/routes/__tests__/publish.spec.jsx +13 -0
- package/src/scripts/refactor_2021/dataset/routes/add-metadata.jsx +0 -1
- package/src/scripts/refactor_2021/dataset/routes/deprecate-snapshot-page.tsx +46 -0
- package/src/scripts/refactor_2021/dataset/snapshot-container.tsx +19 -23
- package/src/scripts/refactor_2021/routes.tsx +9 -9
- package/src/scripts/refactor_2021/uploader/uploader-setup-routes.jsx +4 -24
- package/src/scripts/refactor_2021/uploader/uploader-status-routes.jsx +1 -6
- package/src/scripts/common/forms/__tests__/__snapshots__/input.spec.jsx.snap +0 -13
- package/src/scripts/common/forms/__tests__/input.spec.jsx +0 -25
- package/src/scripts/common/forms/input.jsx +0 -98
- package/src/scripts/datalad/routes/__tests__/__snapshots__/publish.spec.jsx.snap +0 -14
- package/src/scripts/datalad/routes/__tests__/publish.spec.jsx +0 -10
- package/src/scripts/datalad/routes/mobile-class.tsx +0 -16
- package/src/scripts/datalad/routes/publish.jsx +0 -50
- package/src/scripts/refactor_2021/dataset/dataset-query-fragments.js +0 -220
- package/src/scripts/refactor_2021/dataset/queries/dataset-query-fragments.js +0 -220
|
@@ -1,47 +1,60 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
|
-
import {
|
|
2
|
+
import { render } from '@testing-library/react'
|
|
3
|
+
import { MockedProvider } from '@apollo/client/testing'
|
|
3
4
|
import UpdateDescription, {
|
|
4
5
|
mergeFieldValue,
|
|
5
6
|
UPDATE_DESCRIPTION,
|
|
6
7
|
UPDATE_DESCRIPTION_LIST,
|
|
7
8
|
} from '../description.jsx'
|
|
8
9
|
|
|
10
|
+
const mockMutation = jest.fn()
|
|
11
|
+
jest.mock('@apollo/client/react/components', () => ({
|
|
12
|
+
...jest.requireActual('@apollo/client/react/components'),
|
|
13
|
+
Mutation: props => {
|
|
14
|
+
mockMutation(props)
|
|
15
|
+
return <>Mutation mock</>
|
|
16
|
+
},
|
|
17
|
+
}))
|
|
18
|
+
|
|
9
19
|
describe('UpdateDescription mutation', () => {
|
|
10
20
|
it('renders with common props', () => {
|
|
11
|
-
const
|
|
21
|
+
const { asFragment } = render(
|
|
12
22
|
<UpdateDescription
|
|
13
23
|
datasetId="ds001"
|
|
14
24
|
field="Name"
|
|
15
25
|
value="New Name"
|
|
16
26
|
done={jest.fn()}
|
|
17
27
|
/>,
|
|
28
|
+
{ wrapper: MockedProvider },
|
|
18
29
|
)
|
|
19
|
-
expect(
|
|
30
|
+
expect(asFragment()).toMatchSnapshot()
|
|
20
31
|
})
|
|
21
32
|
it('uses the scalar mutation for scalar values', () => {
|
|
22
|
-
|
|
33
|
+
render(
|
|
23
34
|
<UpdateDescription
|
|
24
35
|
datasetId="ds001"
|
|
25
36
|
field="Name"
|
|
26
37
|
value="New Name"
|
|
27
38
|
done={jest.fn()}
|
|
28
39
|
/>,
|
|
40
|
+
{ wrapper: MockedProvider },
|
|
29
41
|
)
|
|
30
|
-
expect(
|
|
31
|
-
UPDATE_DESCRIPTION,
|
|
42
|
+
expect(mockMutation).toHaveBeenCalledWith(
|
|
43
|
+
expect.objectContaining({ mutation: UPDATE_DESCRIPTION }),
|
|
32
44
|
)
|
|
33
45
|
})
|
|
34
46
|
it('uses the list mutation for array values', () => {
|
|
35
|
-
|
|
47
|
+
render(
|
|
36
48
|
<UpdateDescription
|
|
37
49
|
datasetId="ds001"
|
|
38
50
|
field="Authors"
|
|
39
51
|
value={['John Doe', 'Jane Doe']}
|
|
40
52
|
done={jest.fn()}
|
|
41
53
|
/>,
|
|
54
|
+
{ wrapper: MockedProvider },
|
|
42
55
|
)
|
|
43
|
-
expect(
|
|
44
|
-
UPDATE_DESCRIPTION_LIST,
|
|
56
|
+
expect(mockMutation).toHaveBeenCalledWith(
|
|
57
|
+
expect.objectContaining({ mutation: UPDATE_DESCRIPTION_LIST }),
|
|
45
58
|
)
|
|
46
59
|
})
|
|
47
60
|
describe('mergeFieldValue()', () => {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React, { FC } from 'react'
|
|
2
|
+
import { gql, useMutation } from '@apollo/client'
|
|
3
|
+
import { Button } from '@openneuro/components/button'
|
|
4
|
+
import { useHistory } from 'react-router-dom'
|
|
5
|
+
|
|
6
|
+
export const DEPRECATE_VERSION = gql`
|
|
7
|
+
mutation deprecateSnapshot($datasetId: ID!, $tag: String!, $reason: String!) {
|
|
8
|
+
deprecateSnapshot(datasetId: $datasetId, tag: $tag, reason: $reason) {
|
|
9
|
+
id
|
|
10
|
+
deprecated {
|
|
11
|
+
reason
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
`
|
|
16
|
+
|
|
17
|
+
interface DeprecateVersionProps {
|
|
18
|
+
datasetId: string
|
|
19
|
+
tag: string
|
|
20
|
+
reason: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const DeprecateVersion: FC<DeprecateVersionProps> = ({
|
|
24
|
+
datasetId,
|
|
25
|
+
tag,
|
|
26
|
+
reason,
|
|
27
|
+
}) => {
|
|
28
|
+
const history = useHistory()
|
|
29
|
+
const [DeprecateVersionMutation] = useMutation(DEPRECATE_VERSION)
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<Button
|
|
33
|
+
className="btn-modal-action"
|
|
34
|
+
primary={true}
|
|
35
|
+
label="Deprecate Version"
|
|
36
|
+
size="small"
|
|
37
|
+
onClick={() =>
|
|
38
|
+
DeprecateVersionMutation({
|
|
39
|
+
variables: { datasetId, tag, reason },
|
|
40
|
+
}).then(() => {
|
|
41
|
+
history.push(`/datasets/${datasetId}/versions/${tag}`)
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
/>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
|
|
3
3
|
import { gql } from '@apollo/client'
|
|
4
4
|
import { Mutation } from '@apollo/client/react/components'
|
|
5
5
|
import { SaveButton } from '../fragments/save-button'
|
|
6
|
-
import { DRAFT_FRAGMENT } from '
|
|
6
|
+
import { DRAFT_FRAGMENT } from '../../../datalad/dataset/dataset-query-fragments'
|
|
7
7
|
import { datasetCacheId } from './cache-id.js'
|
|
8
8
|
|
|
9
9
|
export const UPDATE_DESCRIPTION = gql`
|
|
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
|
|
3
3
|
import { gql } from '@apollo/client'
|
|
4
4
|
import { Mutation } from '@apollo/client/react/components'
|
|
5
5
|
import { SaveButton } from '../fragments/save-button'
|
|
6
|
-
import { DRAFT_FRAGMENT } from '
|
|
6
|
+
import { DRAFT_FRAGMENT } from '../../../datalad/dataset/dataset-query-fragments'
|
|
7
7
|
import { datasetCacheId } from './cache-id.js'
|
|
8
8
|
|
|
9
9
|
const UPDATE_README = gql`
|
|
@@ -2,7 +2,7 @@ import React from 'react'
|
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import { gql } from '@apollo/client'
|
|
4
4
|
import { Mutation } from '@apollo/client/react/components'
|
|
5
|
-
import { DATASET_METADATA } from '
|
|
5
|
+
import { DATASET_METADATA } from '../../../datalad/dataset/dataset-query-fragments'
|
|
6
6
|
import { datasetCacheId } from './cache-id.js'
|
|
7
7
|
import { Button } from '@openneuro/components/button'
|
|
8
8
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React, { FC } from 'react'
|
|
2
|
+
import { gql, useMutation } from '@apollo/client'
|
|
3
|
+
import { Button } from '@openneuro/components/button'
|
|
4
|
+
import { Tooltip } from '@openneuro/components/tooltip'
|
|
5
|
+
|
|
6
|
+
const UNDO_DEPRECATE_VERSION = gql`
|
|
7
|
+
mutation undoDeprecateSnapshot($datasetId: ID!, $tag: String!) {
|
|
8
|
+
undoDeprecateSnapshot(datasetId: $datasetId, tag: $tag) {
|
|
9
|
+
id
|
|
10
|
+
deprecated {
|
|
11
|
+
reason
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
`
|
|
16
|
+
|
|
17
|
+
interface UndoDeprecateVersionProps {
|
|
18
|
+
datasetId: string
|
|
19
|
+
tag: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const UndoDeprecateVersion: FC<UndoDeprecateVersionProps> = ({
|
|
23
|
+
datasetId,
|
|
24
|
+
tag,
|
|
25
|
+
}) => {
|
|
26
|
+
const [UndoDeprecateVersion] = useMutation(UNDO_DEPRECATE_VERSION)
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<Tooltip tooltip="Undo Deprecation" flow="right">
|
|
30
|
+
<Button
|
|
31
|
+
icon="fa fa-undo"
|
|
32
|
+
iconOnly
|
|
33
|
+
label="Undo"
|
|
34
|
+
size="xsmall"
|
|
35
|
+
onClick={() =>
|
|
36
|
+
UndoDeprecateVersion({
|
|
37
|
+
variables: { datasetId, tag },
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
/>
|
|
41
|
+
</Tooltip>
|
|
42
|
+
)
|
|
43
|
+
}
|
|
@@ -1,37 +1,33 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import UploaderContext from '../../uploader/uploader-context.js'
|
|
4
|
-
import { Tooltip } from '@openneuro/components/tooltip'
|
|
5
4
|
|
|
6
5
|
const UpdateFile = ({
|
|
7
6
|
datasetId,
|
|
8
7
|
directory = false,
|
|
9
8
|
multiple = false,
|
|
10
9
|
path = null,
|
|
11
|
-
tooltip = '',
|
|
12
10
|
children,
|
|
13
11
|
}) => {
|
|
14
12
|
return (
|
|
15
13
|
<UploaderContext.Consumer>
|
|
16
14
|
{uploader => (
|
|
17
15
|
<div className="edit-file">
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
{children}
|
|
34
|
-
</Tooltip>
|
|
16
|
+
<input
|
|
17
|
+
type="file"
|
|
18
|
+
className="update-file"
|
|
19
|
+
onChange={e => {
|
|
20
|
+
e.preventDefault()
|
|
21
|
+
uploader.resumeDataset(
|
|
22
|
+
datasetId,
|
|
23
|
+
path,
|
|
24
|
+
false,
|
|
25
|
+
)({ files: e.target.files })
|
|
26
|
+
}}
|
|
27
|
+
webkitdirectory={directory && 'true'}
|
|
28
|
+
multiple={multiple && true}
|
|
29
|
+
/>
|
|
30
|
+
{children}
|
|
35
31
|
</div>
|
|
36
32
|
)}
|
|
37
33
|
</UploaderContext.Consumer>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { render } from '@testing-library/react'
|
|
3
|
+
import { MemoryRouter } from 'react-router-dom'
|
|
4
|
+
import Publish from '../publish.jsx'
|
|
5
|
+
|
|
6
|
+
describe('Publish dataset route', () => {
|
|
7
|
+
it('renders with common props', () => {
|
|
8
|
+
const { asFragment } = render(<Publish datasetId="ds00001" />, {
|
|
9
|
+
wrapper: MemoryRouter,
|
|
10
|
+
})
|
|
11
|
+
expect(asFragment).toMatchSnapshot()
|
|
12
|
+
})
|
|
13
|
+
})
|
|
@@ -112,7 +112,6 @@ const AddMetadata = ({ dataset }) => {
|
|
|
112
112
|
const errors = runValidations(newValues)
|
|
113
113
|
if (hasChanged(errors, validationErrors)) setValidationErrors(errors)
|
|
114
114
|
}
|
|
115
|
-
// @ts-expect-error Weak type definition for state
|
|
116
115
|
const submitPath = location.state && location.state.submitPath
|
|
117
116
|
const user = getProfile(cookies)
|
|
118
117
|
const hasEdit =
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
import { Link, useRouteMatch } from 'react-router-dom'
|
|
3
|
+
import { DeprecateVersion } from '../mutations/deprecate-version'
|
|
4
|
+
import { Input } from '@openneuro/components/input'
|
|
5
|
+
import LoggedIn from '../../authentication/logged-in.jsx'
|
|
6
|
+
|
|
7
|
+
interface DeprecateSnapshotRouteParams {
|
|
8
|
+
datasetId: string
|
|
9
|
+
snapshotTag: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const DeprecateSnapshotPage = (): React.ReactElement => {
|
|
13
|
+
const {
|
|
14
|
+
params: { datasetId, snapshotTag },
|
|
15
|
+
} = useRouteMatch<DeprecateSnapshotRouteParams>()
|
|
16
|
+
const [reason, setReason] = useState('')
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<div className="container">
|
|
20
|
+
<h2>Deprecate Version</h2>
|
|
21
|
+
<p>
|
|
22
|
+
{`Deprecate ${datasetId} version ${snapshotTag} to let other users know about an issue with this version. The reason provided will be displayed for users visiting the version.`}
|
|
23
|
+
</p>
|
|
24
|
+
<Input
|
|
25
|
+
placeholder="Explanation for deprecation"
|
|
26
|
+
type="text"
|
|
27
|
+
name="front-page-search"
|
|
28
|
+
labelStyle="default"
|
|
29
|
+
setValue={setReason}
|
|
30
|
+
/>
|
|
31
|
+
<hr />
|
|
32
|
+
<div className="dataset-form-controls">
|
|
33
|
+
<LoggedIn>
|
|
34
|
+
<DeprecateVersion
|
|
35
|
+
datasetId={datasetId}
|
|
36
|
+
tag={snapshotTag}
|
|
37
|
+
reason={reason}
|
|
38
|
+
/>
|
|
39
|
+
</LoggedIn>
|
|
40
|
+
<Link className="return-link" to={`/datasets/${datasetId}`}>
|
|
41
|
+
Return to Dataset
|
|
42
|
+
</Link>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
@@ -12,6 +12,7 @@ import Validation from '../validation/validation.jsx'
|
|
|
12
12
|
import { config } from '../../config'
|
|
13
13
|
import Comments from './comments/comments.jsx'
|
|
14
14
|
import DatasetCitation from './fragments/dataset-citation.jsx'
|
|
15
|
+
import { DatasetAlertVersion } from './fragments/dataset-alert-version'
|
|
15
16
|
|
|
16
17
|
import {
|
|
17
18
|
ModalitiesMetaDataBlock,
|
|
@@ -31,16 +32,16 @@ import { Loading } from '@openneuro/components/loading'
|
|
|
31
32
|
import {
|
|
32
33
|
getUnexpiredProfile,
|
|
33
34
|
hasEditPermissions,
|
|
35
|
+
hasDatasetAdminPermissions,
|
|
34
36
|
} from '../authentication/profile'
|
|
35
37
|
import { useCookies } from 'react-cookie'
|
|
36
|
-
import { Modal } from '@openneuro/components/modal'
|
|
37
38
|
|
|
38
39
|
import { ReadMore } from '@openneuro/components/read-more'
|
|
39
40
|
|
|
40
41
|
import { FollowDataset } from './mutations/follow'
|
|
41
42
|
import { StarDataset } from './mutations/star'
|
|
42
43
|
|
|
43
|
-
import { SNAPSHOT_FIELDS } from '
|
|
44
|
+
import { SNAPSHOT_FIELDS } from '../../datalad/dataset/dataset-query-fragments.js'
|
|
44
45
|
import { DOILink } from './fragments/doi-link'
|
|
45
46
|
|
|
46
47
|
const formatDate = dateObject =>
|
|
@@ -67,8 +68,6 @@ const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
|
|
|
67
68
|
const activeDataset = snapshotVersion(location) || 'draft'
|
|
68
69
|
|
|
69
70
|
const [selectedVersion, setSelectedVersion] = React.useState(activeDataset)
|
|
70
|
-
const [deprecatedmodalIsOpen, setDeprecatedModalIsOpen] =
|
|
71
|
-
React.useState(false)
|
|
72
71
|
|
|
73
72
|
const summary = snapshot.summary
|
|
74
73
|
const description = snapshot.description
|
|
@@ -81,18 +80,15 @@ const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
|
|
|
81
80
|
const dateAddedDifference = formatDistanceToNow(parseISO(dataset.created))
|
|
82
81
|
const dateModified = formatDate(snapshot.created)
|
|
83
82
|
const dateUpdatedDifference = formatDistanceToNow(parseISO(snapshot.created))
|
|
84
|
-
const rootPath = `/datasets/${datasetId}/versions/${activeDataset}`
|
|
85
83
|
|
|
86
|
-
//TODO deprecated needs to be added to the dataset snapshot obj and an admin needs to be able to say a version is deprecated somehow.
|
|
87
84
|
const [cookies] = useCookies()
|
|
88
85
|
const profile = getUnexpiredProfile(cookies)
|
|
89
86
|
const isAdmin = profile?.admin
|
|
90
87
|
const hasEdit =
|
|
91
88
|
hasEditPermissions(dataset.permissions, profile?.sub) || isAdmin
|
|
92
|
-
const
|
|
93
|
-
dataset.
|
|
94
|
-
|
|
95
|
-
dataset.snapshots[dataset.snapshots.length - 1].hexsha
|
|
89
|
+
const isDatasetAdmin =
|
|
90
|
+
hasDatasetAdminPermissions(dataset.permissions, profile?.sub) || isAdmin
|
|
91
|
+
|
|
96
92
|
return (
|
|
97
93
|
<>
|
|
98
94
|
<DatasetPage
|
|
@@ -107,6 +103,18 @@ const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
|
|
|
107
103
|
)}
|
|
108
104
|
</>
|
|
109
105
|
)}
|
|
106
|
+
renderAlert={() => (
|
|
107
|
+
<>
|
|
108
|
+
{snapshot?.deprecated && (
|
|
109
|
+
<DatasetAlertVersion
|
|
110
|
+
datasetId={dataset.id}
|
|
111
|
+
tag={snapshot.tag}
|
|
112
|
+
reason={snapshot.deprecated.reason}
|
|
113
|
+
hasEdit={hasEdit}
|
|
114
|
+
/>
|
|
115
|
+
)}
|
|
116
|
+
</>
|
|
117
|
+
)}
|
|
110
118
|
renderHeaderMeta={() => (
|
|
111
119
|
<>
|
|
112
120
|
{summary && (
|
|
@@ -166,6 +174,7 @@ const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
|
|
|
166
174
|
datasetId={datasetId}
|
|
167
175
|
isSnapshot={true}
|
|
168
176
|
isAdmin={isAdmin}
|
|
177
|
+
isDatasetAdmin={isDatasetAdmin}
|
|
169
178
|
/>
|
|
170
179
|
)}
|
|
171
180
|
renderFiles={() => (
|
|
@@ -233,7 +242,6 @@ const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
|
|
|
233
242
|
dateModified={dateModified}
|
|
234
243
|
selected={selectedVersion}
|
|
235
244
|
setSelected={setSelectedVersion}
|
|
236
|
-
setDeprecatedModalIsOpen={setDeprecatedModalIsOpen}
|
|
237
245
|
/>
|
|
238
246
|
</div>
|
|
239
247
|
}
|
|
@@ -371,18 +379,6 @@ const SnapshotContainer: React.FC<SnapshotContainerProps> = ({
|
|
|
371
379
|
/>
|
|
372
380
|
</>
|
|
373
381
|
)}
|
|
374
|
-
renderDeprecatedModal={() => (
|
|
375
|
-
<Modal
|
|
376
|
-
isOpen={deprecatedmodalIsOpen}
|
|
377
|
-
toggle={() => setDeprecatedModalIsOpen(prevIsOpen => !prevIsOpen)}
|
|
378
|
-
closeText={'close'}
|
|
379
|
-
className="deprecated-modal">
|
|
380
|
-
<p>
|
|
381
|
-
You have selected a deprecated version. The author of the dataset
|
|
382
|
-
does not recommend this specific version.
|
|
383
|
-
</p>
|
|
384
|
-
</Modal>
|
|
385
|
-
)}
|
|
386
382
|
renderComments={() => (
|
|
387
383
|
<Comments
|
|
388
384
|
datasetId={dataset.id}
|
|
@@ -17,15 +17,15 @@ import FourOFourPage from '../errors/404page'
|
|
|
17
17
|
|
|
18
18
|
const Routes: React.VoidFunctionComponent = () => (
|
|
19
19
|
<Switch>
|
|
20
|
-
<Route
|
|
21
|
-
<Route
|
|
22
|
-
<Route
|
|
23
|
-
<Route
|
|
24
|
-
<Route
|
|
25
|
-
<Route
|
|
26
|
-
<Route
|
|
27
|
-
<Route
|
|
28
|
-
<Route
|
|
20
|
+
<Route exact path="/faq" component={FAQS} />
|
|
21
|
+
<Route exact path="/" component={FrontPageContainer} />
|
|
22
|
+
<Route exact path="/keygen" component={APIKey} />
|
|
23
|
+
<Route path="/datasets" component={Dataset} />
|
|
24
|
+
<Route path="/search" component={SearchRoutes} />
|
|
25
|
+
<Route path="/admin" component={Admin} />
|
|
26
|
+
<Route path="/error" component={ErrorRoute} />
|
|
27
|
+
<Route path="/pet" component={PETRedirect} />
|
|
28
|
+
<Route path="/cite" component={Citation} />
|
|
29
29
|
<Redirect from="/public" to="/search" />
|
|
30
30
|
<Redirect from="/saved" to="/search?bookmarks" />
|
|
31
31
|
<Redirect from="/dashboard" to="/search?mydatasets" />
|
|
@@ -14,30 +14,10 @@ const UploaderSetupRoutes = props => (
|
|
|
14
14
|
<div className="tasks-col fade-in">
|
|
15
15
|
<div id="upload-tabs" className="uploader">
|
|
16
16
|
<Switch location={props.location}>
|
|
17
|
-
<Route
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
component={UploadSelect}
|
|
22
|
-
/>
|
|
23
|
-
<Route
|
|
24
|
-
name="upload-issues"
|
|
25
|
-
path="/upload/issues"
|
|
26
|
-
exact
|
|
27
|
-
component={UploadIssues}
|
|
28
|
-
/>
|
|
29
|
-
<Route
|
|
30
|
-
name="upload-metadata"
|
|
31
|
-
path="/upload/metadata"
|
|
32
|
-
exact
|
|
33
|
-
component={UploadMetadata}
|
|
34
|
-
/>
|
|
35
|
-
<Route
|
|
36
|
-
name="upload-disclaimer"
|
|
37
|
-
path="/upload/disclaimer"
|
|
38
|
-
exact
|
|
39
|
-
component={UploadDisclaimer}
|
|
40
|
-
/>
|
|
17
|
+
<Route path="/upload" exact component={UploadSelect} />
|
|
18
|
+
<Route path="/upload/issues" exact component={UploadIssues} />
|
|
19
|
+
<Route path="/upload/metadata" exact component={UploadMetadata} />
|
|
20
|
+
<Route path="/upload/disclaimer" exact component={UploadDisclaimer} />
|
|
41
21
|
</Switch>
|
|
42
22
|
</div>
|
|
43
23
|
</div>
|
|
@@ -9,12 +9,7 @@ const UploaderStatusRoutes = props => (
|
|
|
9
9
|
<div className="tasks-col fade-in">
|
|
10
10
|
<div id="upload-tabs" className="uploader">
|
|
11
11
|
<Switch location={props.location}>
|
|
12
|
-
<Route
|
|
13
|
-
name="upload-status"
|
|
14
|
-
path="/upload"
|
|
15
|
-
exact
|
|
16
|
-
component={UploadStatus}
|
|
17
|
-
/>
|
|
12
|
+
<Route path="/upload" exact component={UploadStatus} />
|
|
18
13
|
</Switch>
|
|
19
14
|
</div>
|
|
20
15
|
</div>
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { shallow, mount } from 'enzyme'
|
|
3
|
-
import Input from '../input'
|
|
4
|
-
|
|
5
|
-
describe('common/forms/Input', () => {
|
|
6
|
-
it('renders successfully', () => {
|
|
7
|
-
const wrapper = shallow(<Input initialValue="test-value" />)
|
|
8
|
-
expect(wrapper).toMatchSnapshot()
|
|
9
|
-
})
|
|
10
|
-
it('resets when remounted', () => {
|
|
11
|
-
const initValue = 'one'
|
|
12
|
-
const newValue = 'two'
|
|
13
|
-
const component = mount(<Input initialValue={initValue} />)
|
|
14
|
-
const input = component.find('input')
|
|
15
|
-
expect(component.state('value')).toBe(initValue)
|
|
16
|
-
|
|
17
|
-
// User types in a value
|
|
18
|
-
input.simulate('change', { target: { value: newValue } })
|
|
19
|
-
expect(component.state('value')).toBe(newValue)
|
|
20
|
-
|
|
21
|
-
// Reset by parent component (cleared)
|
|
22
|
-
component.setProps({ value: initValue })
|
|
23
|
-
expect(component.state('value')).toBe(initValue)
|
|
24
|
-
})
|
|
25
|
-
})
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
// dependencies -------------------------------------------------------
|
|
2
|
-
|
|
3
|
-
import React, { Component } from 'react'
|
|
4
|
-
import PropTypes from 'prop-types'
|
|
5
|
-
|
|
6
|
-
// component setup ----------------------------------------------------
|
|
7
|
-
|
|
8
|
-
class Input extends React.Component {
|
|
9
|
-
// life cycle events --------------------------------------------------
|
|
10
|
-
|
|
11
|
-
constructor(props) {
|
|
12
|
-
super(props)
|
|
13
|
-
this.state = {
|
|
14
|
-
value: props.initialValue ? props.initialValue : '',
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
static getDerivedStateFromProps(nextProps) {
|
|
19
|
-
// Will reset value when prop changes
|
|
20
|
-
if ('value' in nextProps) {
|
|
21
|
-
return { value: nextProps.value }
|
|
22
|
-
} else {
|
|
23
|
-
return null
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
render() {
|
|
28
|
-
const placeholder = this.props.placeholder
|
|
29
|
-
const type = this.props.type
|
|
30
|
-
const name = this.props.name
|
|
31
|
-
const value = this.state.value || this.props.value
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<div
|
|
35
|
-
className={`form-group float-label-input ${
|
|
36
|
-
this.props.containerClass || ''
|
|
37
|
-
}`}>
|
|
38
|
-
{value && value.length > 0 ? <label>{placeholder}</label> : null}
|
|
39
|
-
{this._input(type, name, placeholder, value)}
|
|
40
|
-
</div>
|
|
41
|
-
)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// custom methods -----------------------------------------------------
|
|
45
|
-
|
|
46
|
-
_input(type, name, placeholder, value) {
|
|
47
|
-
if (type === 'textarea') {
|
|
48
|
-
return (
|
|
49
|
-
<textarea
|
|
50
|
-
name={name}
|
|
51
|
-
placeholder={placeholder}
|
|
52
|
-
value={value}
|
|
53
|
-
onChange={this._handleChange.bind(this)}
|
|
54
|
-
/>
|
|
55
|
-
)
|
|
56
|
-
} else {
|
|
57
|
-
return (
|
|
58
|
-
<input
|
|
59
|
-
type={type}
|
|
60
|
-
name={name}
|
|
61
|
-
placeholder={placeholder}
|
|
62
|
-
value={value}
|
|
63
|
-
onChange={this._handleChange.bind(this)}
|
|
64
|
-
disabled={this.props.disabled}
|
|
65
|
-
/>
|
|
66
|
-
)
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
_handleChange(event) {
|
|
71
|
-
this.setState({ value: event.target.value })
|
|
72
|
-
|
|
73
|
-
if (this.props.onChange) {
|
|
74
|
-
this.props.onChange(event)
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
_toggleCheckbox(event) {
|
|
79
|
-
this.setState({ value: event.target.checked })
|
|
80
|
-
if (this.props.onChange) {
|
|
81
|
-
this.props.onChange(event)
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
Input.propTypes = {
|
|
87
|
-
initialValue: PropTypes.string,
|
|
88
|
-
placeholder: PropTypes.string,
|
|
89
|
-
name: PropTypes.string,
|
|
90
|
-
type: PropTypes.string,
|
|
91
|
-
value: PropTypes.node,
|
|
92
|
-
onChange: PropTypes.func,
|
|
93
|
-
disabled: PropTypes.bool,
|
|
94
|
-
checked: PropTypes.bool,
|
|
95
|
-
containerClass: PropTypes.string,
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export default Input
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
-
|
|
3
|
-
exports[`Publish dataset route renders with common props 1`] = `
|
|
4
|
-
<Redirect
|
|
5
|
-
to={
|
|
6
|
-
Object {
|
|
7
|
-
"pathname": "/datasets/ds00001/metadata",
|
|
8
|
-
"state": Object {
|
|
9
|
-
"submitPath": "/datasets/ds00001/publish",
|
|
10
|
-
},
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
/>
|
|
14
|
-
`;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { shallow } from 'enzyme'
|
|
3
|
-
import Publish from '../publish.jsx'
|
|
4
|
-
|
|
5
|
-
describe('Publish dataset route', () => {
|
|
6
|
-
it('renders with common props', () => {
|
|
7
|
-
const wrapper = shallow(<Publish datasetId="ds00001" />)
|
|
8
|
-
expect(wrapper).toMatchSnapshot()
|
|
9
|
-
})
|
|
10
|
-
})
|