cozy-ui 74.4.0 → 74.5.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 (36) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/package.json +2 -2
  3. package/react/Snackbar/Readme.md +10 -4
  4. package/react/Snackbar/index.js +12 -5
  5. package/react/Viewer/Footer/BottomSheetContent.jsx +2 -2
  6. package/react/Viewer/Footer/FooterContent.jsx +13 -8
  7. package/react/Viewer/Panel/ActionMenuWrapper.jsx +69 -0
  8. package/react/Viewer/Panel/Qualification.jsx +86 -63
  9. package/react/Viewer/Panel/QualificationListItemContact.jsx +76 -0
  10. package/react/Viewer/Panel/QualificationListItemDate.jsx +47 -0
  11. package/react/Viewer/Panel/QualificationListItemNumber.jsx +42 -0
  12. package/react/Viewer/Panel/QualificationListItemOther.jsx +64 -0
  13. package/react/Viewer/Readme.md +8 -9
  14. package/react/Viewer/ViewerContainer.jsx +23 -18
  15. package/react/Viewer/helpers.js +64 -0
  16. package/react/Viewer/helpers.spec.js +50 -1
  17. package/react/Viewer/{Footer → hooks}/useReferencedContactName.jsx +5 -2
  18. package/react/Viewer/locales/en.json +27 -8
  19. package/react/Viewer/locales/fr.json +27 -8
  20. package/react/Viewer/snackbar/ViewerSnackbar.jsx +30 -0
  21. package/react/Viewer/snackbar/ViewerSnackbarProvider.jsx +64 -0
  22. package/transpiled/react/Snackbar/index.js +10 -5
  23. package/transpiled/react/Viewer/Footer/BottomSheetContent.js +2 -4
  24. package/transpiled/react/Viewer/Footer/FooterContent.js +12 -12
  25. package/transpiled/react/Viewer/Panel/ActionMenuWrapper.js +72 -0
  26. package/transpiled/react/Viewer/Panel/Qualification.js +104 -47
  27. package/transpiled/react/Viewer/Panel/QualificationListItemContact.js +89 -0
  28. package/transpiled/react/Viewer/Panel/QualificationListItemDate.js +49 -0
  29. package/transpiled/react/Viewer/Panel/QualificationListItemNumber.js +41 -0
  30. package/transpiled/react/Viewer/Panel/QualificationListItemOther.js +50 -0
  31. package/transpiled/react/Viewer/ViewerContainer.js +4 -2
  32. package/transpiled/react/Viewer/helpers.js +57 -0
  33. package/transpiled/react/Viewer/{Footer → hooks}/useReferencedContactName.js +3 -2
  34. package/transpiled/react/Viewer/snackbar/ViewerSnackbar.js +25 -0
  35. package/transpiled/react/Viewer/snackbar/ViewerSnackbarProvider.js +73 -0
  36. package/transpiled/react/Viewer/withViewerLocales.js +54 -16
package/CHANGELOG.md CHANGED
@@ -1,3 +1,41 @@
1
+ # [74.5.0](https://github.com/cozy/cozy-ui/compare/v74.4.2...v74.5.0) (2022-09-09)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Change defaultProps to Snackbar component ([c749957](https://github.com/cozy/cozy-ui/commit/c749957))
7
+ * Disabling the Portal on the BottomSheet component in the Viewer ([35ede40](https://github.com/cozy/cozy-ui/commit/35ede40))
8
+ * Translations of the Qualification Viewer ([489f27a](https://github.com/cozy/cozy-ui/commit/489f27a))
9
+
10
+
11
+ ### Features
12
+
13
+ * Add ActionMenuWrapper component ([653e7d5](https://github.com/cozy/cozy-ui/commit/653e7d5))
14
+ * Add arrays of known metadata names ([ab84458](https://github.com/cozy/cozy-ui/commit/ab84458))
15
+ * Add helper for formatting all known metadata ([2fa5906](https://github.com/cozy/cozy-ui/commit/2fa5906))
16
+ * Add QualificationListItem's components ([93f2dd1](https://github.com/cozy/cozy-ui/commit/93f2dd1))
17
+ * Add QualificationListItem's components to Qualification ([c987346](https://github.com/cozy/cozy-ui/commit/c987346))
18
+ * Add ViewerSnackbar component to display alerts in Viewer ([1aef68c](https://github.com/cozy/cozy-ui/commit/1aef68c))
19
+ * Add ViewerSnackbarContext to manage internal Snackbar component ([ce4d2f1](https://github.com/cozy/cozy-ui/commit/ce4d2f1))
20
+ * Create an alert when the attribute is copied ([ccbd467](https://github.com/cozy/cozy-ui/commit/ccbd467))
21
+ * Implement ViewerSnackbar in ViewerContainer component ([3c5eeae](https://github.com/cozy/cozy-ui/commit/3c5eeae))
22
+ * Move `useReferencedContactName` call to Qualification component ([39ccd6e](https://github.com/cozy/cozy-ui/commit/39ccd6e))
23
+ * Update Viewer locales files ([f418f95](https://github.com/cozy/cozy-ui/commit/f418f95))
24
+
25
+ ## [74.4.2](https://github.com/cozy/cozy-ui/compare/v74.4.1...v74.4.2) (2022-09-08)
26
+
27
+
28
+ ### Bug Fixes
29
+
30
+ * isLoadingContacts on useReferencedContactName hook ([dab3e09](https://github.com/cozy/cozy-ui/commit/dab3e09))
31
+
32
+ ## [74.4.1](https://github.com/cozy/cozy-ui/compare/v74.4.0...v74.4.1) (2022-09-08)
33
+
34
+
35
+ ### Bug Fixes
36
+
37
+ * Restore BottomSheet items' gap in `FooterContent` container ([7ba1caf](https://github.com/cozy/cozy-ui/commit/7ba1caf))
38
+
1
39
  # [74.4.0](https://github.com/cozy/cozy-ui/compare/v74.3.0...v74.4.0) (2022-09-06)
2
40
 
3
41
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-ui",
3
- "version": "74.4.0",
3
+ "version": "74.5.0",
4
4
  "description": "Cozy apps UI SDK",
5
5
  "main": "./index.js",
6
6
  "bin": {
@@ -65,6 +65,7 @@
65
65
  "intersection-observer"
66
66
  ],
67
67
  "devDependencies": {
68
+ "@argos-ci/cli": "^0.2.1",
68
69
  "@babel/cli": "7.17.6",
69
70
  "@babel/core": "7.17.8",
70
71
  "@babel/helper-builder-react-jsx": "7.16.7",
@@ -80,7 +81,6 @@
80
81
  "@testing-library/react": "11.2.7",
81
82
  "@testing-library/react-hooks": "^3.2.1",
82
83
  "@testing-library/user-event": "^14.4.2",
83
- "argos-cli": "^0.3.3",
84
84
  "autoprefixer-stylus": "1.0.0",
85
85
  "babel-loader": "8.2.4",
86
86
  "babel-plugin-css-modules-transform": "1.6.2",
@@ -7,6 +7,9 @@ import IconButton from 'cozy-ui/transpiled/react/IconButton'
7
7
  import Typography from 'cozy-ui/transpiled/react/Typography'
8
8
  import Icon from 'cozy-ui/transpiled/react/Icon'
9
9
  import InfoIcon from 'cozy-ui/transpiled/react/Icons/Info'
10
+ import {
11
+ BreakpointsProvider
12
+ } from 'cozy-ui/transpiled/react/hooks/useBreakpoints'
10
13
 
11
14
  initialState = { open: false }
12
15
 
@@ -14,7 +17,7 @@ const handleToggle = () => {setState(state => ({ open: !state.open }))}
14
17
 
15
18
  ;
16
19
 
17
- <>
20
+ <BreakpointsProvider>
18
21
  <Button
19
22
  variant="ghost"
20
23
  size="small"
@@ -34,7 +37,7 @@ const handleToggle = () => {setState(state => ({ open: !state.open }))}
34
37
  }
35
38
  onClose={handleToggle}
36
39
  />
37
- </>
40
+ </BreakpointsProvider>
38
41
  ```
39
42
 
40
43
  ### With `Alert` inside the `Snackbar`
@@ -44,6 +47,9 @@ import Snackbar from 'cozy-ui/transpiled/react/Snackbar'
44
47
  import Alert from 'cozy-ui/transpiled/react/Alert'
45
48
  import Button from 'cozy-ui/transpiled/react/Buttons'
46
49
  import Variants from 'cozy-ui/docs/components/Variants'
50
+ import {
51
+ BreakpointsProvider
52
+ } from 'cozy-ui/transpiled/react/hooks/useBreakpoints'
47
53
 
48
54
  initialState = { open: isTesting() }
49
55
 
@@ -54,7 +60,7 @@ const initialVariants = [{ primary: true, secondary: true, success: false, error
54
60
 
55
61
  ;
56
62
 
57
- <>
63
+ <BreakpointsProvider>
58
64
  <Variants initialVariants={initialVariants} radio>
59
65
  {variant => (
60
66
  <>
@@ -77,5 +83,5 @@ const initialVariants = [{ primary: true, secondary: true, success: false, error
77
83
  label="Open snackbar"
78
84
  onClick={handleToggle}
79
85
  />
80
- </>
86
+ </BreakpointsProvider>
81
87
  ```
@@ -1,9 +1,19 @@
1
1
  import React, { forwardRef } from 'react'
2
2
  import MuiSnackbar from '@material-ui/core/Snackbar'
3
+ import useBreakpoints from '../hooks/useBreakpoints'
3
4
 
4
5
  const Snackbar = forwardRef(({ children, ...props }, ref) => {
6
+ const { isDesktop } = useBreakpoints()
7
+
5
8
  return (
6
- <MuiSnackbar ref={ref} {...props}>
9
+ <MuiSnackbar
10
+ ref={ref}
11
+ anchorOrigin={{
12
+ vertical: !isDesktop ? 'bottom' : 'top',
13
+ horizontal: 'center'
14
+ }}
15
+ {...props}
16
+ >
7
17
  {children}
8
18
  </MuiSnackbar>
9
19
  )
@@ -12,10 +22,7 @@ const Snackbar = forwardRef(({ children, ...props }, ref) => {
12
22
  Snackbar.displayName = 'Snackbar'
13
23
 
14
24
  Snackbar.defaultProps = {
15
- anchorOrigin: {
16
- vertical: 'top',
17
- horizontal: 'center'
18
- }
25
+ autoHideDuration: 2000
19
26
  }
20
27
 
21
28
  export default Snackbar
@@ -5,7 +5,7 @@ import { BottomSheetItem } from '../../BottomSheet'
5
5
 
6
6
  import getPanelBlocks, { panelBlocksSpecs } from '../Panel/getPanelBlocks'
7
7
 
8
- const BottomSheetContent = ({ file, contactsFullname }) => {
8
+ const BottomSheetContent = ({ file }) => {
9
9
  const panelBlocks = getPanelBlocks({ panelBlocksSpecs, file })
10
10
 
11
11
  return panelBlocks.map((PanelBlock, index) => (
@@ -14,7 +14,7 @@ const BottomSheetContent = ({ file, contactsFullname }) => {
14
14
  disableGutters
15
15
  disableElevation={index === panelBlocks.length - 1}
16
16
  >
17
- <PanelBlock file={file} contactsFullname={contactsFullname} />
17
+ <PanelBlock file={file} />
18
18
  </BottomSheetItem>
19
19
  ))
20
20
  }
@@ -1,12 +1,12 @@
1
1
  import React, { useMemo, Children, cloneElement, isValidElement } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
  import { makeStyles } from '@material-ui/core/styles'
4
+ import cx from 'classnames'
4
5
 
5
6
  import BottomSheet, { BottomSheetHeader } from '../../BottomSheet'
6
7
 
7
8
  import { isValidForPanel } from '../helpers'
8
9
  import BottomSheetContent from './BottomSheetContent'
9
- import useReferencedContactName from './useReferencedContactName'
10
10
 
11
11
  const useStyles = makeStyles(theme => ({
12
12
  footer: {
@@ -18,6 +18,9 @@ const useStyles = makeStyles(theme => ({
18
18
  paddingRight: '1rem',
19
19
  borderTop: `1px solid ${theme.palette.divider}`,
20
20
  columnGap: '0.5rem'
21
+ },
22
+ bottomSheetHeader: {
23
+ columnGap: '0.5rem'
21
24
  }
22
25
  }))
23
26
 
@@ -26,8 +29,6 @@ const FooterContent = ({ file, toolbarRef, children }) => {
26
29
 
27
30
  const toolbarProps = useMemo(() => ({ ref: toolbarRef }), [toolbarRef])
28
31
 
29
- const { contactName, isLoadingContacts } = useReferencedContactName(file)
30
-
31
32
  const FooterActionButtons =
32
33
  Children.toArray(children).find(child => {
33
34
  return (
@@ -42,14 +43,18 @@ const FooterContent = ({ file, toolbarRef, children }) => {
42
43
  })
43
44
  : null
44
45
 
45
- // We have to wait for the Contact request to finish before rendering `BottomSheet`, because it doesn't handle async well.
46
- if (isValidForPanel({ file }) && !isLoadingContacts) {
46
+ if (isValidForPanel({ file })) {
47
47
  return (
48
- <BottomSheet toolbarProps={toolbarProps}>
49
- <BottomSheetHeader className="u-ph-1 u-pb-1">
48
+ <BottomSheet
49
+ toolbarProps={toolbarProps}
50
+ portalProps={{ disablePortal: true }}
51
+ >
52
+ <BottomSheetHeader
53
+ className={cx('u-ph-1 u-pb-1', styles.bottomSheetHeader)}
54
+ >
50
55
  {FooterActionButtonsWithFile}
51
56
  </BottomSheetHeader>
52
- <BottomSheetContent file={file} contactsFullname={contactName} />
57
+ <BottomSheetContent file={file} />
53
58
  </BottomSheet>
54
59
  )
55
60
  }
@@ -0,0 +1,69 @@
1
+ import React, { forwardRef } from 'react'
2
+ import PropTypes from 'prop-types'
3
+
4
+ import List from '../../MuiCozyTheme/List'
5
+ import ListItem from '../../MuiCozyTheme/ListItem'
6
+ import ListItemIcon from '../../MuiCozyTheme/ListItemIcon'
7
+ import ListItemText from '../../ListItemText'
8
+ import Icon from '../../Icon'
9
+ import Copy from '../../Icons/Copy'
10
+ import BottomSheet, { BottomSheetItem } from '../../BottomSheet'
11
+ import ActionMenu, { ActionMenuItem } from '../../ActionMenu'
12
+ import Typography from '../../Typography'
13
+ import useBreakpoints from '../../hooks/useBreakpoints'
14
+ import { useI18n } from '../../I18n'
15
+ import useViewerSnackbar from '../snackbar/ViewerSnackbarProvider'
16
+
17
+ const ActionMenuWrapper = forwardRef(({ onClose, value }, ref) => {
18
+ const { isMobile } = useBreakpoints()
19
+ const { t } = useI18n()
20
+ const { showViewerSnackbar } = useViewerSnackbar()
21
+
22
+ const handleCopy = () => {
23
+ if (navigator?.clipboard) {
24
+ navigator.clipboard.writeText(value)
25
+ showViewerSnackbar(
26
+ 'secondary',
27
+ t(`Viewer.snackbar.copiedToClipboard.success`)
28
+ )
29
+ } else {
30
+ showViewerSnackbar('error', t(`Viewer.snackbar.copiedToClipboard.error`))
31
+ }
32
+ onClose()
33
+ }
34
+
35
+ if (isMobile) {
36
+ return (
37
+ <BottomSheet backdrop onClose={onClose}>
38
+ <BottomSheetItem disableGutters>
39
+ <List>
40
+ <ListItem button onClick={handleCopy}>
41
+ <ListItemIcon>
42
+ <Icon icon={Copy} />
43
+ </ListItemIcon>
44
+ <ListItemText
45
+ primary={t(`Viewer.panel.qualification.actions.copyClipboard`)}
46
+ />
47
+ </ListItem>
48
+ </List>
49
+ </BottomSheetItem>
50
+ </BottomSheet>
51
+ )
52
+ }
53
+
54
+ return (
55
+ <ActionMenu onClose={onClose} anchorElRef={ref}>
56
+ <ActionMenuItem onClick={handleCopy} left={<Icon icon={Copy} />}>
57
+ <Typography>{t(`Viewer.panel.qualification.actions.copy`)}</Typography>
58
+ </ActionMenuItem>
59
+ </ActionMenu>
60
+ )
61
+ })
62
+ ActionMenuWrapper.displayName = 'ActionMenuWrapper'
63
+
64
+ ActionMenuWrapper.propTypes = {
65
+ onClose: PropTypes.func,
66
+ value: PropTypes.string
67
+ }
68
+
69
+ export default ActionMenuWrapper
@@ -1,84 +1,107 @@
1
- import React from 'react'
1
+ import React, { useRef, useState, createRef, useMemo, useEffect } from 'react'
2
2
  import PropTypes from 'prop-types'
3
3
 
4
- import { models } from 'cozy-client'
5
-
6
4
  import List from '../../MuiCozyTheme/List'
7
- import ListItem from '../../MuiCozyTheme/ListItem'
8
- import QualificationListItemText from './QualificationListItemText'
9
5
  import { withViewerLocales } from '../withViewerLocales'
10
- import MidEllipsis from '../../MidEllipsis'
6
+ import {
7
+ formatMetadataQualification,
8
+ knownDateMetadataNames,
9
+ knowNumberMetadataNames,
10
+ knowOtherMetadataNames
11
+ } from '../helpers'
12
+ import QualificationListItemContact from './QualificationListItemContact'
13
+ import ActionMenuWrapper from './ActionMenuWrapper'
14
+ import QualificationListItemDate from './QualificationListItemDate'
15
+ import QualificationListItemNumber from './QualificationListItemNumber'
16
+ import QualificationListItemOther from './QualificationListItemOther'
17
+
18
+ const Qualification = ({ file = {} }) => {
19
+ const { metadata = {} } = file
20
+ const actionBtnRef = useRef([])
21
+ const [optionFile, setOptionFile] = useState({
22
+ isOpen: false,
23
+ id: '',
24
+ value: ''
25
+ })
26
+
27
+ const hideActionsMenu = () => {
28
+ setOptionFile({ isOpen: false, id: '', value: '' })
29
+ }
11
30
 
12
- const {
13
- document: {
14
- locales: { getBoundT }
31
+ const toggleActionsMenu = (id, value) => {
32
+ setOptionFile(prev => {
33
+ if (prev.isOpen) return { isOpen: false, id: '', value: '' }
34
+ return { isOpen: true, id, value }
35
+ })
15
36
  }
16
- } = models
17
37
 
18
- const Qualification = ({ file = {}, contactsFullname, t, f, lang }) => {
19
- const scannerT = getBoundT(lang)
38
+ const metadataComputed = useMemo(() => {
39
+ return formatMetadataQualification(metadata)
40
+ }, [metadata])
20
41
 
21
- const { name: filename, metadata = {} } = file
22
- const {
23
- qualification = {},
24
- page: pageLabel,
25
- datetime,
26
- datetimeLabel
27
- } = metadata
42
+ useEffect(() => {
43
+ actionBtnRef.current = metadataComputed.map(
44
+ (_, idx) => actionBtnRef.current[idx] ?? createRef()
45
+ )
46
+ }, [metadataComputed])
28
47
 
29
48
  return (
30
49
  <List className={'u-pv-1'}>
31
- {datetime && (
32
- <ListItem className={'u-ph-2'}>
33
- <QualificationListItemText
34
- primary={t(
35
- `Viewer.panel.qualification.date.title.${
36
- datetimeLabel === 'datetime' || datetimeLabel === undefined
37
- ? 'addedOn'
38
- : datetimeLabel
39
- }`
40
- )}
41
- secondary={f(datetime, 'DD/MM/YYYY')}
42
- />
43
- </ListItem>
44
- )}
45
- {contactsFullname && (
46
- <ListItem className={'u-ph-2'}>
47
- <QualificationListItemText
48
- primary={t('Viewer.panel.qualification.identity')}
49
- secondary={contactsFullname}
50
- />
51
- </ListItem>
52
- )}
53
- <ListItem className={'u-ph-2'}>
54
- <QualificationListItemText
55
- primary={t('Viewer.panel.qualification.label.title')}
56
- secondary={
57
- <MidEllipsis
58
- text={
59
- pageLabel
60
- ? t(`Viewer.panel.qualification.label.${pageLabel}`)
61
- : filename
62
- }
50
+ {metadataComputed.map((meta, idx) => {
51
+ const { name } = meta
52
+
53
+ if (knownDateMetadataNames.includes(name)) {
54
+ return (
55
+ <QualificationListItemDate
56
+ key={idx}
57
+ ref={actionBtnRef.current[idx]}
58
+ metadataComputed={meta}
59
+ toggleActionsMenu={val => toggleActionsMenu(idx, val)}
63
60
  />
61
+ )
62
+ }
63
+
64
+ if (knowNumberMetadataNames.includes(name)) {
65
+ return (
66
+ <QualificationListItemNumber
67
+ key={idx}
68
+ ref={actionBtnRef.current[idx]}
69
+ metadataComputed={meta}
70
+ toggleActionsMenu={val => toggleActionsMenu(idx, val)}
71
+ />
72
+ )
73
+ }
74
+
75
+ if (knowOtherMetadataNames.includes(name)) {
76
+ if (name === 'owner') {
77
+ return <QualificationListItemContact key={idx} file={file} />
64
78
  }
79
+
80
+ return (
81
+ <QualificationListItemOther
82
+ key={idx}
83
+ ref={actionBtnRef.current[idx]}
84
+ filename={file.name}
85
+ metadataComputed={meta}
86
+ toggleActionsMenu={val => toggleActionsMenu(idx, val)}
87
+ />
88
+ )
89
+ }
90
+ })}
91
+
92
+ {optionFile.isOpen && (
93
+ <ActionMenuWrapper
94
+ onClose={hideActionsMenu}
95
+ value={optionFile.value}
96
+ ref={actionBtnRef.current[optionFile.id]}
65
97
  />
66
- </ListItem>
67
- <ListItem className={'u-ph-2'}>
68
- <QualificationListItemText
69
- primary={t('Viewer.panel.qualification.qualification')}
70
- secondary={scannerT(`Scan.items.${qualification.label}`)}
71
- />
72
- </ListItem>
98
+ )}
73
99
  </List>
74
100
  )
75
101
  }
76
102
 
77
103
  Qualification.propTypes = {
78
- file: PropTypes.object.isRequired,
79
- t: PropTypes.func.isRequired,
80
- f: PropTypes.func.isRequired,
81
- lang: PropTypes.string.isRequired
104
+ file: PropTypes.object
82
105
  }
83
106
 
84
- export default withViewerLocales(Qualification)
107
+ export default withViewerLocales(React.memo(Qualification))
@@ -0,0 +1,76 @@
1
+ import React, { useRef, useState } from 'react'
2
+ import PropTypes from 'prop-types'
3
+
4
+ import ListItem from '../../MuiCozyTheme/ListItem'
5
+ import ListItemSecondaryAction from '../../MuiCozyTheme/ListItemSecondaryAction'
6
+ import IconButton from '../../IconButton'
7
+ import Icon from '../../Icon'
8
+ import Dots from '../../Icons/Dots'
9
+ import QualificationListItemText from './QualificationListItemText'
10
+ import Spinner from '../../Spinner'
11
+ import useReferencedContactName from '../hooks/useReferencedContactName'
12
+ import { useI18n } from '../../I18n'
13
+ import ActionMenuWrapper from './ActionMenuWrapper'
14
+
15
+ const QualificationListItemContact = ({ file }) => {
16
+ const { t } = useI18n()
17
+ const actionBtnRef = useRef()
18
+ const [optionFile, setOptionFile] = useState({
19
+ isOpen: false,
20
+ value: ''
21
+ })
22
+
23
+ const hideActionsMenu = () => setOptionFile({ isOpen: false, value: '' })
24
+ const toggleActionsMenu = value =>
25
+ setOptionFile(prev => {
26
+ if (prev.isOpen) return { isOpen: false, value: '' }
27
+ return { isOpen: true, value }
28
+ })
29
+
30
+ const { contactName, isLoadingContacts } = useReferencedContactName(file)
31
+
32
+ if (isLoadingContacts) {
33
+ return (
34
+ <ListItem className={'u-pl-2 u-pr-3'}>
35
+ <Spinner color="var(--secondaryTextColor)" />
36
+ </ListItem>
37
+ )
38
+ }
39
+
40
+ if (!isLoadingContacts && !contactName) {
41
+ return null
42
+ }
43
+
44
+ return (
45
+ <>
46
+ <ListItem className={'u-ph-2'}>
47
+ <QualificationListItemText
48
+ primary={t('Viewer.panel.qualification.owner')}
49
+ secondary={contactName}
50
+ />
51
+ <ListItemSecondaryAction>
52
+ <IconButton
53
+ ref={actionBtnRef}
54
+ onClick={() => toggleActionsMenu(contactName)}
55
+ >
56
+ <Icon icon={Dots} />
57
+ </IconButton>
58
+ </ListItemSecondaryAction>
59
+ </ListItem>
60
+
61
+ {optionFile.isOpen && (
62
+ <ActionMenuWrapper
63
+ onClose={hideActionsMenu}
64
+ value={optionFile.value}
65
+ ref={actionBtnRef}
66
+ />
67
+ )}
68
+ </>
69
+ )
70
+ }
71
+
72
+ QualificationListItemContact.propTypes = {
73
+ file: PropTypes.object.isRequired
74
+ }
75
+
76
+ export default QualificationListItemContact
@@ -0,0 +1,47 @@
1
+ import React, { forwardRef } from 'react'
2
+ import PropTypes from 'prop-types'
3
+
4
+ import ListItem from '../../MuiCozyTheme/ListItem'
5
+ import ListItemSecondaryAction from '../../MuiCozyTheme/ListItemSecondaryAction'
6
+ import IconButton from '../../IconButton'
7
+ import Icon from '../../Icon'
8
+ import Dots from '../../Icons/Dots'
9
+ import QualificationListItemText from './QualificationListItemText'
10
+ import { useI18n } from '../../I18n'
11
+ import { formatDate } from '../helpers'
12
+
13
+ const QualificationListItemDate = forwardRef(
14
+ ({ metadataComputed, toggleActionsMenu }, ref) => {
15
+ const { t, f, lang } = useI18n()
16
+ const { name, value } = metadataComputed
17
+ const formattedDate = formatDate({ f, lang, date: value })
18
+
19
+ return (
20
+ <ListItem className={'u-pl-2 u-pr-3'}>
21
+ <QualificationListItemText
22
+ primary={t(`Viewer.panel.qualification.date.title.${name}`)}
23
+ secondary={formattedDate}
24
+ />
25
+ <ListItemSecondaryAction>
26
+ <IconButton
27
+ ref={ref}
28
+ onClick={() => toggleActionsMenu(formattedDate)}
29
+ >
30
+ <Icon icon={Dots} />
31
+ </IconButton>
32
+ </ListItemSecondaryAction>
33
+ </ListItem>
34
+ )
35
+ }
36
+ )
37
+ QualificationListItemDate.displayName = 'QualificationListItemDate'
38
+
39
+ QualificationListItemDate.propTypes = {
40
+ metadataComputed: PropTypes.shape({
41
+ name: PropTypes.string,
42
+ value: PropTypes.string
43
+ }).isRequired,
44
+ toggleActionsMenu: PropTypes.func.isRequired
45
+ }
46
+
47
+ export default QualificationListItemDate
@@ -0,0 +1,42 @@
1
+ import React, { forwardRef } from 'react'
2
+ import PropTypes from 'prop-types'
3
+
4
+ import ListItem from '../../MuiCozyTheme/ListItem'
5
+ import ListItemSecondaryAction from '../../MuiCozyTheme/ListItemSecondaryAction'
6
+ import IconButton from '../../IconButton'
7
+ import Icon from '../../Icon'
8
+ import Dots from '../../Icons/Dots'
9
+ import QualificationListItemText from './QualificationListItemText'
10
+ import { useI18n } from '../../I18n'
11
+
12
+ const QualificationListItemNumber = forwardRef(
13
+ ({ metadataComputed, toggleActionsMenu }, ref) => {
14
+ const { t } = useI18n()
15
+ const { name, value } = metadataComputed
16
+
17
+ return (
18
+ <ListItem className={'u-pl-2 u-pr-3'}>
19
+ <QualificationListItemText
20
+ primary={t(`Viewer.panel.qualification.number.title.${name}`)}
21
+ secondary={value}
22
+ />
23
+ <ListItemSecondaryAction>
24
+ <IconButton ref={ref} onClick={() => toggleActionsMenu(value)}>
25
+ <Icon icon={Dots} />
26
+ </IconButton>
27
+ </ListItemSecondaryAction>
28
+ </ListItem>
29
+ )
30
+ }
31
+ )
32
+ QualificationListItemNumber.displayName = 'QualificationListItemNumber'
33
+
34
+ QualificationListItemNumber.propTypes = {
35
+ metadataComputed: PropTypes.shape({
36
+ name: PropTypes.string,
37
+ value: PropTypes.string
38
+ }).isRequired,
39
+ toggleActionsMenu: PropTypes.func.isRequired
40
+ }
41
+
42
+ export default QualificationListItemNumber