cozy-viewer 1.1.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 (250) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/LICENSE +21 -0
  3. package/Readme.md +44 -0
  4. package/babel.config.js +23 -0
  5. package/dist/Footer/BottomSheetContent.d.ts +12 -0
  6. package/dist/Footer/BottomSheetContent.js +45 -0
  7. package/dist/Footer/DownloadButton.d.ts +16 -0
  8. package/dist/Footer/DownloadButton.js +113 -0
  9. package/dist/Footer/FooterActionButtons.d.ts +13 -0
  10. package/dist/Footer/FooterActionButtons.js +33 -0
  11. package/dist/Footer/FooterActionButtons.spec.d.ts +1 -0
  12. package/dist/Footer/FooterContent.d.ts +16 -0
  13. package/dist/Footer/FooterContent.js +120 -0
  14. package/dist/Footer/ForwardButton.d.ts +20 -0
  15. package/dist/Footer/ForwardButton.js +177 -0
  16. package/dist/Footer/ForwardButton.spec.d.ts +1 -0
  17. package/dist/Footer/ForwardOrDownloadButton.d.ts +11 -0
  18. package/dist/Footer/ForwardOrDownloadButton.js +42 -0
  19. package/dist/Footer/Sharing.d.ts +16 -0
  20. package/dist/Footer/Sharing.js +79 -0
  21. package/dist/Footer/helpers.d.ts +8 -0
  22. package/dist/Footer/helpers.js +179 -0
  23. package/dist/Footer/helpers.spec.d.ts +1 -0
  24. package/dist/NoViewer/DownloadButton.d.ts +2 -0
  25. package/dist/NoViewer/DownloadButton.js +52 -0
  26. package/dist/NoViewer/FileIcon.d.ts +4 -0
  27. package/dist/NoViewer/FileIcon.js +76 -0
  28. package/dist/NoViewer/NoViewer.d.ts +18 -0
  29. package/dist/NoViewer/NoViewer.js +64 -0
  30. package/dist/NoViewer/NoViewer.spec.d.ts +1 -0
  31. package/dist/NoViewer/index.d.ts +1 -0
  32. package/dist/NoViewer/index.js +15 -0
  33. package/dist/Panel/ActionMenuDesktop.d.ts +3 -0
  34. package/dist/Panel/ActionMenuDesktop.js +91 -0
  35. package/dist/Panel/ActionMenuMobile.d.ts +20 -0
  36. package/dist/Panel/ActionMenuMobile.js +95 -0
  37. package/dist/Panel/ActionMenuWrapper.d.ts +3 -0
  38. package/dist/Panel/ActionMenuWrapper.js +155 -0
  39. package/dist/Panel/Certifications.d.ts +2 -0
  40. package/dist/Panel/Certifications.js +80 -0
  41. package/dist/Panel/PanelContent.d.ts +2 -0
  42. package/dist/Panel/PanelContent.js +71 -0
  43. package/dist/Panel/Qualification.d.ts +2 -0
  44. package/dist/Panel/Qualification.js +148 -0
  45. package/dist/Panel/QualificationListItemContact.d.ts +10 -0
  46. package/dist/Panel/QualificationListItemContact.js +123 -0
  47. package/dist/Panel/QualificationListItemDate.d.ts +3 -0
  48. package/dist/Panel/QualificationListItemDate.js +90 -0
  49. package/dist/Panel/QualificationListItemInformation.d.ts +3 -0
  50. package/dist/Panel/QualificationListItemInformation.js +84 -0
  51. package/dist/Panel/QualificationListItemInformation.spec.d.ts +1 -0
  52. package/dist/Panel/QualificationListItemOther.d.ts +3 -0
  53. package/dist/Panel/QualificationListItemOther.js +78 -0
  54. package/dist/Panel/QualificationListItemText.d.ts +13 -0
  55. package/dist/Panel/QualificationListItemText.js +42 -0
  56. package/dist/Panel/getPanelBlocks.d.ts +26 -0
  57. package/dist/Panel/getPanelBlocks.js +79 -0
  58. package/dist/Panel/getPanelBlocks.spec.d.ts +1 -0
  59. package/dist/Viewer.d.ts +39 -0
  60. package/dist/Viewer.js +191 -0
  61. package/dist/ViewerContainer.d.ts +22 -0
  62. package/dist/ViewerContainer.js +221 -0
  63. package/dist/ViewerExposer.d.ts +2 -0
  64. package/dist/ViewerExposer.js +13 -0
  65. package/dist/ViewerInformationsWrapper.d.ts +20 -0
  66. package/dist/ViewerInformationsWrapper.js +68 -0
  67. package/dist/ViewerInformationsWrapper.spec.d.ts +1 -0
  68. package/dist/ViewerWithCustomPanelAndFooter.d.ts +2 -0
  69. package/dist/ViewerWithCustomPanelAndFooter.js +78 -0
  70. package/dist/ViewersByFile/AudioViewer.d.ts +74 -0
  71. package/dist/ViewersByFile/AudioViewer.js +57 -0
  72. package/dist/ViewersByFile/AudioViewer.spec.d.ts +1 -0
  73. package/dist/ViewersByFile/BlankPaperViewer.d.ts +2 -0
  74. package/dist/ViewersByFile/BlankPaperViewer.js +97 -0
  75. package/dist/ViewersByFile/ImageViewer.d.ts +31 -0
  76. package/dist/ViewersByFile/ImageViewer.js +385 -0
  77. package/dist/ViewersByFile/ImageViewer.spec.d.ts +1 -0
  78. package/dist/ViewersByFile/NoNetworkViewer.d.ts +2 -0
  79. package/dist/ViewersByFile/NoNetworkViewer.js +54 -0
  80. package/dist/ViewersByFile/OnlyOfficeViewer.d.ts +2 -0
  81. package/dist/ViewersByFile/OnlyOfficeViewer.js +46 -0
  82. package/dist/ViewersByFile/PdfJsViewer.d.ts +31 -0
  83. package/dist/ViewersByFile/PdfJsViewer.js +283 -0
  84. package/dist/ViewersByFile/PdfJsViewer.spec.d.ts +1 -0
  85. package/dist/ViewersByFile/PdfMobileViewer.d.ts +4 -0
  86. package/dist/ViewersByFile/PdfMobileViewer.js +185 -0
  87. package/dist/ViewersByFile/PdfMobileViewer.spec.d.ts +1 -0
  88. package/dist/ViewersByFile/ShortcutViewer.d.ts +2 -0
  89. package/dist/ViewersByFile/ShortcutViewer.js +61 -0
  90. package/dist/ViewersByFile/ShortcutViewer.spec.d.ts +4 -0
  91. package/dist/ViewersByFile/TextViewer.d.ts +90 -0
  92. package/dist/ViewersByFile/TextViewer.js +250 -0
  93. package/dist/ViewersByFile/TextViewer.spec.d.ts +1 -0
  94. package/dist/ViewersByFile/VideoViewer.d.ts +74 -0
  95. package/dist/ViewersByFile/VideoViewer.js +46 -0
  96. package/dist/ViewersByFile/VideoViewer.spec.d.ts +1 -0
  97. package/dist/assets/IlluGenericNewPage.svg +10 -0
  98. package/dist/components/ExpirationAlert.d.ts +2 -0
  99. package/dist/components/ExpirationAlert.js +129 -0
  100. package/dist/components/ExpirationAnnotation.d.ts +10 -0
  101. package/dist/components/ExpirationAnnotation.js +56 -0
  102. package/dist/components/Footer.d.ts +4 -0
  103. package/dist/components/Footer.js +41 -0
  104. package/dist/components/InformationPanel.d.ts +12 -0
  105. package/dist/components/InformationPanel.js +36 -0
  106. package/dist/components/Navigation.d.ts +18 -0
  107. package/dist/components/Navigation.js +63 -0
  108. package/dist/components/PdfToolbarButton.d.ts +16 -0
  109. package/dist/components/PdfToolbarButton.js +40 -0
  110. package/dist/components/PrintButton.d.ts +16 -0
  111. package/dist/components/PrintButton.js +163 -0
  112. package/dist/components/Toolbar.d.ts +2 -0
  113. package/dist/components/Toolbar.js +146 -0
  114. package/dist/components/ToolbarButtons.d.ts +5 -0
  115. package/dist/components/ToolbarButtons.js +20 -0
  116. package/dist/components/ToolbarFilePath.d.ts +3 -0
  117. package/dist/components/ToolbarFilePath.js +92 -0
  118. package/dist/components/ViewerByFile.d.ts +7 -0
  119. package/dist/components/ViewerByFile.js +137 -0
  120. package/dist/components/ViewerByFile.spec.d.ts +1 -0
  121. package/dist/components/ViewerControls.d.ts +9 -0
  122. package/dist/components/ViewerControls.js +251 -0
  123. package/dist/components/ViewerControls.spec.d.ts +1 -0
  124. package/dist/components/ViewerSpinner.d.ts +2 -0
  125. package/dist/components/ViewerSpinner.js +31 -0
  126. package/dist/docs/DemoProvider.d.ts +6 -0
  127. package/dist/docs/DemoProvider.js +159 -0
  128. package/dist/helpers.d.ts +37 -0
  129. package/dist/helpers.js +190 -0
  130. package/dist/helpers.spec.d.ts +1 -0
  131. package/dist/hoc/withFileUrl.d.ts +75 -0
  132. package/dist/hoc/withFileUrl.js +231 -0
  133. package/dist/hoc/withViewerLocales.d.ts +1 -0
  134. package/dist/hoc/withViewerLocales.js +15 -0
  135. package/dist/hooks/useReferencedContactName.d.ts +5 -0
  136. package/dist/hooks/useReferencedContactName.js +45 -0
  137. package/dist/index.d.ts +10 -0
  138. package/dist/index.js +75 -0
  139. package/dist/locales/index.d.ts +6 -0
  140. package/dist/locales/index.js +18 -0
  141. package/dist/proptypes.d.ts +7 -0
  142. package/dist/proptypes.js +25 -0
  143. package/dist/providers/ActionMenuProvider.d.ts +13 -0
  144. package/dist/providers/ActionMenuProvider.js +47 -0
  145. package/dist/providers/EncryptedProvider.d.ts +8 -0
  146. package/dist/providers/EncryptedProvider.js +43 -0
  147. package/dist/queries.d.ts +15 -0
  148. package/dist/queries.js +40 -0
  149. package/dist/stylesheet.css +218 -0
  150. package/jest.config.js +23 -0
  151. package/package.json +62 -0
  152. package/preprocess.js +16 -0
  153. package/src/Footer/BottomSheetContent.jsx +30 -0
  154. package/src/Footer/DownloadButton.jsx +66 -0
  155. package/src/Footer/FooterActionButtons.jsx +22 -0
  156. package/src/Footer/FooterActionButtons.spec.jsx +30 -0
  157. package/src/Footer/FooterContent.jsx +102 -0
  158. package/src/Footer/ForwardButton.jsx +95 -0
  159. package/src/Footer/ForwardButton.spec.jsx +87 -0
  160. package/src/Footer/ForwardOrDownloadButton.jsx +24 -0
  161. package/src/Footer/Sharing.jsx +59 -0
  162. package/src/Footer/helpers.js +106 -0
  163. package/src/Footer/helpers.spec.js +77 -0
  164. package/src/NoViewer/DownloadButton.jsx +28 -0
  165. package/src/NoViewer/FileIcon.jsx +46 -0
  166. package/src/NoViewer/NoViewer.jsx +30 -0
  167. package/src/NoViewer/NoViewer.spec.jsx +44 -0
  168. package/src/NoViewer/__snapshots__/NoViewer.spec.jsx.snap +82 -0
  169. package/src/NoViewer/index.jsx +1 -0
  170. package/src/Panel/ActionMenuDesktop.jsx +69 -0
  171. package/src/Panel/ActionMenuMobile.jsx +76 -0
  172. package/src/Panel/ActionMenuWrapper.jsx +104 -0
  173. package/src/Panel/Certifications.jsx +63 -0
  174. package/src/Panel/PanelContent.jsx +50 -0
  175. package/src/Panel/Qualification.jsx +114 -0
  176. package/src/Panel/QualificationListItemContact.jsx +85 -0
  177. package/src/Panel/QualificationListItemDate.jsx +78 -0
  178. package/src/Panel/QualificationListItemInformation.jsx +68 -0
  179. package/src/Panel/QualificationListItemInformation.spec.jsx +73 -0
  180. package/src/Panel/QualificationListItemOther.jsx +61 -0
  181. package/src/Panel/QualificationListItemText.jsx +30 -0
  182. package/src/Panel/getPanelBlocks.jsx +56 -0
  183. package/src/Panel/getPanelBlocks.spec.jsx +79 -0
  184. package/src/Panel/styles.styl +13 -0
  185. package/src/Readme.md +352 -0
  186. package/src/Viewer.jsx +135 -0
  187. package/src/ViewerContainer.jsx +170 -0
  188. package/src/ViewerExposer.js +3 -0
  189. package/src/ViewerInformationsWrapper.jsx +70 -0
  190. package/src/ViewerInformationsWrapper.spec.jsx +63 -0
  191. package/src/ViewerWithCustomPanelAndFooter.jsx +57 -0
  192. package/src/ViewersByFile/AudioViewer.jsx +22 -0
  193. package/src/ViewersByFile/AudioViewer.spec.jsx +40 -0
  194. package/src/ViewersByFile/BlankPaperViewer.jsx +47 -0
  195. package/src/ViewersByFile/ImageViewer.jsx +331 -0
  196. package/src/ViewersByFile/ImageViewer.spec.jsx +73 -0
  197. package/src/ViewersByFile/NoNetworkViewer.jsx +18 -0
  198. package/src/ViewersByFile/OnlyOfficeViewer.jsx +29 -0
  199. package/src/ViewersByFile/PdfJsViewer.jsx +210 -0
  200. package/src/ViewersByFile/PdfJsViewer.spec.jsx +161 -0
  201. package/src/ViewersByFile/PdfMobileViewer.jsx +106 -0
  202. package/src/ViewersByFile/PdfMobileViewer.spec.jsx +76 -0
  203. package/src/ViewersByFile/ShortcutViewer.jsx +38 -0
  204. package/src/ViewersByFile/ShortcutViewer.spec.jsx +32 -0
  205. package/src/ViewersByFile/TextViewer.jsx +126 -0
  206. package/src/ViewersByFile/TextViewer.spec.jsx +118 -0
  207. package/src/ViewersByFile/VideoViewer.jsx +13 -0
  208. package/src/ViewersByFile/VideoViewer.spec.jsx +40 -0
  209. package/src/ViewersByFile/__snapshots__/AudioViewer.spec.jsx.snap +43 -0
  210. package/src/ViewersByFile/__snapshots__/ShortcutViewer.spec.jsx.snap +57 -0
  211. package/src/ViewersByFile/__snapshots__/TextViewer.spec.jsx.snap +100 -0
  212. package/src/ViewersByFile/__snapshots__/VideoViewer.spec.jsx.snap +19 -0
  213. package/src/ViewersByFile/styles.styl +87 -0
  214. package/src/assets/IlluGenericNewPage.svg +10 -0
  215. package/src/components/ExpirationAlert.jsx +86 -0
  216. package/src/components/ExpirationAnnotation.jsx +39 -0
  217. package/src/components/Footer.jsx +14 -0
  218. package/src/components/InformationPanel.jsx +26 -0
  219. package/src/components/Navigation.jsx +40 -0
  220. package/src/components/PdfToolbarButton.jsx +26 -0
  221. package/src/components/PrintButton.jsx +89 -0
  222. package/src/components/Toolbar.jsx +111 -0
  223. package/src/components/ToolbarButtons.jsx +11 -0
  224. package/src/components/ToolbarFilePath.jsx +61 -0
  225. package/src/components/ViewerByFile.jsx +112 -0
  226. package/src/components/ViewerByFile.spec.jsx +100 -0
  227. package/src/components/ViewerControls.jsx +191 -0
  228. package/src/components/ViewerControls.spec.jsx +54 -0
  229. package/src/components/ViewerSpinner.jsx +17 -0
  230. package/src/components/styles.styl +93 -0
  231. package/src/docs/DemoProvider.jsx +90 -0
  232. package/src/helpers.js +131 -0
  233. package/src/helpers.spec.js +136 -0
  234. package/src/hoc/withFileUrl.jsx +93 -0
  235. package/src/hoc/withViewerLocales.jsx +5 -0
  236. package/src/hooks/useReferencedContactName.jsx +26 -0
  237. package/src/index.jsx +12 -0
  238. package/src/locales/en.json +66 -0
  239. package/src/locales/fr.json +66 -0
  240. package/src/locales/index.js +4 -0
  241. package/src/proptypes.js +12 -0
  242. package/src/providers/ActionMenuProvider.jsx +35 -0
  243. package/src/providers/EncryptedProvider.jsx +25 -0
  244. package/src/queries.js +20 -0
  245. package/src/styles.styl +22 -0
  246. package/src/vars.styl +6 -0
  247. package/test/__mocks__/fileMock.js +3 -0
  248. package/test/jestLib/setup.js +5 -0
  249. package/tsconfig-build.json +13 -0
  250. package/tsconfig.json +34 -0
@@ -0,0 +1,44 @@
1
+ import { render } from '@testing-library/react'
2
+ import React from 'react'
3
+
4
+ import NoViewer from './NoViewer'
5
+ import DemoProvider from '../docs/DemoProvider'
6
+
7
+ const file = {
8
+ _id: 'notSupported',
9
+ class: 'notSupported',
10
+ mime: 'notSupported',
11
+ name: 'notSupported.xyz'
12
+ }
13
+
14
+ const setup = ({ renderFallbackExtraContent } = {}) => {
15
+ const root = render(
16
+ <DemoProvider>
17
+ <NoViewer
18
+ file={file}
19
+ renderFallbackExtraContent={renderFallbackExtraContent}
20
+ />
21
+ </DemoProvider>
22
+ )
23
+
24
+ return { root }
25
+ }
26
+
27
+ describe('NoViewer', () => {
28
+ it('should render the viewer', () => {
29
+ const { root } = setup()
30
+ const { container } = root
31
+
32
+ expect(container).toMatchSnapshot()
33
+ })
34
+
35
+ it('should render the viewer with specific extra content', () => {
36
+ const renderFallbackExtraContent = () => (
37
+ <div>with specific extra content</div>
38
+ )
39
+ const { root } = setup({ renderFallbackExtraContent })
40
+ const { container } = root
41
+
42
+ expect(container).toMatchSnapshot()
43
+ })
44
+ })
@@ -0,0 +1,82 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`NoViewer should render the viewer 1`] = `
4
+ <div>
5
+ <div
6
+ class="viewer-noviewer"
7
+ >
8
+ <svg
9
+ class="styles__icon___23x3R"
10
+ height="140"
11
+ viewBox="0 0 32 32"
12
+ width="160"
13
+ >
14
+ <g
15
+ fill="none"
16
+ fill-rule="evenodd"
17
+ >
18
+ <path
19
+ d="M3 2.002C3 .896 3.89 0 4.997 0H22l7 7v22.996A2 2 0 0127.003 32H4.997A1.995 1.995 0 013 29.998V2.002z"
20
+ fill="#D1D5DB"
21
+ />
22
+ <path
23
+ d="M21.5 0c-.276 0-.5.23-.5.5V8h7.5c.276 0 .5-.232.5-.5V7l-7-7h-.5z"
24
+ fill="#A3ACB8"
25
+ />
26
+ </g>
27
+ </svg>
28
+ <p
29
+ class="viewer-filename"
30
+ >
31
+ notSupported.xyz
32
+ </p>
33
+ <button
34
+ class="styles__c-btn___3kXsk styles__c-btn--center___Nny0n"
35
+ type="submit"
36
+ >
37
+ <span>
38
+ <span>
39
+ Download
40
+ </span>
41
+ </span>
42
+ </button>
43
+ </div>
44
+ </div>
45
+ `;
46
+
47
+ exports[`NoViewer should render the viewer with specific extra content 1`] = `
48
+ <div>
49
+ <div
50
+ class="viewer-noviewer"
51
+ >
52
+ <svg
53
+ class="styles__icon___23x3R"
54
+ height="140"
55
+ viewBox="0 0 32 32"
56
+ width="160"
57
+ >
58
+ <g
59
+ fill="none"
60
+ fill-rule="evenodd"
61
+ >
62
+ <path
63
+ d="M3 2.002C3 .896 3.89 0 4.997 0H22l7 7v22.996A2 2 0 0127.003 32H4.997A1.995 1.995 0 013 29.998V2.002z"
64
+ fill="#D1D5DB"
65
+ />
66
+ <path
67
+ d="M21.5 0c-.276 0-.5.23-.5.5V8h7.5c.276 0 .5-.232.5-.5V7l-7-7h-.5z"
68
+ fill="#A3ACB8"
69
+ />
70
+ </g>
71
+ </svg>
72
+ <p
73
+ class="viewer-filename"
74
+ >
75
+ notSupported.xyz
76
+ </p>
77
+ <div>
78
+ with specific extra content
79
+ </div>
80
+ </div>
81
+ </div>
82
+ `;
@@ -0,0 +1 @@
1
+ export { default } from './NoViewer'
@@ -0,0 +1,69 @@
1
+ import PropTypes from 'prop-types'
2
+ import React, { forwardRef } from 'react'
3
+
4
+ import AppLinker from 'cozy-ui/transpiled/react/AppLinker'
5
+ import Icon from 'cozy-ui/transpiled/react/Icon'
6
+ import Copy from 'cozy-ui/transpiled/react/Icons/Copy'
7
+ import Edit from 'cozy-ui/transpiled/react/Icons/Rename'
8
+ import Typography from 'cozy-ui/transpiled/react/Typography'
9
+ import ActionMenu, {
10
+ ActionMenuItem
11
+ } from 'cozy-ui/transpiled/react/deprecated/ActionMenu'
12
+ import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
13
+
14
+ import styles from './styles.styl'
15
+
16
+ const ActionMenuDesktop = forwardRef(
17
+ ({ onClose, isEditable, actions, appLink, appSlug }, ref) => {
18
+ const { handleCopy, handleEdit } = actions
19
+ const { t } = useI18n()
20
+
21
+ return (
22
+ <ActionMenu
23
+ className={styles['ActionMenuDesktop-ActionMenu']}
24
+ onClose={onClose}
25
+ anchorElRef={ref}
26
+ >
27
+ {isEditable && (
28
+ <AppLinker app={{ slug: appSlug }} href={appLink}>
29
+ {({ onClick, href }) => {
30
+ return (
31
+ <a href={href} onClick={() => handleEdit(onClick)}>
32
+ <ActionMenuItem
33
+ left={<Icon icon={Edit} color="var(--iconTextColor)" />}
34
+ >
35
+ <Typography>
36
+ {t(`Viewer.panel.qualification.actions.edit`)}
37
+ </Typography>
38
+ </ActionMenuItem>
39
+ </a>
40
+ )
41
+ }}
42
+ </AppLinker>
43
+ )}
44
+ <ActionMenuItem
45
+ onClick={handleCopy}
46
+ left={<Icon icon={Copy} color="var(--iconTextColor)" />}
47
+ >
48
+ <Typography>
49
+ {t(`Viewer.panel.qualification.actions.copy`)}
50
+ </Typography>
51
+ </ActionMenuItem>
52
+ </ActionMenu>
53
+ )
54
+ }
55
+ )
56
+ ActionMenuDesktop.displayName = 'ActionMenuDesktop'
57
+
58
+ ActionMenuDesktop.propTypes = {
59
+ onClose: PropTypes.func,
60
+ isEditable: PropTypes.bool,
61
+ actions: PropTypes.shape({
62
+ handleCopy: PropTypes.func,
63
+ handleEdit: PropTypes.func
64
+ }),
65
+ appLink: PropTypes.string,
66
+ appSlug: PropTypes.string
67
+ }
68
+
69
+ export default ActionMenuDesktop
@@ -0,0 +1,76 @@
1
+ import PropTypes from 'prop-types'
2
+ import React from 'react'
3
+
4
+ import AppLinker from 'cozy-ui/transpiled/react/AppLinker'
5
+ import BottomSheet, {
6
+ BottomSheetItem
7
+ } from 'cozy-ui/transpiled/react/BottomSheet'
8
+ import Icon from 'cozy-ui/transpiled/react/Icon'
9
+ import Copy from 'cozy-ui/transpiled/react/Icons/Copy'
10
+ import Edit from 'cozy-ui/transpiled/react/Icons/Rename'
11
+ import List from 'cozy-ui/transpiled/react/List'
12
+ import ListItem from 'cozy-ui/transpiled/react/ListItem'
13
+ import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
14
+ import ListItemText from 'cozy-ui/transpiled/react/ListItemText'
15
+ import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
16
+
17
+ const ActionMenuMobile = ({
18
+ onClose,
19
+ isEditable,
20
+ actions,
21
+ appLink,
22
+ appSlug
23
+ }) => {
24
+ const { t } = useI18n()
25
+ const { handleCopy, handleEdit } = actions
26
+
27
+ return (
28
+ <BottomSheet backdrop onClose={onClose}>
29
+ <BottomSheetItem disableGutters>
30
+ <List>
31
+ {isEditable && (
32
+ <AppLinker app={{ slug: appSlug }} href={appLink}>
33
+ {({ onClick, href }) => {
34
+ return (
35
+ <ListItem
36
+ button
37
+ component="a"
38
+ href={href}
39
+ onClick={() => handleEdit(onClick)}
40
+ >
41
+ <ListItemIcon>
42
+ <Icon icon={Edit} />
43
+ </ListItemIcon>
44
+ <ListItemText
45
+ primary={t(`Viewer.panel.qualification.actions.edit`)}
46
+ />
47
+ </ListItem>
48
+ )
49
+ }}
50
+ </AppLinker>
51
+ )}
52
+ <ListItem button onClick={handleCopy}>
53
+ <ListItemIcon>
54
+ <Icon icon={Copy} />
55
+ </ListItemIcon>
56
+ <ListItemText
57
+ primary={t(`Viewer.panel.qualification.actions.copyClipboard`)}
58
+ />
59
+ </ListItem>
60
+ </List>
61
+ </BottomSheetItem>
62
+ </BottomSheet>
63
+ )
64
+ }
65
+
66
+ ActionMenuMobile.propTypes = {
67
+ onClose: PropTypes.func,
68
+ isEditable: PropTypes.bool,
69
+ actions: PropTypes.shape({
70
+ handleCopy: PropTypes.func,
71
+ handleEdit: PropTypes.func
72
+ }),
73
+ appLink: PropTypes.string
74
+ }
75
+
76
+ export default ActionMenuMobile
@@ -0,0 +1,104 @@
1
+ import PropTypes from 'prop-types'
2
+ import React, { forwardRef } from 'react'
3
+
4
+ import { useAppLinkWithStoreFallback, useClient } from 'cozy-client'
5
+ import { useAlert } from 'cozy-ui/transpiled/react/providers/Alert'
6
+ import useBreakpoints from 'cozy-ui/transpiled/react/providers/Breakpoints'
7
+ import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
8
+
9
+ import ActionMenuDesktop from './ActionMenuDesktop'
10
+ import ActionMenuMobile from './ActionMenuMobile'
11
+ import {
12
+ buildEditAttributePath,
13
+ isEditableAttribute,
14
+ getCurrentModel
15
+ } from '../helpers'
16
+ import useActionMenuContext from '../providers/ActionMenuProvider'
17
+
18
+ const mespapiersAppSlug = 'mespapiers'
19
+
20
+ const ActionMenuWrapper = forwardRef(({ onClose, file, optionFile }, ref) => {
21
+ const { name, value } = optionFile
22
+ const editPathByModelProps = useActionMenuContext()
23
+ const { isMobile } = useBreakpoints()
24
+ const { t } = useI18n()
25
+ const { showAlert } = useAlert()
26
+ const client = useClient()
27
+
28
+ const currentModel = getCurrentModel(name)
29
+ const editPath = buildEditAttributePath(
30
+ editPathByModelProps,
31
+ currentModel,
32
+ optionFile.name
33
+ )
34
+
35
+ const { fetchStatus, url } = useAppLinkWithStoreFallback(
36
+ mespapiersAppSlug,
37
+ client,
38
+ editPath
39
+ )
40
+ const isAppLinkLoaded = fetchStatus === 'loaded'
41
+ const isEditable = Boolean(editPath) && isEditableAttribute(name, file)
42
+
43
+ const handleCopy = async () => {
44
+ try {
45
+ await navigator.clipboard.writeText(value)
46
+ showAlert({
47
+ message: t(`Viewer.snackbar.copiedToClipboard.success`),
48
+ severity: 'success',
49
+ variant: 'filled',
50
+ icon: false
51
+ })
52
+ } catch (error) {
53
+ showAlert({
54
+ message: t(`Viewer.snackbar.copiedToClipboard.error`),
55
+ severity: 'error',
56
+ variant: 'filled',
57
+ icon: false
58
+ })
59
+ }
60
+ onClose()
61
+ }
62
+
63
+ const handleEdit = cb => {
64
+ if (isAppLinkLoaded) {
65
+ onClose()
66
+ cb && cb()
67
+ }
68
+ }
69
+
70
+ if (isMobile) {
71
+ return (
72
+ <ActionMenuMobile
73
+ onClose={onClose}
74
+ isEditable={isEditable}
75
+ actions={{ handleCopy, handleEdit }}
76
+ appLink={url}
77
+ appSlug={mespapiersAppSlug}
78
+ />
79
+ )
80
+ }
81
+
82
+ return (
83
+ <ActionMenuDesktop
84
+ ref={ref}
85
+ onClose={onClose}
86
+ isEditable={isEditable}
87
+ actions={{ handleCopy, handleEdit }}
88
+ appLink={url}
89
+ appSlug={mespapiersAppSlug}
90
+ />
91
+ )
92
+ })
93
+ ActionMenuWrapper.displayName = 'ActionMenuWrapper'
94
+
95
+ ActionMenuWrapper.propTypes = {
96
+ onClose: PropTypes.func,
97
+ file: PropTypes.object,
98
+ optionFile: PropTypes.shape({
99
+ name: PropTypes.string,
100
+ value: PropTypes.string
101
+ })
102
+ }
103
+
104
+ export default ActionMenuWrapper
@@ -0,0 +1,63 @@
1
+ import has from 'lodash/has'
2
+ import PropTypes from 'prop-types'
3
+ import React from 'react'
4
+
5
+ import Icon, { iconPropType } from 'cozy-ui/transpiled/react/Icon'
6
+ import CarbonCopyIcon from 'cozy-ui/transpiled/react/Icons/CarbonCopy'
7
+ import SafeIcon from 'cozy-ui/transpiled/react/Icons/Safe'
8
+ import Typography from 'cozy-ui/transpiled/react/Typography'
9
+ import { Media, Img, Bd } from 'cozy-ui/transpiled/react/deprecated/Media'
10
+
11
+ import { withViewerLocales } from '../hoc/withViewerLocales'
12
+
13
+ const Certification = ({ icon, title, caption }) => {
14
+ return (
15
+ <div className="u-ph-2 u-pv-1">
16
+ <Media className="u-mb-half" align="top">
17
+ <Img className="u-mr-half">
18
+ <Icon icon={icon} />
19
+ </Img>
20
+ <Bd>
21
+ <Typography variant="body1">{title}</Typography>
22
+ </Bd>
23
+ </Media>
24
+ <Typography variant="caption">{caption}</Typography>
25
+ </div>
26
+ )
27
+ }
28
+
29
+ Certification.propTypes = {
30
+ icon: iconPropType.isRequired,
31
+ title: PropTypes.string.isRequired,
32
+ caption: PropTypes.string.isRequired
33
+ }
34
+
35
+ const Certifications = ({ file, t }) => {
36
+ const hasCarbonCopy = has(file, 'metadata.carbonCopy')
37
+ const hasElectronicSafe = has(file, 'metadata.electronicSafe')
38
+
39
+ return (
40
+ <>
41
+ {hasCarbonCopy && (
42
+ <Certification
43
+ icon={CarbonCopyIcon}
44
+ title={t('Viewer.panel.certifications.carbonCopy.title')}
45
+ caption={t('Viewer.panel.certifications.carbonCopy.caption')}
46
+ />
47
+ )}
48
+ {hasElectronicSafe && (
49
+ <Certification
50
+ icon={SafeIcon}
51
+ title={t('Viewer.panel.certifications.electronicSafe.title')}
52
+ caption={t('Viewer.panel.certifications.electronicSafe.caption')}
53
+ />
54
+ )}
55
+ </>
56
+ )
57
+ }
58
+
59
+ Certifications.propTypes = {
60
+ file: PropTypes.object.isRequired
61
+ }
62
+
63
+ export default withViewerLocales(Certifications)
@@ -0,0 +1,50 @@
1
+ import cx from 'classnames'
2
+ import PropTypes from 'prop-types'
3
+ import React from 'react'
4
+
5
+ import Paper from 'cozy-ui/transpiled/react/Paper'
6
+ import Stack from 'cozy-ui/transpiled/react/Stack'
7
+ import Typography from 'cozy-ui/transpiled/react/Typography'
8
+
9
+ import getPanelBlocks, { getPanelBlocksSpecs } from './getPanelBlocks'
10
+ import { withViewerLocales } from '../hoc/withViewerLocales'
11
+
12
+ const PanelContent = ({ file, isPublic, t }) => {
13
+ const panelBlocks = getPanelBlocks({
14
+ panelBlocksSpecs: getPanelBlocksSpecs(isPublic),
15
+ file
16
+ })
17
+
18
+ return (
19
+ <Stack spacing="s" className={cx('u-flex u-flex-column u-h-100')}>
20
+ <Paper
21
+ className="u-flex u-flex-items-center u-h-3 u-ph-2 u-flex-shrink-0"
22
+ elevation={2}
23
+ square
24
+ >
25
+ <Typography variant="h4">{t('Viewer.panel.title')}</Typography>
26
+ </Paper>
27
+ {panelBlocks.map((PanelBlock, index) => (
28
+ <Paper
29
+ key={index}
30
+ className={cx({
31
+ 'u-flex-grow-1': index === panelBlocks.length - 1
32
+ })}
33
+ elevation={2}
34
+ square
35
+ >
36
+ <Typography variant="h4" className="u-pv-1">
37
+ <PanelBlock file={file} />
38
+ </Typography>
39
+ </Paper>
40
+ ))}
41
+ </Stack>
42
+ )
43
+ }
44
+
45
+ PanelContent.propTypes = {
46
+ file: PropTypes.object.isRequired,
47
+ isPublic: PropTypes.bool
48
+ }
49
+
50
+ export default withViewerLocales(PanelContent)
@@ -0,0 +1,114 @@
1
+ import PropTypes from 'prop-types'
2
+ import React, { useRef, useState, createRef, useMemo, useEffect } from 'react'
3
+
4
+ import {
5
+ isExpiringSoon,
6
+ formatMetadataQualification,
7
+ KNOWN_BILLS_ATTRIBUTES_NAMES,
8
+ getMetadataQualificationType
9
+ } from 'cozy-client/dist/models/paper'
10
+ import List from 'cozy-ui/transpiled/react/List'
11
+
12
+ import ActionMenuWrapper from './ActionMenuWrapper'
13
+ import QualificationListItemContact from './QualificationListItemContact'
14
+ import QualificationListItemDate from './QualificationListItemDate'
15
+ import QualificationListItemInformation from './QualificationListItemInformation'
16
+ import QualificationListItemOther from './QualificationListItemOther'
17
+ import ExpirationAlert from '../components/ExpirationAlert'
18
+ import { withViewerLocales } from '../hoc/withViewerLocales'
19
+
20
+ const ComponentFromMetadataQualificationType = {
21
+ contact: QualificationListItemContact,
22
+ date: QualificationListItemDate,
23
+ information: QualificationListItemInformation,
24
+ other: QualificationListItemOther,
25
+ bills: QualificationListItemInformation
26
+ }
27
+
28
+ const isExpirationAlertHidden = file => {
29
+ return file?.metadata?.hideExpirationAlert ?? false
30
+ }
31
+
32
+ const Qualification = ({ file }) => {
33
+ const { metadata = {} } = file
34
+ const actionBtnRef = useRef([])
35
+ const [optionFile, setOptionFile] = useState({
36
+ id: '',
37
+ name: '',
38
+ value: ''
39
+ })
40
+
41
+ const hideActionsMenu = () => {
42
+ setOptionFile({ id: '', name: '', value: '' })
43
+ }
44
+
45
+ const toggleActionsMenu = (id, name, value) => {
46
+ setOptionFile(prev => {
47
+ if (prev.value) return { id: '', name: '', value: '' }
48
+ return { id, name, value }
49
+ })
50
+ }
51
+
52
+ const formattedMetadataQualification = useMemo(() => {
53
+ const relatedBills = file.bills?.data?.[0]
54
+
55
+ if (relatedBills) {
56
+ const formattedBillsMetadata = KNOWN_BILLS_ATTRIBUTES_NAMES.map(
57
+ attrName => ({ name: attrName, value: relatedBills[attrName] })
58
+ )
59
+
60
+ return formatMetadataQualification(metadata).concat(
61
+ formattedBillsMetadata
62
+ )
63
+ }
64
+
65
+ return formatMetadataQualification(metadata)
66
+ }, [metadata, file.bills?.data])
67
+
68
+ useEffect(() => {
69
+ actionBtnRef.current = formattedMetadataQualification.map(
70
+ (_, idx) => actionBtnRef.current[idx] ?? createRef()
71
+ )
72
+ }, [formattedMetadataQualification])
73
+
74
+ return (
75
+ <>
76
+ {isExpiringSoon(file) && !isExpirationAlertHidden(file) && (
77
+ <ExpirationAlert file={file} />
78
+ )}
79
+ <List className="u-pv-1">
80
+ {formattedMetadataQualification.map((meta, idx) => {
81
+ const { name } = meta
82
+ const metadataQualificationType = getMetadataQualificationType(name)
83
+ const QualificationListItemComp =
84
+ ComponentFromMetadataQualificationType[metadataQualificationType]
85
+
86
+ return (
87
+ <QualificationListItemComp
88
+ key={idx}
89
+ file={file}
90
+ ref={actionBtnRef.current[idx]}
91
+ formattedMetadataQualification={meta}
92
+ toggleActionsMenu={val => toggleActionsMenu(idx, name, val)}
93
+ />
94
+ )
95
+ })}
96
+
97
+ {optionFile.name && (
98
+ <ActionMenuWrapper
99
+ onClose={hideActionsMenu}
100
+ file={file}
101
+ optionFile={optionFile}
102
+ ref={actionBtnRef.current[optionFile.id]}
103
+ />
104
+ )}
105
+ </List>
106
+ </>
107
+ )
108
+ }
109
+
110
+ Qualification.propTypes = {
111
+ file: PropTypes.object.isRequired
112
+ }
113
+
114
+ export default withViewerLocales(Qualification)
@@ -0,0 +1,85 @@
1
+ import PropTypes from 'prop-types'
2
+ import React, { useRef, useState } from 'react'
3
+
4
+ import {
5
+ getTranslatedNameForContact,
6
+ formatContactValue
7
+ } from 'cozy-client/dist/models/paper'
8
+ import Icon from 'cozy-ui/transpiled/react/Icon'
9
+ import IconButton from 'cozy-ui/transpiled/react/IconButton'
10
+ import Dots from 'cozy-ui/transpiled/react/Icons/Dots'
11
+ import ListItem from 'cozy-ui/transpiled/react/ListItem'
12
+ import ListItemSecondaryAction from 'cozy-ui/transpiled/react/ListItemSecondaryAction'
13
+ import Spinner from 'cozy-ui/transpiled/react/Spinner'
14
+ import { useI18n } from 'cozy-ui/transpiled/react/providers/I18n'
15
+
16
+ import ActionMenuWrapper from './ActionMenuWrapper'
17
+ import QualificationListItemText from './QualificationListItemText'
18
+ import useReferencedContactName from '../hooks/useReferencedContactName'
19
+
20
+ const QualificationListItemContact = ({ file }) => {
21
+ const { lang } = useI18n()
22
+ const actionBtnRef = useRef()
23
+ const [optionFile, setOptionFile] = useState({
24
+ name: '',
25
+ value: ''
26
+ })
27
+
28
+ const hideActionsMenu = () => setOptionFile({ name: '', value: '' })
29
+ const toggleActionsMenu = (name, value) =>
30
+ setOptionFile(prev => {
31
+ if (prev.value) return { name: '', value: '' }
32
+ return { name, value }
33
+ })
34
+
35
+ const { contacts, isLoadingContacts } = useReferencedContactName(file)
36
+
37
+ if (isLoadingContacts) {
38
+ return (
39
+ <ListItem className="u-pl-2 u-pr-3">
40
+ <Spinner color="var(--secondaryTextColor)" />
41
+ </ListItem>
42
+ )
43
+ }
44
+
45
+ const formattedTitle = getTranslatedNameForContact({ lang })
46
+ const formattedValue = formatContactValue(contacts)
47
+
48
+ if (!isLoadingContacts && !formattedValue) {
49
+ return null
50
+ }
51
+
52
+ return (
53
+ <>
54
+ <ListItem className="u-ph-2">
55
+ <QualificationListItemText
56
+ primary={formattedTitle}
57
+ secondary={formattedValue}
58
+ />
59
+ <ListItemSecondaryAction>
60
+ <IconButton
61
+ ref={actionBtnRef}
62
+ onClick={() => toggleActionsMenu('contact', formattedValue)}
63
+ >
64
+ <Icon icon={Dots} />
65
+ </IconButton>
66
+ </ListItemSecondaryAction>
67
+ </ListItem>
68
+
69
+ {optionFile.value && (
70
+ <ActionMenuWrapper
71
+ onClose={hideActionsMenu}
72
+ file={file}
73
+ optionFile={optionFile}
74
+ ref={actionBtnRef}
75
+ />
76
+ )}
77
+ </>
78
+ )
79
+ }
80
+
81
+ QualificationListItemContact.propTypes = {
82
+ file: PropTypes.object.isRequired
83
+ }
84
+
85
+ export default QualificationListItemContact