@akemona-org/strapi-plugin-upload 3.7.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.
Files changed (246) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +19 -0
  3. package/admin/src/assets/images/logo.svg +1 -0
  4. package/admin/src/components/BrowseAssets/Wrapper.js +8 -0
  5. package/admin/src/components/BrowseAssets/index.js +182 -0
  6. package/admin/src/components/Card/index.js +146 -0
  7. package/admin/src/components/CardBorder/index.js +28 -0
  8. package/admin/src/components/CardControl/Wrapper.js +89 -0
  9. package/admin/src/components/CardControl/index.js +61 -0
  10. package/admin/src/components/CardControlsWrapper/index.js +22 -0
  11. package/admin/src/components/CardEmpty/Bar.js +19 -0
  12. package/admin/src/components/CardEmpty/Wrapper.js +7 -0
  13. package/admin/src/components/CardEmpty/index.js +16 -0
  14. package/admin/src/components/CardErrorMessage/index.js +9 -0
  15. package/admin/src/components/CardImgWrapper/index.js +52 -0
  16. package/admin/src/components/CardPreview/Image.js +12 -0
  17. package/admin/src/components/CardPreview/Wrapper.js +25 -0
  18. package/admin/src/components/CardPreview/index.js +66 -0
  19. package/admin/src/components/CardTitle/index.js +14 -0
  20. package/admin/src/components/CardWrapper/index.js +23 -0
  21. package/admin/src/components/CheckControl/Button.js +49 -0
  22. package/admin/src/components/CheckControl/CustomDropdownSection.js +9 -0
  23. package/admin/src/components/CheckControl/Spacer.js +7 -0
  24. package/admin/src/components/CheckControl/index.js +74 -0
  25. package/admin/src/components/Container/index.js +7 -0
  26. package/admin/src/components/ContainerFluid/index.js +12 -0
  27. package/admin/src/components/ControlsWrapper/index.js +9 -0
  28. package/admin/src/components/DragLayer/Wrapper.js +13 -0
  29. package/admin/src/components/DragLayer/index.js +68 -0
  30. package/admin/src/components/DropdownButton/index.js +63 -0
  31. package/admin/src/components/DropdownSection/index.js +27 -0
  32. package/admin/src/components/Duration/index.js +25 -0
  33. package/admin/src/components/Duration/utils/formatDuration.js +13 -0
  34. package/admin/src/components/EditForm/CropWrapper.js +21 -0
  35. package/admin/src/components/EditForm/ErrorMessage.js +10 -0
  36. package/admin/src/components/EditForm/FileDetailsBox.js +95 -0
  37. package/admin/src/components/EditForm/FileDetailsBoxWrapper.js +14 -0
  38. package/admin/src/components/EditForm/FileWrapper.js +41 -0
  39. package/admin/src/components/EditForm/FormWrapper.js +7 -0
  40. package/admin/src/components/EditForm/SizeBox.js +13 -0
  41. package/admin/src/components/EditForm/Wrapper.js +8 -0
  42. package/admin/src/components/EditForm/index.js +425 -0
  43. package/admin/src/components/EditForm/utils/form.js +34 -0
  44. package/admin/src/components/EditForm/utils/isImageType.js +3 -0
  45. package/admin/src/components/EditForm/utils/isVideoType.js +3 -0
  46. package/admin/src/components/FileIcon/Wrapper.js +20 -0
  47. package/admin/src/components/FileIcon/index.js +33 -0
  48. package/admin/src/components/FileIcon/utils/extensions.json +4 -0
  49. package/admin/src/components/FileInfos/index.js +32 -0
  50. package/admin/src/components/Filters/index.js +30 -0
  51. package/admin/src/components/FiltersList/index.js +34 -0
  52. package/admin/src/components/FiltersList/utils/formatFilter.js +36 -0
  53. package/admin/src/components/FiltersPicker/FiltersCard/FilterButton.js +8 -0
  54. package/admin/src/components/FiltersPicker/FiltersCard/FilterInput.js +35 -0
  55. package/admin/src/components/FiltersPicker/FiltersCard/InputWrapper.js +10 -0
  56. package/admin/src/components/FiltersPicker/FiltersCard/SizeInput.js +57 -0
  57. package/admin/src/components/FiltersPicker/FiltersCard/Wrapper.js +8 -0
  58. package/admin/src/components/FiltersPicker/FiltersCard/index.js +97 -0
  59. package/admin/src/components/FiltersPicker/FiltersCard/init.js +21 -0
  60. package/admin/src/components/FiltersPicker/FiltersCard/reducer.js +47 -0
  61. package/admin/src/components/FiltersPicker/FiltersCard/utils/filtersForm.js +27 -0
  62. package/admin/src/components/FiltersPicker/index.js +43 -0
  63. package/admin/src/components/FiltersPicker/utils/formatFilter.js +18 -0
  64. package/admin/src/components/InfiniteLoadingIndicator/Button.js +20 -0
  65. package/admin/src/components/InfiniteLoadingIndicator/Container.js +12 -0
  66. package/admin/src/components/InfiniteLoadingIndicator/Wrapper.js +18 -0
  67. package/admin/src/components/InfiniteLoadingIndicator/index.js +39 -0
  68. package/admin/src/components/Input/index.js +7 -0
  69. package/admin/src/components/InputFileModal/Label.js +47 -0
  70. package/admin/src/components/InputFileModal/P.js +15 -0
  71. package/admin/src/components/InputFileModal/index.js +73 -0
  72. package/admin/src/components/InputMedia/CardControlWrapper.js +12 -0
  73. package/admin/src/components/InputMedia/CardPreviewWrapper.js +13 -0
  74. package/admin/src/components/InputMedia/Chevron/Wrapper.js +10 -0
  75. package/admin/src/components/InputMedia/Chevron/index.js +21 -0
  76. package/admin/src/components/InputMedia/EmptyInputMedia.js +60 -0
  77. package/admin/src/components/InputMedia/EmptyText.js +13 -0
  78. package/admin/src/components/InputMedia/ErrorMessage.js +12 -0
  79. package/admin/src/components/InputMedia/IconUpload.js +48 -0
  80. package/admin/src/components/InputMedia/InputFilePreview.js +37 -0
  81. package/admin/src/components/InputMedia/Name.js +10 -0
  82. package/admin/src/components/InputMedia/Wrapper.js +11 -0
  83. package/admin/src/components/InputMedia/index.js +238 -0
  84. package/admin/src/components/InputUploadURL/Wrapper.js +13 -0
  85. package/admin/src/components/InputUploadURL/index.js +46 -0
  86. package/admin/src/components/IntlText/index.js +26 -0
  87. package/admin/src/components/List/ListCell.js +19 -0
  88. package/admin/src/components/List/ListRow.js +8 -0
  89. package/admin/src/components/List/index.js +114 -0
  90. package/admin/src/components/ListEmpty/Wrapper.js +15 -0
  91. package/admin/src/components/ListEmpty/index.js +70 -0
  92. package/admin/src/components/ListEmpty/utils/generateRows.js +12 -0
  93. package/admin/src/components/ListModal/BaselineAlignmentWrapper.js +12 -0
  94. package/admin/src/components/ListModal/index.js +66 -0
  95. package/admin/src/components/ListWrapper/index.js +16 -0
  96. package/admin/src/components/LoadingIndicator/index.js +44 -0
  97. package/admin/src/components/ModalHeader/BackButton.js +33 -0
  98. package/admin/src/components/ModalHeader/Wrapper.js +24 -0
  99. package/admin/src/components/ModalHeader/index.js +47 -0
  100. package/admin/src/components/ModalNavWrapper/BaselineAlignment.js +12 -0
  101. package/admin/src/components/ModalNavWrapper/Hr.js +14 -0
  102. package/admin/src/components/ModalNavWrapper/Wrapper.js +8 -0
  103. package/admin/src/components/ModalNavWrapper/index.js +70 -0
  104. package/admin/src/components/ModalSection/index.js +20 -0
  105. package/admin/src/components/ModalTab/Count/Wrapper.js +16 -0
  106. package/admin/src/components/ModalTab/Count/index.js +30 -0
  107. package/admin/src/components/ModalTab/Wrapper.js +37 -0
  108. package/admin/src/components/ModalTab/index.js +60 -0
  109. package/admin/src/components/PlayIcon/Play.js +65 -0
  110. package/admin/src/components/PlayIcon/Wrapper.js +24 -0
  111. package/admin/src/components/PlayIcon/index.js +23 -0
  112. package/admin/src/components/SelectAll/Wrapper.js +19 -0
  113. package/admin/src/components/SelectAll/index.js +26 -0
  114. package/admin/src/components/SelectedAssets/DraggableCard.js +149 -0
  115. package/admin/src/components/SelectedAssets/ListTitleWrapper.js +7 -0
  116. package/admin/src/components/SelectedAssets/ListWrapper.js +7 -0
  117. package/admin/src/components/SelectedAssets/SortableList.js +102 -0
  118. package/admin/src/components/SelectedAssets/Wrapper.js +7 -0
  119. package/admin/src/components/SelectedAssets/index.js +56 -0
  120. package/admin/src/components/SortList/Wrapper.js +19 -0
  121. package/admin/src/components/SortList/index.js +37 -0
  122. package/admin/src/components/SortListItem/Wrapper.js +28 -0
  123. package/admin/src/components/SortListItem/index.js +35 -0
  124. package/admin/src/components/SortPicker/index.js +54 -0
  125. package/admin/src/components/Tag/Wrapper.js +16 -0
  126. package/admin/src/components/Tag/index.js +25 -0
  127. package/admin/src/components/UploadForm/index.js +61 -0
  128. package/admin/src/components/UploadList/ButtonWrapper.js +7 -0
  129. package/admin/src/components/UploadList/Container.js +10 -0
  130. package/admin/src/components/UploadList/CustomModalSection.js +9 -0
  131. package/admin/src/components/UploadList/ListTitle.js +10 -0
  132. package/admin/src/components/UploadList/ListTitleWrapper.js +7 -0
  133. package/admin/src/components/UploadList/RowItem.js +98 -0
  134. package/admin/src/components/UploadList/index.js +90 -0
  135. package/admin/src/components/VideoPlayer/Wrapper.js +24 -0
  136. package/admin/src/components/VideoPlayer/index.js +57 -0
  137. package/admin/src/components/VideoPreview/CanvasWrapper.js +22 -0
  138. package/admin/src/components/VideoPreview/Thumbnail.js +12 -0
  139. package/admin/src/components/VideoPreview/Wrapper.js +15 -0
  140. package/admin/src/components/VideoPreview/index.js +165 -0
  141. package/admin/src/components/VideoPreview/reducer.js +33 -0
  142. package/admin/src/containers/App/index.js +31 -0
  143. package/admin/src/containers/HomePage/HomePageContent/HomePageList.js +98 -0
  144. package/admin/src/containers/HomePage/HomePageContent/HomePageSettings.js +103 -0
  145. package/admin/src/containers/HomePage/HomePageContent/index.js +90 -0
  146. package/admin/src/containers/HomePage/components.js +18 -0
  147. package/admin/src/containers/HomePage/index.js +373 -0
  148. package/admin/src/containers/HomePage/init.js +5 -0
  149. package/admin/src/containers/HomePage/reducer.js +88 -0
  150. package/admin/src/containers/HomePage/utils/generateParamsFromQuery.js +14 -0
  151. package/admin/src/containers/HomePage/utils/generateStringFromParams.js +27 -0
  152. package/admin/src/containers/HomePage/utils/getHeaderLabel.js +13 -0
  153. package/admin/src/containers/HomePage/utils/index.js +2 -0
  154. package/admin/src/containers/Initializer/index.js +44 -0
  155. package/admin/src/containers/InputModalStepper/HeaderSearch.js +12 -0
  156. package/admin/src/containers/InputModalStepper/InputModalStepper.js +480 -0
  157. package/admin/src/containers/InputModalStepper/Search.js +48 -0
  158. package/admin/src/containers/InputModalStepper/index.js +86 -0
  159. package/admin/src/containers/InputModalStepper/stepper.js +52 -0
  160. package/admin/src/containers/InputModalStepperProvider/index.js +564 -0
  161. package/admin/src/containers/InputModalStepperProvider/init.js +5 -0
  162. package/admin/src/containers/InputModalStepperProvider/reducer.js +301 -0
  163. package/admin/src/containers/ModalStepper/index.js +629 -0
  164. package/admin/src/containers/ModalStepper/init.js +5 -0
  165. package/admin/src/containers/ModalStepper/reducer.js +132 -0
  166. package/admin/src/containers/ModalStepper/stepper.js +46 -0
  167. package/admin/src/containers/SettingsPage/Divider.js +11 -0
  168. package/admin/src/containers/SettingsPage/SectionTitleWrapper.js +7 -0
  169. package/admin/src/containers/SettingsPage/Wrapper.js +17 -0
  170. package/admin/src/containers/SettingsPage/index.js +198 -0
  171. package/admin/src/containers/SettingsPage/init.js +5 -0
  172. package/admin/src/containers/SettingsPage/reducer.js +38 -0
  173. package/admin/src/contexts/AppContext/index.js +5 -0
  174. package/admin/src/contexts/InputModal/InputModalDataManager.js +5 -0
  175. package/admin/src/contexts/index.js +2 -0
  176. package/admin/src/hooks/index.js +2 -0
  177. package/admin/src/hooks/useAppContext/index.js +6 -0
  178. package/admin/src/hooks/useModalContext.js +6 -0
  179. package/admin/src/icons/BrokenFile/index.js +91 -0
  180. package/admin/src/icons/Cloud/index.js +35 -0
  181. package/admin/src/icons/DoubleFile/index.js +35 -0
  182. package/admin/src/icons/Download/index.js +36 -0
  183. package/admin/src/icons/File/index.js +35 -0
  184. package/admin/src/index.js +85 -0
  185. package/admin/src/lifecycles.js +13 -0
  186. package/admin/src/permissions.js +40 -0
  187. package/admin/src/pluginId.js +5 -0
  188. package/admin/src/translations/de.json +81 -0
  189. package/admin/src/translations/dk.json +81 -0
  190. package/admin/src/translations/en.json +86 -0
  191. package/admin/src/translations/es.json +81 -0
  192. package/admin/src/translations/fr.json +85 -0
  193. package/admin/src/translations/he.json +81 -0
  194. package/admin/src/translations/index.js +39 -0
  195. package/admin/src/translations/it.json +82 -0
  196. package/admin/src/translations/ja.json +81 -0
  197. package/admin/src/translations/ms.json +73 -0
  198. package/admin/src/translations/pl.json +81 -0
  199. package/admin/src/translations/pt-BR.json +81 -0
  200. package/admin/src/translations/ru.json +81 -0
  201. package/admin/src/translations/sk.json +81 -0
  202. package/admin/src/translations/th.json +81 -0
  203. package/admin/src/translations/uk.json +78 -0
  204. package/admin/src/translations/zh-Hans.json +86 -0
  205. package/admin/src/translations/zh.json +81 -0
  206. package/admin/src/utils/ItemTypes.js +3 -0
  207. package/admin/src/utils/canDownloadFile.js +3 -0
  208. package/admin/src/utils/compactParams.js +13 -0
  209. package/admin/src/utils/createFileToDownloadName.js +9 -0
  210. package/admin/src/utils/createMatrix.js +32 -0
  211. package/admin/src/utils/createNewFilesToDownloadArray.js +57 -0
  212. package/admin/src/utils/createNewFilesToUploadArray.js +25 -0
  213. package/admin/src/utils/formatBytes.js +13 -0
  214. package/admin/src/utils/formatFileForEditing.js +20 -0
  215. package/admin/src/utils/formatFilters.js +23 -0
  216. package/admin/src/utils/generatePageFromStart.js +5 -0
  217. package/admin/src/utils/generateStartFromPage.js +5 -0
  218. package/admin/src/utils/getFileModelTimestamps.js +15 -0
  219. package/admin/src/utils/getFilesToDownload.js +5 -0
  220. package/admin/src/utils/getRequestUrl.js +5 -0
  221. package/admin/src/utils/getTrad.js +5 -0
  222. package/admin/src/utils/getType.js +15 -0
  223. package/admin/src/utils/getYupError.js +17 -0
  224. package/admin/src/utils/index.js +20 -0
  225. package/admin/src/utils/unformatBytes.js +16 -0
  226. package/admin/src/utils/urlYupSchema.js +49 -0
  227. package/config/config.json +8 -0
  228. package/config/functions/bootstrap.js +143 -0
  229. package/config/routes.json +98 -0
  230. package/config/schema.graphql.js +96 -0
  231. package/controllers/Upload.js +103 -0
  232. package/controllers/upload/admin.js +213 -0
  233. package/controllers/upload/api.js +125 -0
  234. package/controllers/validation/settings.js +22 -0
  235. package/controllers/validation/upload.js +27 -0
  236. package/documentation/1.0.0/overrides/upload-File.json +263 -0
  237. package/errors.js +48 -0
  238. package/index.js +7 -0
  239. package/middlewares/upload/defaults.json +5 -0
  240. package/middlewares/upload/index.js +35 -0
  241. package/models/File.js +7 -0
  242. package/models/File.settings.json +86 -0
  243. package/package.json +71 -0
  244. package/services/Upload.js +397 -0
  245. package/services/image-manipulation.js +167 -0
  246. package/utils/file.js +23 -0
@@ -0,0 +1,54 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { FormattedMessage } from 'react-intl';
4
+ import { Carret, useGlobalContext } from 'strapi-helper-plugin';
5
+ import { Picker } from '@buffetjs/core';
6
+ import { getTrad, getFileModelTimestamps } from '../../utils';
7
+
8
+ import SortList from '../SortList';
9
+
10
+ const SortPicker = ({ onChange, value }) => {
11
+ const { plugins } = useGlobalContext();
12
+ const [created_at, updated_at] = getFileModelTimestamps(plugins);
13
+ const orders = {
14
+ created_at_desc: `${created_at}:DESC`,
15
+ created_at_asc: `${created_at}:ASC`,
16
+ name_asc: 'name:ASC',
17
+ name_desc: 'name:DESC',
18
+ updated_at_desc: `${updated_at}:DESC`,
19
+ updated_at_asc: `${updated_at}:ASC`,
20
+ };
21
+
22
+ return (
23
+ <Picker
24
+ renderButtonContent={isOpen => (
25
+ <>
26
+ <FormattedMessage id={getTrad('sort.label')} />
27
+ <Carret isUp={isOpen} fill={isOpen ? '#007EFF' : '#292b2c'} />
28
+ </>
29
+ )}
30
+ renderSectionContent={onToggle => (
31
+ <SortList
32
+ list={orders}
33
+ selectedItem={value}
34
+ onClick={e => {
35
+ onChange(e);
36
+ onToggle();
37
+ }}
38
+ />
39
+ )}
40
+ />
41
+ );
42
+ };
43
+
44
+ SortPicker.defaultProps = {
45
+ onChange: () => {},
46
+ value: null,
47
+ };
48
+
49
+ SortPicker.propTypes = {
50
+ onChange: PropTypes.func,
51
+ value: PropTypes.string,
52
+ };
53
+
54
+ export default SortPicker;
@@ -0,0 +1,16 @@
1
+ import styled from 'styled-components';
2
+ import { themePropTypes } from 'strapi-helper-plugin';
3
+
4
+ const Wrapper = styled.div`
5
+ padding: 0 5px;
6
+ margin-top: 6px;
7
+ height: 14px;
8
+ background-color: ${({ theme }) => theme.main.colors.mediumGrey};
9
+ border-radius: ${({ theme }) => theme.main.sizes.borderRadius};
10
+ `;
11
+
12
+ Wrapper.propTypes = {
13
+ ...themePropTypes,
14
+ };
15
+
16
+ export default Wrapper;
@@ -0,0 +1,25 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Text } from '@buffetjs/core';
4
+
5
+ import Wrapper from './Wrapper';
6
+
7
+ const Tag = ({ label }) => {
8
+ return (
9
+ <Wrapper>
10
+ <Text color="grey" fontWeight="bold" fontSize="xs" textTransform="uppercase">
11
+ {label}
12
+ </Text>
13
+ </Wrapper>
14
+ );
15
+ };
16
+
17
+ Tag.defaultProps = {
18
+ label: null,
19
+ };
20
+
21
+ Tag.propTypes = {
22
+ label: PropTypes.string,
23
+ };
24
+
25
+ export default Tag;
@@ -0,0 +1,61 @@
1
+ import React, { useEffect } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import InputFileModal from '../InputFileModal';
4
+ import InputUploadURL from '../InputUploadURL';
5
+ import ModalNavWrapper from '../ModalNavWrapper';
6
+ import ModalSection from '../ModalSection';
7
+
8
+ const UploadForm = ({
9
+ addFilesToUpload,
10
+ filesToDownload,
11
+ formErrors,
12
+ onChange,
13
+ setShouldDisplayNextButton,
14
+ }) => {
15
+ useEffect(() => {
16
+ return () => {
17
+ setShouldDisplayNextButton(false);
18
+ };
19
+ // eslint-disable-next-line react-hooks/exhaustive-deps
20
+ }, []);
21
+
22
+ const handleClick = to => {
23
+ setShouldDisplayNextButton(to === 'url');
24
+ };
25
+
26
+ const links = [
27
+ { to: 'computer', label: 'computer', isDisabled: false, onClick: handleClick },
28
+ { to: 'url', label: 'url', isDisabled: false, onClick: handleClick },
29
+ ];
30
+
31
+ return (
32
+ <ModalNavWrapper links={links}>
33
+ {to => (
34
+ <ModalSection>
35
+ {to === 'computer' && <InputFileModal onChange={addFilesToUpload} />}
36
+ {to === 'url' && (
37
+ <InputUploadURL errors={formErrors} onChange={onChange} value={filesToDownload} />
38
+ )}
39
+ </ModalSection>
40
+ )}
41
+ </ModalNavWrapper>
42
+ );
43
+ };
44
+
45
+ UploadForm.defaultProps = {
46
+ addFilesToUpload: () => {},
47
+ filesToDownload: [],
48
+ formErrors: null,
49
+ onChange: () => {},
50
+ setShouldDisplayNextButton: () => {},
51
+ };
52
+
53
+ UploadForm.propTypes = {
54
+ addFilesToUpload: PropTypes.func,
55
+ filesToDownload: PropTypes.arrayOf(PropTypes.string),
56
+ formErrors: PropTypes.object,
57
+ onChange: PropTypes.func,
58
+ setShouldDisplayNextButton: PropTypes.func,
59
+ };
60
+
61
+ export default UploadForm;
@@ -0,0 +1,7 @@
1
+ import styled from 'styled-components';
2
+
3
+ const ButtonWrapper = styled.div`
4
+ padding-top: 28px;
5
+ `;
6
+
7
+ export default ButtonWrapper;
@@ -0,0 +1,10 @@
1
+ import styled from 'styled-components';
2
+ import ContainerFluid from '../ContainerFluid';
3
+
4
+ const Container = styled(ContainerFluid)`
5
+ margin-bottom: 3px;
6
+ padding-top: 15px;
7
+ max-height: 357px;
8
+ `;
9
+
10
+ export default Container;
@@ -0,0 +1,9 @@
1
+ import styled from 'styled-components';
2
+
3
+ import ModalSection from '../ModalSection';
4
+
5
+ const CustomModalSection = styled(ModalSection)`
6
+ overflow: auto;
7
+ `;
8
+
9
+ export default CustomModalSection;
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import styled from 'styled-components';
3
+
4
+ import IntlText from '../IntlText';
5
+
6
+ const ListTitle = styled(props => <IntlText fontSize="md" fontWeight="bold" {...props} />)`
7
+ margin-bottom: 3px;
8
+ `;
9
+
10
+ export default ListTitle;
@@ -0,0 +1,7 @@
1
+ import styled from 'styled-components';
2
+
3
+ const ListTitle = styled.div`
4
+ margin-top: 34px;
5
+ `;
6
+
7
+ export default ListTitle;
@@ -0,0 +1,98 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { pick } from 'lodash';
4
+
5
+ import Card from '../Card';
6
+ import CardControl from '../CardControl';
7
+ import CardControlsWrapper from '../CardControlsWrapper';
8
+ import InfiniteLoadingIndicator from '../InfiniteLoadingIndicator';
9
+
10
+ const RowItem = ({
11
+ file,
12
+ fileInfo,
13
+ hasError,
14
+ errorMessage,
15
+ isDownloading,
16
+ isUploading,
17
+ onClick,
18
+ onClickDeleteFileToUpload,
19
+ onClickEdit,
20
+ originalIndex,
21
+ }) => {
22
+ const url = file ? URL.createObjectURL(file) : null;
23
+
24
+ const handleClick = () => {
25
+ onClick(originalIndex);
26
+ };
27
+
28
+ const handleClickDelete = () => {
29
+ onClickDeleteFileToUpload(originalIndex);
30
+ };
31
+
32
+ const handleClickEdit = () => {
33
+ onClickEdit(originalIndex);
34
+ };
35
+
36
+ let fileSize = null;
37
+
38
+ if (file) {
39
+ fileSize = file.mime ? file.type : file.size / 1000;
40
+ }
41
+
42
+ const shouldDisplayControls = !isUploading && !isDownloading && file !== null;
43
+ const shouldDisplayTrashIcon = file === null && hasError;
44
+
45
+ const cardOptions = {
46
+ ...pick(fileInfo, ['ext', 'name', 'mime', 'height', 'width', 'previewUrl', 'id']),
47
+ small: true,
48
+ errorMessage,
49
+ hasError,
50
+ type: file ? file.type : null,
51
+ size: fileSize,
52
+ url,
53
+ withFileCaching: false,
54
+ withoutFileInfo: isDownloading || (file === null && hasError),
55
+ };
56
+
57
+ return (
58
+ <div className="col-xs-12 col-md-6 col-xl-3" key={originalIndex}>
59
+ <Card options={cardOptions}>
60
+ {(isUploading || isDownloading) && <InfiniteLoadingIndicator onClick={handleClick} />}
61
+ {shouldDisplayTrashIcon && (
62
+ <CardControlsWrapper className="card-control-wrapper">
63
+ <CardControl title="delete" onClick={handleClickDelete} type="trash-alt" small />
64
+ </CardControlsWrapper>
65
+ )}
66
+ {shouldDisplayControls && (
67
+ <CardControlsWrapper className="card-control-wrapper">
68
+ <CardControl title="delete" onClick={handleClickDelete} type="trash-alt" small />
69
+ <CardControl title="edit" onClick={handleClickEdit} small />
70
+ </CardControlsWrapper>
71
+ )}
72
+ </Card>
73
+ </div>
74
+ );
75
+ };
76
+
77
+ RowItem.defaultProps = {
78
+ file: null,
79
+ errorMessage: null,
80
+ isDownloading: false,
81
+ };
82
+
83
+ RowItem.propTypes = {
84
+ file: PropTypes.object,
85
+ fileInfo: PropTypes.shape({
86
+ name: PropTypes.string.isRequired,
87
+ }).isRequired,
88
+ hasError: PropTypes.bool.isRequired,
89
+ errorMessage: PropTypes.string,
90
+ isDownloading: PropTypes.bool,
91
+ isUploading: PropTypes.bool.isRequired,
92
+ onClick: PropTypes.func.isRequired,
93
+ onClickDeleteFileToUpload: PropTypes.func.isRequired,
94
+ onClickEdit: PropTypes.func.isRequired,
95
+ originalIndex: PropTypes.number.isRequired,
96
+ };
97
+
98
+ export default RowItem;
@@ -0,0 +1,90 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Button } from '@buffetjs/core';
4
+ import { createMatrix, getTrad } from '../../utils';
5
+ import ModalSection from '../ModalSection';
6
+ import IntlText from '../IntlText';
7
+ import Container from './Container';
8
+ import ButtonWrapper from './ButtonWrapper';
9
+ import RowItem from './RowItem';
10
+ import ListTitle from './ListTitle';
11
+ import ListTitleWrapper from './ListTitleWrapper';
12
+ import CustomModalSection from './CustomModalSection';
13
+
14
+ const UploadList = ({
15
+ filesToUpload,
16
+ onClickCancelUpload,
17
+ onClickDeleteFileToUpload,
18
+ onClickEditNewFile,
19
+ onGoToAddBrowseFiles,
20
+ }) => {
21
+ const matrix = createMatrix(filesToUpload);
22
+ const filesToUploadLength = filesToUpload.length;
23
+ const titleId = `modal.upload-list.sub-header-title.${
24
+ filesToUploadLength > 1 ? 'plural' : 'singular'
25
+ }`;
26
+
27
+ return (
28
+ <>
29
+ <ModalSection justifyContent="space-between">
30
+ <ListTitleWrapper>
31
+ <ListTitle id={getTrad(titleId)} values={{ number: filesToUploadLength }} />
32
+ <IntlText
33
+ id={getTrad('modal.upload-list.sub-header-subtitle')}
34
+ values={{ number: filesToUploadLength }}
35
+ fontSize="sm"
36
+ color="grey"
37
+ />
38
+ </ListTitleWrapper>
39
+ <ButtonWrapper>
40
+ <Button type="button" color="primary" onClick={onGoToAddBrowseFiles}>
41
+ <IntlText
42
+ id={getTrad('modal.upload-list.sub-header.button')}
43
+ fontWeight="bold"
44
+ color="white"
45
+ />
46
+ </Button>
47
+ </ButtonWrapper>
48
+ </ModalSection>
49
+ <CustomModalSection>
50
+ <Container>
51
+ {matrix.map(({ key, rowContent }) => {
52
+ return (
53
+ <div className="row" key={key}>
54
+ {rowContent.map(data => {
55
+ return (
56
+ <RowItem
57
+ {...data}
58
+ onClick={onClickCancelUpload}
59
+ onClickDeleteFileToUpload={onClickDeleteFileToUpload}
60
+ onClickEdit={onClickEditNewFile}
61
+ key={data.originalIndex}
62
+ />
63
+ );
64
+ })}
65
+ </div>
66
+ );
67
+ })}
68
+ </Container>
69
+ </CustomModalSection>
70
+ </>
71
+ );
72
+ };
73
+
74
+ UploadList.defaultProps = {
75
+ filesToUpload: [],
76
+ onClickCancelUpload: () => {},
77
+ onClickDeleteFileToUpload: () => {},
78
+ onClickEditNewFile: () => {},
79
+ onGoToAddBrowseFiles: () => {},
80
+ };
81
+
82
+ UploadList.propTypes = {
83
+ filesToUpload: PropTypes.array,
84
+ onClickCancelUpload: PropTypes.func,
85
+ onClickDeleteFileToUpload: PropTypes.func,
86
+ onClickEditNewFile: PropTypes.func,
87
+ onGoToAddBrowseFiles: PropTypes.func,
88
+ };
89
+
90
+ export default UploadList;
@@ -0,0 +1,24 @@
1
+ import styled from 'styled-components';
2
+
3
+ const Wrapper = styled.div`
4
+ position: absolute;
5
+ top: 0;
6
+ left: 0;
7
+ display: flex;
8
+ align-items: center;
9
+ justify-content: center;
10
+ width: 100%;
11
+ height: 100%;
12
+ cursor: pointer;
13
+ video {
14
+ display: block;
15
+ max-width: 100%;
16
+ max-height: 100%;
17
+ width: auto;
18
+ height: auto;
19
+ margin: auto;
20
+ outline: 0;
21
+ }
22
+ `;
23
+
24
+ export default Wrapper;
@@ -0,0 +1,57 @@
1
+ import React, { useRef, useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+
4
+ import PlayIcon from '../PlayIcon';
5
+ import Duration from '../Duration';
6
+ import Wrapper from './Wrapper';
7
+
8
+ const VideoPlayer = ({ src }) => {
9
+ const [duration, setDuration] = useState(0);
10
+ const [isPlaying, setIsPlaying] = useState(false);
11
+
12
+ const videoRef = useRef();
13
+
14
+ const togglePlay = () => {
15
+ if (isPlaying) {
16
+ videoRef.current.pause();
17
+ // Change isPlaying here too because onPause handler is only called on controls click
18
+ setIsPlaying(false);
19
+ } else {
20
+ videoRef.current.play();
21
+ }
22
+ };
23
+
24
+ return (
25
+ <Wrapper onClick={togglePlay}>
26
+ <video
27
+ controls={isPlaying}
28
+ ref={videoRef}
29
+ src={src}
30
+ crossOrigin="anonymous"
31
+ onLoadedData={({ target: { duration } }) => {
32
+ setDuration(duration);
33
+ }}
34
+ onPlay={() => {
35
+ setIsPlaying(true);
36
+ }}
37
+ onPause={() => {
38
+ setIsPlaying(false);
39
+ }}
40
+ >
41
+ <track default kind="captions" srcLang="en" src="" />
42
+ </video>
43
+ {!isPlaying && <PlayIcon />}
44
+ <Duration duration={duration} />
45
+ </Wrapper>
46
+ );
47
+ };
48
+
49
+ VideoPlayer.defaultProps = {
50
+ src: null,
51
+ };
52
+
53
+ VideoPlayer.propTypes = {
54
+ src: PropTypes.string,
55
+ };
56
+
57
+ export default VideoPlayer;
@@ -0,0 +1,22 @@
1
+ import styled from 'styled-components';
2
+
3
+ const CanvasWrapper = styled.div`
4
+ display: flex;
5
+ justify-content: center;
6
+ align-items: center;
7
+ position: absolute;
8
+ top: 0;
9
+ left: 0;
10
+ width: 100%;
11
+ height: 100%;
12
+ canvas {
13
+ display: block;
14
+ max-width: 100%;
15
+ max-height: 100%;
16
+ width: auto;
17
+ height: auto;
18
+ margin: auto;
19
+ }
20
+ `;
21
+
22
+ export default CanvasWrapper;
@@ -0,0 +1,12 @@
1
+ import styled from 'styled-components';
2
+
3
+ const Thumbnail = styled.img`
4
+ display: block;
5
+ max-width: 100%;
6
+ max-height: 100%;
7
+ width: auto;
8
+ height: auto;
9
+ margin: auto;
10
+ `;
11
+
12
+ export default Thumbnail;
@@ -0,0 +1,15 @@
1
+ import styled from 'styled-components';
2
+
3
+ const Wrapper = styled.div`
4
+ position: relative;
5
+ width: 100%;
6
+ height: 100%;
7
+ display: flex;
8
+ align-items: center;
9
+ justify-content: center;
10
+ video {
11
+ display: none;
12
+ }
13
+ `;
14
+
15
+ export default Wrapper;
@@ -0,0 +1,165 @@
1
+ import React, { useEffect, useReducer, useRef } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import styled from 'styled-components';
4
+ import { FormattedMessage, useIntl } from 'react-intl';
5
+ import Duration from '../Duration';
6
+ import LoadingIndicator from '../LoadingIndicator';
7
+ import PlayIcon from '../PlayIcon';
8
+ import Wrapper from './Wrapper';
9
+ import CanvasWrapper from './CanvasWrapper';
10
+ import Thumbnail from './Thumbnail';
11
+ import reducer, { initialState } from './reducer';
12
+ import getTrad from '../../utils/getTrad';
13
+
14
+ const EmptyPreview = styled.div`
15
+ display: flex;
16
+ align-items: center;
17
+ justify-content: center;
18
+ font-size: ${({ theme }) => theme.main.sizes.fonts.xs};
19
+ color: ${({ theme }) => theme.main.colors.grey};
20
+ `;
21
+
22
+ const VideoPreview = ({ hasIcon, previewUrl, src }) => {
23
+ const { formatMessage } = useIntl();
24
+ const [reducerState, dispatch] = useReducer(reducer, initialState);
25
+ const {
26
+ duration,
27
+ dataLoaded,
28
+ isHover,
29
+ metadataLoaded,
30
+ snapshot,
31
+ seeked,
32
+ isError,
33
+ } = reducerState.toJS();
34
+
35
+ // Adapted from https://github.com/brothatru/react-video-thumbnail/blob/master/src/components/VideoThumbnail.js
36
+ // And from https://github.com/soupette/poc-video-preview
37
+ const canvasRef = useRef();
38
+ const videoRef = useRef();
39
+
40
+ useEffect(() => {
41
+ const getSnapshot = () => {
42
+ try {
43
+ const video = videoRef.current;
44
+ const canvas = canvasRef.current;
45
+
46
+ canvas.height = video.videoHeight;
47
+ canvas.width = video.videoWidth;
48
+ canvas.getContext('2d').drawImage(video, 0, 0);
49
+
50
+ const thumbnail = canvas.toDataURL('image/png');
51
+
52
+ video.src = ''; // setting to empty string stops video from loading
53
+
54
+ dispatch({
55
+ type: 'SET_SNAPSHOT',
56
+ snapshot: thumbnail,
57
+ });
58
+ } catch (e) {
59
+ console.error(e);
60
+ }
61
+ };
62
+
63
+ if (dataLoaded && metadataLoaded && videoRef.current) {
64
+ videoRef.current.currentTime = 0;
65
+
66
+ if (seeked && !snapshot) {
67
+ getSnapshot();
68
+ }
69
+ }
70
+ }, [dataLoaded, metadataLoaded, seeked, snapshot]);
71
+
72
+ if (isError) {
73
+ return (
74
+ <EmptyPreview>
75
+ <FormattedMessage id={getTrad('list.assets.not-supported-content')} />
76
+ </EmptyPreview>
77
+ );
78
+ }
79
+
80
+ return (
81
+ <Wrapper
82
+ // Specify isHover to prevent bad behavior when compo is under the cursor on modal open
83
+ onMouseEnter={() => {
84
+ dispatch({
85
+ type: 'SET_IS_HOVER',
86
+ isHover: true,
87
+ });
88
+ }}
89
+ onMouseLeave={() => {
90
+ dispatch({
91
+ type: 'SET_IS_HOVER',
92
+ isHover: false,
93
+ });
94
+ }}
95
+ >
96
+ {!snapshot && (
97
+ <LoadingIndicator
98
+ aria-label={formatMessage(
99
+ {
100
+ id: getTrad('list.assets.loading-asset'),
101
+ },
102
+ { path: src }
103
+ )}
104
+ />
105
+ )}
106
+
107
+ <CanvasWrapper>
108
+ {previewUrl ? (
109
+ <Thumbnail
110
+ src={previewUrl}
111
+ alt={formatMessage(
112
+ {
113
+ id: getTrad('list.assets.preview-asset'),
114
+ },
115
+ { path: src }
116
+ )}
117
+ />
118
+ ) : (
119
+ <>
120
+ <video
121
+ muted
122
+ ref={videoRef}
123
+ src={src}
124
+ onError={() => dispatch({ type: 'SET_ERROR', isError: true })}
125
+ onLoadedMetadata={() => {
126
+ dispatch({
127
+ type: 'METADATA_LOADED',
128
+ });
129
+ }}
130
+ onLoadedData={({ target: { duration } }) => {
131
+ dispatch({
132
+ type: 'DATA_LOADED',
133
+ duration,
134
+ });
135
+ }}
136
+ onSeeked={() => {
137
+ dispatch({
138
+ type: 'SEEKED',
139
+ });
140
+ }}
141
+ />
142
+ <canvas ref={canvasRef} />
143
+ </>
144
+ )}
145
+ <Duration duration={duration} />
146
+
147
+ {(hasIcon || isHover) && <PlayIcon small />}
148
+ </CanvasWrapper>
149
+ </Wrapper>
150
+ );
151
+ };
152
+
153
+ VideoPreview.defaultProps = {
154
+ hasIcon: false,
155
+ previewUrl: null,
156
+ src: null,
157
+ };
158
+
159
+ VideoPreview.propTypes = {
160
+ hasIcon: PropTypes.bool,
161
+ previewUrl: PropTypes.string,
162
+ src: PropTypes.string,
163
+ };
164
+
165
+ export default VideoPreview;