cozy-ui 62.7.0 → 62.9.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/CHANGELOG.md CHANGED
@@ -1,3 +1,31 @@
1
+ ## [62.9.1](https://github.com/cozy/cozy-ui/compare/v62.9.0...v62.9.1) (2022-04-21)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * bump convict from 6.0.0 to 6.2.2 ([403c38e](https://github.com/cozy/cozy-ui/commit/403c38e))
7
+
8
+ # [62.9.0](https://github.com/cozy/cozy-ui/compare/v62.8.0...v62.9.0) (2022-04-20)
9
+
10
+
11
+ ### Features
12
+
13
+ * Add makeStyles helper from Mui ([7962227](https://github.com/cozy/cozy-ui/commit/7962227))
14
+
15
+ # [62.8.0](https://github.com/cozy/cozy-ui/compare/v62.7.0...v62.8.0) (2022-04-19)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * **deps:** Piwik-react-router should be a dependency ([ba6130b](https://github.com/cozy/cozy-ui/commit/ba6130b))
21
+
22
+
23
+ ### Features
24
+
25
+ * Add mime-types package ([cc96d4a](https://github.com/cozy/cozy-ui/commit/cc96d4a))
26
+ * Improve FilePicker component ([d52c45d](https://github.com/cozy/cozy-ui/commit/d52c45d)), closes [#2026](https://github.com/cozy/cozy-ui/issues/2026)
27
+ * Update documentation ([dbb6098](https://github.com/cozy/cozy-ui/commit/dbb6098))
28
+
1
29
  # [62.7.0](https://github.com/cozy/cozy-ui/compare/v62.6.0...v62.7.0) (2022-04-14)
2
30
 
3
31
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-ui",
3
- "version": "62.7.0",
3
+ "version": "62.9.1",
4
4
  "description": "Cozy apps UI SDK",
5
5
  "main": "./index.js",
6
6
  "bin": {
@@ -105,6 +105,7 @@
105
105
  "enzyme-adapter-react-16": "1.15.6",
106
106
  "enzyme-to-json": "3.6.2",
107
107
  "eslint-config-cozy-app": "4.0.0",
108
+ "eslint-plugin-prettier": "^4.0.0",
108
109
  "express": "^4.17.1",
109
110
  "focus-trap-react": "^6.0.0",
110
111
  "git-directory-deploy": "1.5.1",
@@ -121,7 +122,6 @@
121
122
  "mini-css-extract-plugin": "0.6.0",
122
123
  "nodemon": "1.19.4",
123
124
  "npm-run-all": "4.1.5",
124
- "piwik-react-router": "0.12.1",
125
125
  "postcss-cli": "6.1.3",
126
126
  "postcss-loader": "2.1.6",
127
127
  "pretty": "2.0.0",
@@ -159,9 +159,11 @@
159
159
  "filesize": "8.0.7",
160
160
  "hammerjs": "^2.0.8",
161
161
  "intersection-observer": "0.11.0",
162
+ "mime-types": "2.1.35",
162
163
  "mui-bottom-sheet": "https://github.com/cozy/mui-bottom-sheet.git#v1.0.6",
163
164
  "node-polyglot": "^2.2.2",
164
165
  "normalize.css": "^8.0.0",
166
+ "piwik-react-router": "0.12.1",
165
167
  "react-markdown": "^4.0.8",
166
168
  "react-pdf": "^4.0.5",
167
169
  "react-popper": "^2.2.3",
@@ -177,11 +179,15 @@
177
179
  "cozy-harvest-lib": "^6.7.3",
178
180
  "cozy-intent": ">=1.3.0",
179
181
  "cozy-sharing": "^3.10.0",
180
- "piwik-react-router": "0.12.1",
181
182
  "puppeteer": "^1.20.0",
182
183
  "react": "^16.8.6",
183
184
  "react-dom": "^16.8.6"
184
185
  },
186
+ "peerDependenciesMeta ": {
187
+ "puppeteer": {
188
+ "optional": true
189
+ }
190
+ },
185
191
  "eslintConfig": {
186
192
  "extends": [
187
193
  "eslint-config-cozy-app"
@@ -40,7 +40,9 @@ const DumbAddContactButton = props => {
40
40
 
41
41
  return (
42
42
  <AppLinker
43
- slug={installedApp ? installedApp.attributes.slug : 'store'}
43
+ app={{
44
+ slug: installedApp ? installedApp.attributes.slug : 'store'
45
+ }}
44
46
  href={href}
45
47
  >
46
48
  {({ onClick, href }) => (
@@ -1,4 +1,4 @@
1
- import React, { useCallback, memo } from 'react'
1
+ import React, { useCallback } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
 
4
4
  import { models, useQuery } from 'cozy-client'
@@ -7,17 +7,18 @@ import LoadMore from '../LoadMore'
7
7
 
8
8
  import { buildContentFolderQuery } from './queries'
9
9
  import FilePickerBodyItem from './FilePickerBodyItem'
10
+ import { isValidFile } from '../helpers/acceptedTypes'
10
11
 
11
12
  const {
12
- file: { isDirectory, isFile }
13
+ file: { isDirectory }
13
14
  } = models
14
15
 
15
16
  const FilePickerBody = ({
16
17
  navigateTo,
17
18
  folderId,
18
- onSelectFileId,
19
- filesIdsSelected,
20
- fileTypesAccepted,
19
+ onSelectItemId,
20
+ itemsIdsSelected,
21
+ itemTypesAccepted,
21
22
  multiple
22
23
  }) => {
23
24
  const contentFolderQuery = buildContentFolderQuery(folderId)
@@ -27,68 +28,68 @@ const FilePickerBody = ({
27
28
  )
28
29
 
29
30
  const onCheck = useCallback(
30
- fileId => {
31
- const isChecked = filesIdsSelected.some(
32
- fileIdSelected => fileIdSelected === fileId
31
+ itemId => {
32
+ const isChecked = itemsIdsSelected.some(
33
+ fileIdSelected => fileIdSelected === itemId
33
34
  )
34
35
  if (isChecked) {
35
- onSelectFileId(
36
- filesIdsSelected.filter(fileIdSelected => fileIdSelected !== fileId)
36
+ onSelectItemId(
37
+ itemsIdsSelected.filter(fileIdSelected => fileIdSelected !== itemId)
37
38
  )
38
- } else onSelectFileId(prev => [...prev, fileId])
39
+ } else onSelectItemId(prev => [...prev, itemId])
39
40
  },
40
- [filesIdsSelected, onSelectFileId]
41
+ [itemsIdsSelected, onSelectItemId]
41
42
  )
42
43
 
43
44
  // When click on checkbox/radio area...
44
45
  const handleChoiceClick = useCallback(
45
- file => () => {
46
- if (multiple) onCheck(file._id)
47
- else onSelectFileId(file._id)
46
+ item => () => {
47
+ if (multiple) onCheck(item._id)
48
+ else onSelectItemId(item._id)
48
49
  },
49
- [multiple, onCheck, onSelectFileId]
50
+ [multiple, onCheck, onSelectItemId]
50
51
  )
51
52
 
52
53
  // ...when click anywhere on the rest of the line
53
54
  const handleListItemClick = useCallback(
54
- file => () => {
55
- if (isDirectory(file)) {
56
- navigateTo(contentFolder.find(f => f._id === file._id))
55
+ item => () => {
56
+ if (isDirectory(item)) {
57
+ navigateTo(contentFolder.find(it => it._id === item._id))
57
58
  }
58
59
 
59
- if (isFile(file) && fileTypesAccepted.file) {
60
- if (multiple) onCheck(file._id)
61
- else onSelectFileId(file._id)
60
+ if (isValidFile(item, itemTypesAccepted)) {
61
+ if (multiple) onCheck(item._id)
62
+ else onSelectItemId(item._id)
62
63
  }
63
64
  },
64
65
  [
65
66
  contentFolder,
66
- fileTypesAccepted.file,
67
+ itemTypesAccepted,
67
68
  multiple,
68
69
  navigateTo,
69
70
  onCheck,
70
- onSelectFileId
71
+ onSelectItemId
71
72
  ]
72
73
  )
73
74
 
74
75
  return (
75
76
  <List>
76
77
  {contentFolder &&
77
- contentFolder.map((file, idx) => {
78
+ contentFolder.map((item, idx) => {
78
79
  const hasDivider = contentFolder
79
80
  ? idx !== contentFolder.length - 1
80
81
  : false
81
82
 
82
83
  return (
83
84
  <FilePickerBodyItem
84
- key={file._id}
85
- file={file}
86
- fileTypesAccepted={fileTypesAccepted}
85
+ key={item._id}
86
+ item={item}
87
+ itemTypesAccepted={itemTypesAccepted}
87
88
  multiple={multiple}
88
89
  handleChoiceClick={handleChoiceClick}
89
90
  handleListItemClick={handleListItemClick}
90
91
  onCheck={onCheck}
91
- filesIdsSelected={filesIdsSelected}
92
+ itemsIdsSelected={itemsIdsSelected}
92
93
  hasDivider={hasDivider}
93
94
  />
94
95
  )
@@ -99,14 +100,11 @@ const FilePickerBody = ({
99
100
  }
100
101
 
101
102
  FilePickerBody.propTypes = {
102
- onSelectFileId: PropTypes.func.isRequired,
103
- filesIdsSelected: PropTypes.arrayOf(PropTypes.string).isRequired,
103
+ onSelectItemId: PropTypes.func.isRequired,
104
+ itemsIdsSelected: PropTypes.arrayOf(PropTypes.string).isRequired,
104
105
  folderId: PropTypes.string.isRequired,
105
106
  navigateTo: PropTypes.func.isRequired,
106
- fileTypesAccepted: PropTypes.exact({
107
- file: PropTypes.bool,
108
- folder: PropTypes.bool
109
- })
107
+ itemTypesAccepted: PropTypes.arrayOf(PropTypes.string).isRequired
110
108
  }
111
109
 
112
- export default memo(FilePickerBody)
110
+ export default FilePickerBody
@@ -1,4 +1,4 @@
1
- import React, { memo } from 'react'
1
+ import React from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import cx from 'classnames'
4
4
  import filesize from 'filesize'
@@ -17,6 +17,8 @@ import Checkbox from '../Checkbox'
17
17
  import Radio from '../Radios'
18
18
  import { useI18n } from '../I18n'
19
19
 
20
+ import { isValidFile, isValidFolder } from '../helpers/acceptedTypes'
21
+
20
22
  import styles from './styles.styl'
21
23
 
22
24
  const {
@@ -37,49 +39,54 @@ const useStyles = makeStyles(() => ({
37
39
  }))
38
40
 
39
41
  const FilePickerBodyItem = ({
40
- file,
41
- fileTypesAccepted,
42
+ item,
43
+ itemTypesAccepted,
42
44
  multiple,
43
45
  handleChoiceClick,
44
46
  handleListItemClick,
45
- filesIdsSelected,
47
+ itemsIdsSelected,
46
48
  hasDivider
47
49
  }) => {
48
50
  const classes = useStyles()
49
51
  const { f } = useI18n()
50
52
  const hasChoice =
51
- (fileTypesAccepted.file && isFile(file)) ||
52
- (fileTypesAccepted.folder && isDirectory(file))
53
+ isValidFile(item, itemTypesAccepted) ||
54
+ isValidFolder(item, itemTypesAccepted)
53
55
 
54
56
  const Input = multiple ? Checkbox : Radio
55
57
 
56
- const listItemSecondaryContent = isFile(file)
57
- ? `${f(file.updated_at, 'DD MMM YYYY')} - ${filesize(file.size, {
58
+ const listItemSecondaryContent = isFile(item)
59
+ ? `${f(item.updated_at, 'DD MMM YYYY')} - ${filesize(item.size, {
58
60
  base: 10
59
61
  })}`
60
62
  : null
61
63
 
62
64
  return (
63
65
  <>
64
- <ListItem button className="u-p-0">
66
+ <ListItem
67
+ disabled={!hasChoice && isFile(item)}
68
+ button
69
+ className="u-p-0"
70
+ data-testid="list-item"
71
+ >
65
72
  <div
66
73
  data-testid="listitem-onclick"
67
74
  className={styles['filePickerBreadcrumb-wrapper']}
68
- onClick={handleListItemClick(file)}
75
+ onClick={handleListItemClick(item)}
69
76
  >
70
77
  <ListItemIcon className={classes.listItemIcon}>
71
78
  <Icon
72
- icon={isDirectory(file) ? FileTypeFolder : FileTypeText}
79
+ icon={isDirectory(item) ? FileTypeFolder : FileTypeText}
73
80
  width="32"
74
81
  height="32"
75
82
  />
76
83
  </ListItemIcon>
77
84
  <ListItemText
78
- primary={file.name}
85
+ primary={item.name}
79
86
  secondary={listItemSecondaryContent}
80
87
  />
81
88
  </div>
82
- {isDirectory(file) && hasChoice && (
89
+ {isDirectory(item) && hasChoice && (
83
90
  <Divider
84
91
  orientation="vertical"
85
92
  flexItem
@@ -89,15 +96,15 @@ const FilePickerBodyItem = ({
89
96
  <div
90
97
  data-testid="choice-onclick"
91
98
  className="u-ph-1 u-pv-half u-h-2 u-flex u-flex-items-center"
92
- onClick={hasChoice ? handleChoiceClick(file) : undefined}
99
+ onClick={hasChoice ? handleChoiceClick(item) : undefined}
93
100
  >
94
101
  <Input
95
102
  data-testid={multiple ? 'checkbox-btn' : 'radio-btn'}
96
103
  onChange={() => {
97
104
  // handled by onClick on the container
98
105
  }}
99
- checked={filesIdsSelected.includes(file._id)}
100
- value={file._id}
106
+ checked={itemsIdsSelected.includes(item._id)}
107
+ value={item._id}
101
108
  className={cx('u-p-0', {
102
109
  'u-o-100': hasChoice,
103
110
  'u-o-0': !hasChoice
@@ -112,16 +119,13 @@ const FilePickerBodyItem = ({
112
119
  }
113
120
 
114
121
  FilePickerBodyItem.propTypes = {
115
- file: PropTypes.object.isRequired,
116
- fileTypesAccepted: PropTypes.exact({
117
- file: PropTypes.bool,
118
- folder: PropTypes.bool
119
- }),
122
+ item: PropTypes.object.isRequired,
123
+ itemTypesAccepted: PropTypes.arrayOf(PropTypes.string).isRequired,
120
124
  multiple: PropTypes.bool,
121
125
  handleChoiceClick: PropTypes.func.isRequired,
122
126
  handleListItemClick: PropTypes.func.isRequired,
123
- filesIdsSelected: PropTypes.arrayOf(PropTypes.string).isRequired,
127
+ itemsIdsSelected: PropTypes.arrayOf(PropTypes.string).isRequired,
124
128
  hasDivider: PropTypes.bool.isRequired
125
129
  }
126
130
 
127
- export default memo(FilePickerBodyItem)
131
+ export default FilePickerBodyItem
@@ -4,11 +4,13 @@ import filesize from 'filesize'
4
4
 
5
5
  import DemoProvider from './docs/DemoProvider'
6
6
  import FilePickerBodyItem from './FilePickerBodyItem'
7
+ import { isValidFile, isValidFolder } from '../helpers/acceptedTypes'
7
8
 
8
9
  const mockFile01 = {
9
10
  _id: '001',
10
11
  type: 'file',
11
- name: 'Filename',
12
+ name: 'Filename.pdf',
13
+ mime: 'application/pdf',
12
14
  updated_at: '2021-01-01T12:00:00.000000+01:00'
13
15
  }
14
16
  const mockFolder01 = {
@@ -19,6 +21,11 @@ const mockFolder01 = {
19
21
  }
20
22
 
21
23
  jest.mock('filesize', () => jest.fn())
24
+ jest.mock('../helpers/acceptedTypes', () => ({
25
+ ...jest.requireActual('../helpers/acceptedTypes'),
26
+ isValidFile: jest.fn(),
27
+ isValidFolder: jest.fn()
28
+ }))
22
29
 
23
30
  describe('FilePickerBodyItem components:', () => {
24
31
  const mockHandleChoiceClick = jest.fn()
@@ -26,19 +33,23 @@ describe('FilePickerBodyItem components:', () => {
26
33
  filesize.mockReturnValue('111Ko')
27
34
 
28
35
  const setup = ({
29
- file = mockFile01,
36
+ item = mockFile01,
30
37
  multiple = false,
31
- fileTypesAccepted = { file: true, folder: false }
32
- }) => {
38
+ validFile = false,
39
+ validFolder = false
40
+ } = {}) => {
41
+ isValidFile.mockReturnValue(validFile)
42
+ isValidFolder.mockReturnValue(validFolder)
43
+
33
44
  return render(
34
45
  <DemoProvider>
35
46
  <FilePickerBodyItem
36
- file={file}
37
- fileTypesAccepted={fileTypesAccepted}
47
+ item={item}
48
+ itemTypesAccepted={[]}
38
49
  multiple={multiple}
39
50
  handleChoiceClick={mockHandleChoiceClick}
40
51
  handleListItemClick={mockHandleListItemClick}
41
- filesIdsSelected={[]}
52
+ itemsIdsSelected={[]}
42
53
  hasDivider={false}
43
54
  />
44
55
  </DemoProvider>
@@ -50,48 +61,71 @@ describe('FilePickerBodyItem components:', () => {
50
61
  })
51
62
 
52
63
  it('should be rendered correctly', () => {
53
- const { container } = setup({})
64
+ const { container } = setup()
54
65
 
55
66
  expect(container).toBeDefined()
56
67
  })
57
68
 
58
69
  it('should display filename', () => {
59
- const { getByText } = setup({})
70
+ const { getByText } = setup()
60
71
 
61
- expect(getByText('Filename'))
72
+ expect(getByText('Filename.pdf'))
62
73
  })
63
74
 
64
75
  it('should display foldername', () => {
65
- const { getByText } = setup({ file: mockFolder01 })
76
+ const { getByText } = setup({ item: mockFolder01 })
66
77
 
67
78
  expect(getByText('Foldername'))
68
79
  })
69
80
 
81
+ it("should item's line is not disabled when has not valid type & is File", () => {
82
+ const { getByTestId } = setup({
83
+ item: mockFile01,
84
+ validFile: false,
85
+ validFolder: false
86
+ })
87
+ const listItem = getByTestId('list-item')
88
+
89
+ expect(listItem).toHaveAttribute('aria-disabled', 'true')
90
+ })
91
+
92
+ it("should item's line is not disabled when has not valid type & is Folder", () => {
93
+ const { getByTestId } = setup({
94
+ item: mockFolder01,
95
+ validFile: false,
96
+ validFolder: false
97
+ })
98
+ const listItem = getByTestId('list-item')
99
+
100
+ expect(listItem).toHaveAttribute('aria-disabled', 'false')
101
+ })
102
+
70
103
  describe('Functions called', () => {
71
104
  it('should call "handleChoiceClick" function when click on checkbox/radio area', () => {
72
- const { getByTestId } = setup({})
105
+ const { getByTestId } = setup({ validFile: true })
73
106
  fireEvent.click(getByTestId('choice-onclick'))
74
107
 
75
108
  expect(mockHandleChoiceClick).toHaveBeenCalled()
76
109
  })
77
110
 
78
111
  it('should NOT call "handleChoiceClick" function when click on checkbox/radio area, if is Folder & not accepted', () => {
79
- const { getByTestId } = setup({ file: mockFolder01 })
112
+ const { getByTestId } = setup({
113
+ item: mockFolder01,
114
+ validFolder: false
115
+ })
80
116
  fireEvent.click(getByTestId('choice-onclick'))
81
117
 
82
118
  expect(mockHandleChoiceClick).not.toHaveBeenCalled()
83
119
  })
84
120
  it('should NOT call "handleChoiceClick" function when click on checkbox/radio area, if is File & not accepted', () => {
85
- const { getByTestId } = setup({
86
- fileTypesAccepted: { file: false, folder: true }
87
- })
121
+ const { getByTestId } = setup({ validFile: false })
88
122
  fireEvent.click(getByTestId('choice-onclick'))
89
123
 
90
124
  expect(mockHandleChoiceClick).not.toHaveBeenCalled()
91
125
  })
92
126
 
93
127
  it('should call "handleListItemClick" function when click on ListItem node', () => {
94
- const { getByTestId } = setup({})
128
+ const { getByTestId } = setup()
95
129
  fireEvent.click(getByTestId('listitem-onclick'))
96
130
 
97
131
  expect(mockHandleListItemClick).toHaveBeenCalled()
@@ -100,7 +134,7 @@ describe('FilePickerBodyItem components:', () => {
100
134
 
101
135
  describe('Attribute "multiple"', () => {
102
136
  it('should radio button exists if "multiple" atribute is False', () => {
103
- const { getByTestId } = setup({})
137
+ const { getByTestId } = setup()
104
138
  const radioBtn = getByTestId('radio-btn')
105
139
  expect(radioBtn).not.toBeNull()
106
140
  })
@@ -114,16 +148,14 @@ describe('FilePickerBodyItem components:', () => {
114
148
 
115
149
  describe('Radio/Checkbox button', () => {
116
150
  it('should disable and not display the Radio button if it is a File and is not accepted', () => {
117
- const { getByTestId } = setup({
118
- fileTypesAccepted: { file: false }
119
- })
151
+ const { getByTestId } = setup({ validFile: false })
120
152
  const radioBtn = getByTestId('radio-btn')
121
153
 
122
154
  expect(radioBtn.getAttribute('disabled')).toBe(null)
123
155
  })
124
156
 
125
157
  it('should disable and not display the Radio button if it is a Folder and is not accepted', () => {
126
- const { getByTestId } = setup({ file: mockFolder01 })
158
+ const { getByTestId } = setup({ item: mockFolder01 })
127
159
  const radioBtn = getByTestId('radio-btn')
128
160
 
129
161
  expect(radioBtn.getAttribute('disabled')).toBe(null)
@@ -12,7 +12,7 @@ initialState = {
12
12
  };
13
13
 
14
14
  const initialVariants = [
15
- { acceptFile: true, acceptFolder: false, multiple: false }
15
+ { acceptFileTXT: false, acceptFileMD: false, acceptFolder: false, multiple: false }
16
16
  ];
17
17
 
18
18
  const toggleFilePicker = () => setState({ filePickerOpened: !state.filePickerOpened });
@@ -20,18 +20,15 @@ const onChange = (fileId) => alert(`ID of file selected : [${fileId}]`);
20
20
  <DemoProvider>
21
21
  <Variants initialVariants={initialVariants} screenshotAllVariants>
22
22
  {variant => {
23
- let acceptRule = ''
24
- if (variant.acceptFile) {
25
- acceptRule = 'file'
26
- if (variant.acceptFolder) {
27
- acceptRule = 'file,folder'
28
- }
23
+ const acceptRule = []
24
+ if (variant.acceptFileMD) {
25
+ acceptRule.push('.md')
26
+ }
27
+ if (variant.acceptFileTXT) {
28
+ acceptRule.push('.txt')
29
29
  }
30
30
  if (variant.acceptFolder) {
31
- acceptRule = 'folder'
32
- if (variant.acceptFile) {
33
- acceptRule = 'folder,file'
34
- }
31
+ acceptRule.push('folder')
35
32
  }
36
33
 
37
34
  return (
@@ -41,7 +38,7 @@ const onChange = (fileId) => alert(`ID of file selected : [${fileId}]`);
41
38
  <FilePicker
42
39
  onClose={toggleFilePicker}
43
40
  onChange={onChange}
44
- accept={acceptRule}
41
+ accept={acceptRule.toString()}
45
42
  multiple={variant.multiple}
46
43
  />
47
44
  )}
@@ -7,22 +7,7 @@ import FilePickerHeader from './FilePickerHeader'
7
7
  import FilePickerFooter from './FilePickerFooter'
8
8
  import FilePickerBody from './FilePickerBody'
9
9
  import useBreakpoints from '../hooks/useBreakpoints'
10
-
11
- /**
12
- * @param {string} fileType - Defines the file types that should be accepted ("file" and/or "folder"), separated by commas
13
- * @returns {{ file: boolean, folder: boolean }}
14
- */
15
- const getFileTypesAccepted = fileType => {
16
- // If accept is falsy, set default to file
17
- const acceptedFileType = fileType
18
- ? fileType.replaceAll(' ', '').split(',')
19
- : ['file']
20
-
21
- return {
22
- file: acceptedFileType.includes('file'),
23
- folder: acceptedFileType.includes('folder')
24
- }
25
- }
10
+ import { getCompliantTypes } from '../helpers/acceptedTypes'
26
11
 
27
12
  const useStyles = makeStyles(() => ({
28
13
  paper: {
@@ -36,23 +21,23 @@ const FilePicker = ({ onClose, onChange, accept, multiple }) => {
36
21
  const { isMobile } = useBreakpoints()
37
22
  const classes = useStyles()
38
23
  const [folderId, setFolderId] = useState(ROOT_DIR_ID)
39
- const [filesIdsSelected, setFilesIdsSelected] = useState([])
24
+ const [itemsIdsSelected, setItemsIdsSelected] = useState([])
40
25
 
41
- const onSelectFileId = fileId => {
26
+ const onSelectItemId = fileId => {
42
27
  if (!multiple) {
43
28
  handleConfirm(null, fileId)
44
29
  } else {
45
- setFilesIdsSelected(fileId)
30
+ setItemsIdsSelected(fileId)
46
31
  }
47
32
  }
48
33
 
49
34
  const navigateTo = folder => setFolderId(folder.id)
50
35
 
51
36
  const handleConfirm = (_, fileId) => {
52
- onChange(fileId ? fileId : filesIdsSelected)
37
+ onChange(fileId ? fileId : itemsIdsSelected)
53
38
  onClose()
54
39
  }
55
- const fileTypesAccepted = getFileTypesAccepted(accept)
40
+ const itemTypesAccepted = getCompliantTypes(accept)
56
41
 
57
42
  return (
58
43
  <FixedDialog
@@ -73,10 +58,10 @@ const FilePicker = ({ onClose, onChange, accept, multiple }) => {
73
58
  content={
74
59
  <FilePickerBody
75
60
  navigateTo={navigateTo}
76
- onSelectFileId={onSelectFileId}
77
- filesIdsSelected={filesIdsSelected}
61
+ onSelectItemId={onSelectItemId}
62
+ itemsIdsSelected={itemsIdsSelected}
78
63
  folderId={folderId}
79
- fileTypesAccepted={fileTypesAccepted}
64
+ itemTypesAccepted={itemTypesAccepted}
80
65
  multiple={multiple}
81
66
  />
82
67
  }
@@ -85,7 +70,7 @@ const FilePicker = ({ onClose, onChange, accept, multiple }) => {
85
70
  <FilePickerFooter
86
71
  onClose={onClose}
87
72
  onConfirm={handleConfirm}
88
- disabledConfirm={filesIdsSelected.length === 0}
73
+ disabledConfirm={itemsIdsSelected.length === 0}
89
74
  />
90
75
  ) : null
91
76
  }
@@ -101,7 +86,7 @@ FilePicker.propTypes = {
101
86
  }
102
87
 
103
88
  FilePicker.defaultProps = {
104
- accept: 'file',
89
+ accept: '',
105
90
  multiple: false
106
91
  }
107
92
 
@@ -1,16 +1,21 @@
1
1
  import React from 'react'
2
2
  import Icon from '../Icon'
3
+ import FileTypeAudioIcon from '../Icons/FileTypeAudio'
3
4
 
4
5
  import withFileUrl from './withFileUrl'
5
6
  import styles from './styles.styl'
6
7
 
7
- import FileTypeAudioIcon from 'cozy-ui/transpiled/react/Icons/FileTypeAudio'
8
+ import isTesting from '../../react/helpers/isTesting'
8
9
 
9
10
  const AudioViewer = ({ file, url }) => (
10
11
  <div className={styles['viewer-audioviewer']}>
11
12
  <Icon icon={FileTypeAudioIcon} width={160} height={140} />
12
13
  <p className={styles['viewer-filename']}>{file.name}</p>
13
- <audio src={url} controls="controls" />
14
+ <audio
15
+ src={url}
16
+ controls="controls"
17
+ preload={isTesting() ? 'none' : 'auto'}
18
+ />
14
19
  </div>
15
20
  )
16
21
 
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
3
3
  import cx from 'classnames'
4
4
 
5
5
  import Icon from '../Icon'
6
- import { default as ArrowIcon } from 'cozy-ui/transpiled/react/Icons/DropdownClose'
6
+ import { default as ArrowIcon } from '../Icons/DropdownClose'
7
7
 
8
8
  import styles from './styles.styl'
9
9
 
@@ -35,6 +35,7 @@ exports[`AudioViewer should render a spinner then the audio viewer 1`] = `
35
35
  </p>
36
36
  <audio
37
37
  controls=""
38
+ preload="auto"
38
39
  src="https://viewerdemo.cozycloud.cc/Z.mp3"
39
40
  />
40
41
  </div>
@@ -0,0 +1,50 @@
1
+ import mimeTypes from 'mime-types'
2
+
3
+ import { models } from 'cozy-client'
4
+
5
+ const {
6
+ file: { isDirectory, isFile }
7
+ } = models
8
+
9
+ /**
10
+ * @param {string} types - Types we wish to accept ("folder" and/or "extensions/mime" of file), separated by commas
11
+ * @returns {string[]} All the valid types, if the parameter is undefined or if no type is valid, return an empty array
12
+ */
13
+ export const getCompliantTypes = types => {
14
+ if (types) {
15
+ return types
16
+ .replaceAll(' ', '')
17
+ .split(',')
18
+ .filter(type =>
19
+ type !== 'folder' ? !!mimeTypes.contentType(type) : true
20
+ )
21
+ }
22
+
23
+ return []
24
+ }
25
+
26
+ /**
27
+ * Check if Item is a file with accepted extension/mime
28
+ *
29
+ * @param {object} item - file or folder
30
+ * @param {string[]} validTypes - List of accepted types
31
+ * @returns {boolean}
32
+ */
33
+ export const isValidFile = (item, validTypes) => {
34
+ const fileTypesAccepted =
35
+ validTypes.includes(`.${item.name.split('.').pop()}`) ||
36
+ validTypes.includes(item.mime)
37
+
38
+ return isFile(item) && (fileTypesAccepted || validTypes.length === 0)
39
+ }
40
+
41
+ /**
42
+ * Check if Item is a folder with accepted type
43
+ *
44
+ * @param {object} item - file or folder
45
+ * @param {string[]} validTypes - List of accepted types
46
+ * @returns {boolean}
47
+ */
48
+ export const isValidFolder = (item, validTypes) => {
49
+ return isDirectory(item) && validTypes.includes(`folder`)
50
+ }
@@ -0,0 +1,86 @@
1
+ import { isValidFile, isValidFolder, getCompliantTypes } from './acceptedTypes'
2
+
3
+ const makeMockFile = ({
4
+ extension = '.pdf',
5
+ mime = 'application/pdf'
6
+ } = {}) => ({
7
+ _id: '123',
8
+ type: 'file',
9
+ mime: mime,
10
+ name: `mockFile${extension}`
11
+ })
12
+ const makeMockFolder = () => ({
13
+ _id: '789',
14
+ type: 'directory',
15
+ name: 'mockDir'
16
+ })
17
+
18
+ describe('acceptedTypes', () => {
19
+ describe('getCompliantTypes', () => {
20
+ it('should an array with all valid types', () => {
21
+ const res = getCompliantTypes('.pdf, text/plain, .not')
22
+
23
+ expect(res).toStrictEqual(['.pdf', 'text/plain'])
24
+ })
25
+ })
26
+
27
+ describe('isValidFile', () => {
28
+ it('should be valid when item has no type providen', () => {
29
+ const item = makeMockFile()
30
+ const validTypesAccepted = []
31
+
32
+ expect(isValidFile(item, validTypesAccepted)).toBe(true)
33
+ })
34
+
35
+ it('should be valid when item has an accepted extension', () => {
36
+ const item = makeMockFile({ extension: '.png' })
37
+ const validTypesAccepted = ['.png', '.pdf']
38
+
39
+ expect(isValidFile(item, validTypesAccepted)).toBe(true)
40
+ })
41
+
42
+ it('should not be valid when item has not an accepted extension', () => {
43
+ const item = makeMockFile({ extension: '.png' })
44
+ const validTypesAccepted = ['.pdf']
45
+
46
+ expect(isValidFile(item, validTypesAccepted)).toBe(false)
47
+ })
48
+
49
+ it('should be valid when item has an accepted mime', () => {
50
+ const item = makeMockFile({ mime: 'image/png' })
51
+ const validTypesAccepted = ['application/pdf', 'image/png']
52
+
53
+ expect(isValidFile(item, validTypesAccepted)).toBe(true)
54
+ })
55
+
56
+ it('should not be valid when item has not an accepted mime', () => {
57
+ const item = makeMockFile({ mime: 'image/png' })
58
+ const validTypesAccepted = ['application/pdf']
59
+
60
+ expect(isValidFile(item, validTypesAccepted)).toBe(false)
61
+ })
62
+
63
+ it('should not be valid when item is not an file', () => {
64
+ const item = makeMockFolder()
65
+ const validTypesAccepted = []
66
+
67
+ expect(isValidFile(item, validTypesAccepted)).toBe(false)
68
+ })
69
+ })
70
+
71
+ describe('isValidFolder', () => {
72
+ it('should be valid when item is an folder', () => {
73
+ const item = makeMockFolder()
74
+ const validTypesAccepted = ['folder']
75
+
76
+ expect(isValidFolder(item, validTypesAccepted)).toBe(true)
77
+ })
78
+
79
+ it('should not be valid when item is not an folder', () => {
80
+ const item = makeMockFile()
81
+ const validTypesAccepted = ['folder']
82
+
83
+ expect(isValidFolder(item, validTypesAccepted)).toBe(false)
84
+ })
85
+ })
86
+ })
@@ -0,0 +1,2 @@
1
+ import { makeStyles } from '@material-ui/core/styles'
2
+ export default makeStyles
package/react/index.js CHANGED
@@ -28,6 +28,7 @@ export { default as AccordionSummary } from './MuiCozyTheme/AccordionSummary'
28
28
  export { default as AccordionDetails } from './MuiCozyTheme/AccordionDetails'
29
29
  export { default as Toggle } from './Toggle'
30
30
  export { default as withBreakpoints } from './helpers/withBreakpoints'
31
+ export { default as makeStyles } from './helpers/makeStyles'
31
32
  export { default as useBreakpoints } from './hooks/useBreakpoints'
32
33
  export { default as useBrowserOffline } from './hooks/useBrowserOffline'
33
34
  export { Media, Img, Bd } from './Media'
@@ -39,7 +39,9 @@ var DumbAddContactButton = function DumbAddContactButton(props) {
39
39
  }
40
40
 
41
41
  return /*#__PURE__*/React.createElement(AppLinker, {
42
- slug: installedApp ? installedApp.attributes.slug : 'store',
42
+ app: {
43
+ slug: installedApp ? installedApp.attributes.slug : 'store'
44
+ },
43
45
  href: href
44
46
  }, function (_ref) {
45
47
  var onClick = _ref.onClick,
@@ -1,21 +1,20 @@
1
1
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
- import React, { useCallback, memo } from 'react';
2
+ import React, { useCallback } from 'react';
3
3
  import PropTypes from 'prop-types';
4
4
  import { models, useQuery } from 'cozy-client';
5
5
  import List from "cozy-ui/transpiled/react/MuiCozyTheme/List";
6
6
  import LoadMore from "cozy-ui/transpiled/react/LoadMore";
7
7
  import { buildContentFolderQuery } from "cozy-ui/transpiled/react/FilePicker/queries";
8
8
  import FilePickerBodyItem from "cozy-ui/transpiled/react/FilePicker/FilePickerBodyItem";
9
- var _models$file = models.file,
10
- isDirectory = _models$file.isDirectory,
11
- isFile = _models$file.isFile;
9
+ import { isValidFile } from "cozy-ui/transpiled/react/helpers/acceptedTypes";
10
+ var isDirectory = models.file.isDirectory;
12
11
 
13
12
  var FilePickerBody = function FilePickerBody(_ref) {
14
13
  var navigateTo = _ref.navigateTo,
15
14
  folderId = _ref.folderId,
16
- onSelectFileId = _ref.onSelectFileId,
17
- filesIdsSelected = _ref.filesIdsSelected,
18
- fileTypesAccepted = _ref.fileTypesAccepted,
15
+ onSelectItemId = _ref.onSelectItemId,
16
+ itemsIdsSelected = _ref.itemsIdsSelected,
17
+ itemTypesAccepted = _ref.itemTypesAccepted,
19
18
  multiple = _ref.multiple;
20
19
  var contentFolderQuery = buildContentFolderQuery(folderId);
21
20
 
@@ -24,50 +23,50 @@ var FilePickerBody = function FilePickerBody(_ref) {
24
23
  hasMore = _useQuery.hasMore,
25
24
  fetchMore = _useQuery.fetchMore;
26
25
 
27
- var onCheck = useCallback(function (fileId) {
28
- var isChecked = filesIdsSelected.some(function (fileIdSelected) {
29
- return fileIdSelected === fileId;
26
+ var onCheck = useCallback(function (itemId) {
27
+ var isChecked = itemsIdsSelected.some(function (fileIdSelected) {
28
+ return fileIdSelected === itemId;
30
29
  });
31
30
 
32
31
  if (isChecked) {
33
- onSelectFileId(filesIdsSelected.filter(function (fileIdSelected) {
34
- return fileIdSelected !== fileId;
32
+ onSelectItemId(itemsIdsSelected.filter(function (fileIdSelected) {
33
+ return fileIdSelected !== itemId;
35
34
  }));
36
- } else onSelectFileId(function (prev) {
37
- return [].concat(_toConsumableArray(prev), [fileId]);
35
+ } else onSelectItemId(function (prev) {
36
+ return [].concat(_toConsumableArray(prev), [itemId]);
38
37
  });
39
- }, [filesIdsSelected, onSelectFileId]); // When click on checkbox/radio area...
38
+ }, [itemsIdsSelected, onSelectItemId]); // When click on checkbox/radio area...
40
39
 
41
- var handleChoiceClick = useCallback(function (file) {
40
+ var handleChoiceClick = useCallback(function (item) {
42
41
  return function () {
43
- if (multiple) onCheck(file._id);else onSelectFileId(file._id);
42
+ if (multiple) onCheck(item._id);else onSelectItemId(item._id);
44
43
  };
45
- }, [multiple, onCheck, onSelectFileId]); // ...when click anywhere on the rest of the line
44
+ }, [multiple, onCheck, onSelectItemId]); // ...when click anywhere on the rest of the line
46
45
 
47
- var handleListItemClick = useCallback(function (file) {
46
+ var handleListItemClick = useCallback(function (item) {
48
47
  return function () {
49
- if (isDirectory(file)) {
50
- navigateTo(contentFolder.find(function (f) {
51
- return f._id === file._id;
48
+ if (isDirectory(item)) {
49
+ navigateTo(contentFolder.find(function (it) {
50
+ return it._id === item._id;
52
51
  }));
53
52
  }
54
53
 
55
- if (isFile(file) && fileTypesAccepted.file) {
56
- if (multiple) onCheck(file._id);else onSelectFileId(file._id);
54
+ if (isValidFile(item, itemTypesAccepted)) {
55
+ if (multiple) onCheck(item._id);else onSelectItemId(item._id);
57
56
  }
58
57
  };
59
- }, [contentFolder, fileTypesAccepted.file, multiple, navigateTo, onCheck, onSelectFileId]);
60
- return /*#__PURE__*/React.createElement(List, null, contentFolder && contentFolder.map(function (file, idx) {
58
+ }, [contentFolder, itemTypesAccepted, multiple, navigateTo, onCheck, onSelectItemId]);
59
+ return /*#__PURE__*/React.createElement(List, null, contentFolder && contentFolder.map(function (item, idx) {
61
60
  var hasDivider = contentFolder ? idx !== contentFolder.length - 1 : false;
62
61
  return /*#__PURE__*/React.createElement(FilePickerBodyItem, {
63
- key: file._id,
64
- file: file,
65
- fileTypesAccepted: fileTypesAccepted,
62
+ key: item._id,
63
+ item: item,
64
+ itemTypesAccepted: itemTypesAccepted,
66
65
  multiple: multiple,
67
66
  handleChoiceClick: handleChoiceClick,
68
67
  handleListItemClick: handleListItemClick,
69
68
  onCheck: onCheck,
70
- filesIdsSelected: filesIdsSelected,
69
+ itemsIdsSelected: itemsIdsSelected,
71
70
  hasDivider: hasDivider
72
71
  });
73
72
  }), hasMore && /*#__PURE__*/React.createElement(LoadMore, {
@@ -77,13 +76,10 @@ var FilePickerBody = function FilePickerBody(_ref) {
77
76
  };
78
77
 
79
78
  FilePickerBody.propTypes = {
80
- onSelectFileId: PropTypes.func.isRequired,
81
- filesIdsSelected: PropTypes.arrayOf(PropTypes.string).isRequired,
79
+ onSelectItemId: PropTypes.func.isRequired,
80
+ itemsIdsSelected: PropTypes.arrayOf(PropTypes.string).isRequired,
82
81
  folderId: PropTypes.string.isRequired,
83
82
  navigateTo: PropTypes.func.isRequired,
84
- fileTypesAccepted: PropTypes.exact({
85
- file: PropTypes.bool,
86
- folder: PropTypes.bool
87
- })
83
+ itemTypesAccepted: PropTypes.arrayOf(PropTypes.string).isRequired
88
84
  };
89
- export default /*#__PURE__*/memo(FilePickerBody);
85
+ export default FilePickerBody;
@@ -1,4 +1,4 @@
1
- import React, { memo } from 'react';
1
+ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import cx from 'classnames';
4
4
  import filesize from 'filesize';
@@ -14,6 +14,7 @@ import FileTypeFolder from "cozy-ui/transpiled/react/Icons/FileTypeFolder";
14
14
  import Checkbox from "cozy-ui/transpiled/react/Checkbox";
15
15
  import Radio from "cozy-ui/transpiled/react/Radios";
16
16
  import { useI18n } from "cozy-ui/transpiled/react/I18n";
17
+ import { isValidFile, isValidFolder } from "cozy-ui/transpiled/react/helpers/acceptedTypes";
17
18
  var styles = {
18
19
  "filePickerBreadcrumb-previousPath": "styles__filePickerBreadcrumb-previousPath___3LKJH",
19
20
  "filePickerBreadcrumb-icon": "styles__filePickerBreadcrumb-icon___3aFyd",
@@ -38,53 +39,55 @@ var useStyles = makeStyles(function () {
38
39
  });
39
40
 
40
41
  var FilePickerBodyItem = function FilePickerBodyItem(_ref) {
41
- var file = _ref.file,
42
- fileTypesAccepted = _ref.fileTypesAccepted,
42
+ var item = _ref.item,
43
+ itemTypesAccepted = _ref.itemTypesAccepted,
43
44
  multiple = _ref.multiple,
44
45
  handleChoiceClick = _ref.handleChoiceClick,
45
46
  handleListItemClick = _ref.handleListItemClick,
46
- filesIdsSelected = _ref.filesIdsSelected,
47
+ itemsIdsSelected = _ref.itemsIdsSelected,
47
48
  hasDivider = _ref.hasDivider;
48
49
  var classes = useStyles();
49
50
 
50
51
  var _useI18n = useI18n(),
51
52
  f = _useI18n.f;
52
53
 
53
- var hasChoice = fileTypesAccepted.file && isFile(file) || fileTypesAccepted.folder && isDirectory(file);
54
+ var hasChoice = isValidFile(item, itemTypesAccepted) || isValidFolder(item, itemTypesAccepted);
54
55
  var Input = multiple ? Checkbox : Radio;
55
- var listItemSecondaryContent = isFile(file) ? "".concat(f(file.updated_at, 'DD MMM YYYY'), " - ").concat(filesize(file.size, {
56
+ var listItemSecondaryContent = isFile(item) ? "".concat(f(item.updated_at, 'DD MMM YYYY'), " - ").concat(filesize(item.size, {
56
57
  base: 10
57
58
  })) : null;
58
59
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ListItem, {
60
+ disabled: !hasChoice && isFile(item),
59
61
  button: true,
60
- className: "u-p-0"
62
+ className: "u-p-0",
63
+ "data-testid": "list-item"
61
64
  }, /*#__PURE__*/React.createElement("div", {
62
65
  "data-testid": "listitem-onclick",
63
66
  className: styles['filePickerBreadcrumb-wrapper'],
64
- onClick: handleListItemClick(file)
67
+ onClick: handleListItemClick(item)
65
68
  }, /*#__PURE__*/React.createElement(ListItemIcon, {
66
69
  className: classes.listItemIcon
67
70
  }, /*#__PURE__*/React.createElement(Icon, {
68
- icon: isDirectory(file) ? FileTypeFolder : FileTypeText,
71
+ icon: isDirectory(item) ? FileTypeFolder : FileTypeText,
69
72
  width: "32",
70
73
  height: "32"
71
74
  })), /*#__PURE__*/React.createElement(ListItemText, {
72
- primary: file.name,
75
+ primary: item.name,
73
76
  secondary: listItemSecondaryContent
74
- })), isDirectory(file) && hasChoice && /*#__PURE__*/React.createElement(Divider, {
77
+ })), isDirectory(item) && hasChoice && /*#__PURE__*/React.createElement(Divider, {
75
78
  orientation: "vertical",
76
79
  flexItem: true,
77
80
  className: classes.verticalDivider
78
81
  }), /*#__PURE__*/React.createElement("div", {
79
82
  "data-testid": "choice-onclick",
80
83
  className: "u-ph-1 u-pv-half u-h-2 u-flex u-flex-items-center",
81
- onClick: hasChoice ? handleChoiceClick(file) : undefined
84
+ onClick: hasChoice ? handleChoiceClick(item) : undefined
82
85
  }, /*#__PURE__*/React.createElement(Input, {
83
86
  "data-testid": multiple ? 'checkbox-btn' : 'radio-btn',
84
87
  onChange: function onChange() {// handled by onClick on the container
85
88
  },
86
- checked: filesIdsSelected.includes(file._id),
87
- value: file._id,
89
+ checked: itemsIdsSelected.includes(item._id),
90
+ value: item._id,
88
91
  className: cx('u-p-0', {
89
92
  'u-o-100': hasChoice,
90
93
  'u-o-0': !hasChoice
@@ -96,15 +99,12 @@ var FilePickerBodyItem = function FilePickerBodyItem(_ref) {
96
99
  };
97
100
 
98
101
  FilePickerBodyItem.propTypes = {
99
- file: PropTypes.object.isRequired,
100
- fileTypesAccepted: PropTypes.exact({
101
- file: PropTypes.bool,
102
- folder: PropTypes.bool
103
- }),
102
+ item: PropTypes.object.isRequired,
103
+ itemTypesAccepted: PropTypes.arrayOf(PropTypes.string).isRequired,
104
104
  multiple: PropTypes.bool,
105
105
  handleChoiceClick: PropTypes.func.isRequired,
106
106
  handleListItemClick: PropTypes.func.isRequired,
107
- filesIdsSelected: PropTypes.arrayOf(PropTypes.string).isRequired,
107
+ itemsIdsSelected: PropTypes.arrayOf(PropTypes.string).isRequired,
108
108
  hasDivider: PropTypes.bool.isRequired
109
109
  };
110
- export default /*#__PURE__*/memo(FilePickerBodyItem);
110
+ export default FilePickerBodyItem;
@@ -7,20 +7,7 @@ import FilePickerHeader from "cozy-ui/transpiled/react/FilePicker/FilePickerHead
7
7
  import FilePickerFooter from "cozy-ui/transpiled/react/FilePicker/FilePickerFooter";
8
8
  import FilePickerBody from "cozy-ui/transpiled/react/FilePicker/FilePickerBody";
9
9
  import useBreakpoints from "cozy-ui/transpiled/react/hooks/useBreakpoints";
10
- /**
11
- * @param {string} fileType - Defines the file types that should be accepted ("file" and/or "folder"), separated by commas
12
- * @returns {{ file: boolean, folder: boolean }}
13
- */
14
-
15
- var getFileTypesAccepted = function getFileTypesAccepted(fileType) {
16
- // If accept is falsy, set default to file
17
- var acceptedFileType = fileType ? fileType.replaceAll(' ', '').split(',') : ['file'];
18
- return {
19
- file: acceptedFileType.includes('file'),
20
- folder: acceptedFileType.includes('folder')
21
- };
22
- };
23
-
10
+ import { getCompliantTypes } from "cozy-ui/transpiled/react/helpers/acceptedTypes";
24
11
  var useStyles = makeStyles(function () {
25
12
  return {
26
13
  paper: {
@@ -48,14 +35,14 @@ var FilePicker = function FilePicker(_ref) {
48
35
 
49
36
  var _useState3 = useState([]),
50
37
  _useState4 = _slicedToArray(_useState3, 2),
51
- filesIdsSelected = _useState4[0],
52
- setFilesIdsSelected = _useState4[1];
38
+ itemsIdsSelected = _useState4[0],
39
+ setItemsIdsSelected = _useState4[1];
53
40
 
54
- var onSelectFileId = function onSelectFileId(fileId) {
41
+ var onSelectItemId = function onSelectItemId(fileId) {
55
42
  if (!multiple) {
56
43
  handleConfirm(null, fileId);
57
44
  } else {
58
- setFilesIdsSelected(fileId);
45
+ setItemsIdsSelected(fileId);
59
46
  }
60
47
  };
61
48
 
@@ -64,11 +51,11 @@ var FilePicker = function FilePicker(_ref) {
64
51
  };
65
52
 
66
53
  var handleConfirm = function handleConfirm(_, fileId) {
67
- onChange(fileId ? fileId : filesIdsSelected);
54
+ onChange(fileId ? fileId : itemsIdsSelected);
68
55
  onClose();
69
56
  };
70
57
 
71
- var fileTypesAccepted = getFileTypesAccepted(accept);
58
+ var itemTypesAccepted = getCompliantTypes(accept);
72
59
  return /*#__PURE__*/React.createElement(FixedDialog, {
73
60
  open: true,
74
61
  disableGutters: true,
@@ -84,16 +71,16 @@ var FilePicker = function FilePicker(_ref) {
84
71
  }),
85
72
  content: /*#__PURE__*/React.createElement(FilePickerBody, {
86
73
  navigateTo: navigateTo,
87
- onSelectFileId: onSelectFileId,
88
- filesIdsSelected: filesIdsSelected,
74
+ onSelectItemId: onSelectItemId,
75
+ itemsIdsSelected: itemsIdsSelected,
89
76
  folderId: folderId,
90
- fileTypesAccepted: fileTypesAccepted,
77
+ itemTypesAccepted: itemTypesAccepted,
91
78
  multiple: multiple
92
79
  }),
93
80
  actions: multiple ? /*#__PURE__*/React.createElement(FilePickerFooter, {
94
81
  onClose: onClose,
95
82
  onConfirm: handleConfirm,
96
- disabledConfirm: filesIdsSelected.length === 0
83
+ disabledConfirm: itemsIdsSelected.length === 0
97
84
  }) : null
98
85
  });
99
86
  };
@@ -105,7 +92,7 @@ FilePicker.propTypes = {
105
92
  multiple: PropTypes.bool
106
93
  };
107
94
  FilePicker.defaultProps = {
108
- accept: 'file',
95
+ accept: '',
109
96
  multiple: false
110
97
  };
111
98
  export default /*#__PURE__*/memo(FilePicker);
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import Icon from "cozy-ui/transpiled/react/Icon";
3
+ import FileTypeAudioIcon from "cozy-ui/transpiled/react/Icons/FileTypeAudio";
3
4
  import withFileUrl from "cozy-ui/transpiled/react/Viewer/withFileUrl";
4
5
  var styles = {
5
6
  "CozyTheme--inverted": "styles__CozyTheme--inverted___1II8o",
@@ -31,7 +32,7 @@ var styles = {
31
32
  "viewer-pdfMobile": "styles__viewer-pdfMobile___2V75t",
32
33
  "viewer-pdfMobile--image": "styles__viewer-pdfMobile--image___2xo_a"
33
34
  };
34
- import FileTypeAudioIcon from 'cozy-ui/transpiled/react/Icons/FileTypeAudio';
35
+ import isTesting from "cozy-ui/transpiled/react/helpers/isTesting";
35
36
 
36
37
  var AudioViewer = function AudioViewer(_ref) {
37
38
  var file = _ref.file,
@@ -46,7 +47,8 @@ var AudioViewer = function AudioViewer(_ref) {
46
47
  className: styles['viewer-filename']
47
48
  }, file.name), /*#__PURE__*/React.createElement("audio", {
48
49
  src: url,
49
- controls: "controls"
50
+ controls: "controls",
51
+ preload: isTesting() ? 'none' : 'auto'
50
52
  }));
51
53
  };
52
54
 
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  import PropTypes from 'prop-types';
4
4
  import cx from 'classnames';
5
5
  import Icon from "cozy-ui/transpiled/react/Icon";
6
- import { default as ArrowIcon } from 'cozy-ui/transpiled/react/Icons/DropdownClose';
6
+ import { default as ArrowIcon } from "cozy-ui/transpiled/react/Icons/DropdownClose";
7
7
  var styles = {
8
8
  "CozyTheme--inverted": "styles__CozyTheme--inverted___1II8o",
9
9
  "CozyTheme--normal": "styles__CozyTheme--normal___382qj",
@@ -0,0 +1,42 @@
1
+ import mimeTypes from 'mime-types';
2
+ import { models } from 'cozy-client';
3
+ var _models$file = models.file,
4
+ isDirectory = _models$file.isDirectory,
5
+ isFile = _models$file.isFile;
6
+ /**
7
+ * @param {string} types - Types we wish to accept ("folder" and/or "extensions/mime" of file), separated by commas
8
+ * @returns {string[]} All the valid types, if the parameter is undefined or if no type is valid, return an empty array
9
+ */
10
+
11
+ export var getCompliantTypes = function getCompliantTypes(types) {
12
+ if (types) {
13
+ return types.replaceAll(' ', '').split(',').filter(function (type) {
14
+ return type !== 'folder' ? !!mimeTypes.contentType(type) : true;
15
+ });
16
+ }
17
+
18
+ return [];
19
+ };
20
+ /**
21
+ * Check if Item is a file with accepted extension/mime
22
+ *
23
+ * @param {object} item - file or folder
24
+ * @param {string[]} validTypes - List of accepted types
25
+ * @returns {boolean}
26
+ */
27
+
28
+ export var isValidFile = function isValidFile(item, validTypes) {
29
+ var fileTypesAccepted = validTypes.includes(".".concat(item.name.split('.').pop())) || validTypes.includes(item.mime);
30
+ return isFile(item) && (fileTypesAccepted || validTypes.length === 0);
31
+ };
32
+ /**
33
+ * Check if Item is a folder with accepted type
34
+ *
35
+ * @param {object} item - file or folder
36
+ * @param {string[]} validTypes - List of accepted types
37
+ * @returns {boolean}
38
+ */
39
+
40
+ export var isValidFolder = function isValidFolder(item, validTypes) {
41
+ return isDirectory(item) && validTypes.includes("folder");
42
+ };
@@ -0,0 +1,2 @@
1
+ import { makeStyles } from '@material-ui/core/styles';
2
+ export default makeStyles;
@@ -21,6 +21,7 @@ export { default as AccordionSummary } from './MuiCozyTheme/AccordionSummary';
21
21
  export { default as AccordionDetails } from './MuiCozyTheme/AccordionDetails';
22
22
  export { default as Toggle } from './Toggle';
23
23
  export { default as withBreakpoints } from './helpers/withBreakpoints';
24
+ export { default as makeStyles } from './helpers/makeStyles';
24
25
  export { default as useBreakpoints } from './hooks/useBreakpoints';
25
26
  export { default as useBrowserOffline } from './hooks/useBrowserOffline';
26
27
  export { Media, Img, Bd } from './Media';