cozy-ui 67.0.2 → 68.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/package.json +1 -1
- package/react/Buttons/index.jsx +20 -6
- package/react/CozyDialogs/ConfirmDialog.jsx +7 -1
- package/react/CozyDialogs/Dialog.jsx +7 -1
- package/react/CozyDialogs/IllustrationDialog.jsx +7 -1
- package/react/CozyDialogs/Readme.md +122 -99
- package/react/MuiCozyTheme/makeOverrides.js +13 -1
- package/react/Viewer/Footer/DownloadButton.jsx +1 -1
- package/react/Viewer/Footer/FooterActionButtons.jsx +20 -0
- package/react/Viewer/Footer/FooterActionButtons.spec.jsx +30 -0
- package/react/Viewer/Footer/FooterContent.jsx +26 -41
- package/react/Viewer/Footer/ForwardOrDownloadButton.jsx +24 -0
- package/react/Viewer/Footer/Sharing.jsx +1 -1
- package/react/Viewer/Footer/helpers.js +16 -0
- package/react/Viewer/Footer/useReferencedContactName.jsx +32 -0
- package/react/Viewer/Footer.jsx +5 -3
- package/react/Viewer/Panel/getPanelBlocks.spec.jsx +60 -0
- package/react/Viewer/Readme.md +25 -3
- package/react/Viewer/ViewerContainer.jsx +5 -12
- package/react/Viewer/ViewerInformationsWrapper.jsx +10 -9
- package/react/Viewer/ViewerInformationsWrapper.spec.jsx +63 -0
- package/react/Viewer/helpers.js +10 -0
- package/react/__snapshots__/examples.spec.jsx.snap +21 -21
- package/transpiled/react/Buttons/index.js +14 -6
- package/transpiled/react/CozyDialogs/ConfirmDialog.js +5 -1
- package/transpiled/react/CozyDialogs/Dialog.js +5 -1
- package/transpiled/react/CozyDialogs/IllustrationDialog.js +5 -1
- package/transpiled/react/MuiCozyTheme/makeOverrides.js +13 -1
- package/transpiled/react/Viewer/Footer/DownloadButton.js +1 -1
- package/transpiled/react/Viewer/Footer/FooterActionButtons.js +20 -0
- package/transpiled/react/Viewer/Footer/FooterContent.js +20 -42
- package/transpiled/react/Viewer/Footer/ForwardOrDownloadButton.js +20 -0
- package/transpiled/react/Viewer/Footer/Sharing.js +1 -1
- package/transpiled/react/Viewer/Footer/helpers.js +16 -1
- package/transpiled/react/Viewer/Footer/useReferencedContactName.js +35 -0
- package/transpiled/react/Viewer/Footer.js +7 -4
- package/transpiled/react/Viewer/ViewerContainer.js +4 -8
- package/transpiled/react/Viewer/ViewerInformationsWrapper.js +6 -7
- package/transpiled/react/Viewer/helpers.js +11 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,55 @@
|
|
|
1
|
+
# [68.0.0](https://github.com/cozy/cozy-ui/compare/v67.0.4...v68.0.0) (2022-05-24)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* Warning of proptypes ([7b2c464](https://github.com/cozy/cozy-ui/commit/7b2c464))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* Add FooterActionButtons component ([1c3efc1](https://github.com/cozy/cozy-ui/commit/1c3efc1))
|
|
12
|
+
* Refactor the viewer to let the app handle the action buttons ([60084d6](https://github.com/cozy/cozy-ui/commit/60084d6))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### BREAKING CHANGES
|
|
16
|
+
|
|
17
|
+
* The management of action buttons
|
|
18
|
+
should now be handled on the application side
|
|
19
|
+
via the `FooterActionButtons` component.
|
|
20
|
+
The `disableSharing` prop has also been removed, as it is no longer needed.
|
|
21
|
+
|
|
22
|
+
Example:
|
|
23
|
+
```
|
|
24
|
+
<Viewer {...props}>
|
|
25
|
+
<FooterActionButtons>
|
|
26
|
+
<SharingButton />
|
|
27
|
+
<ForwardOrDownloadButton />
|
|
28
|
+
</FooterActionButtons>
|
|
29
|
+
</Viewer>
|
|
30
|
+
```
|
|
31
|
+
You can use a codemods `transform-viewer.js` to automatically handle this breaking change.
|
|
32
|
+
[See the codemods documentation](https://github.com/cozy/cozy-libs/tree/master/packages/cozy-codemods).
|
|
33
|
+
Using linter js auto-correction can be a good idea after that.
|
|
34
|
+
Here a common example (don't forget to change `src` value):
|
|
35
|
+
```
|
|
36
|
+
jscodeshift -t $(yarn global dir)/node_modules/@cozy/codemods/src/transforms/transform-viewer.js src --parser babel --extensions js,jsx && yarn lint:js --fix
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## [67.0.4](https://github.com/cozy/cozy-ui/compare/v67.0.3...v67.0.4) (2022-05-20)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
### Bug Fixes
|
|
43
|
+
|
|
44
|
+
* **Buttons:** Classname when using ghost variant ([c070c0c](https://github.com/cozy/cozy-ui/commit/c070c0c))
|
|
45
|
+
|
|
46
|
+
## [67.0.3](https://github.com/cozy/cozy-ui/compare/v67.0.2...v67.0.3) (2022-05-20)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
### Bug Fixes
|
|
50
|
+
|
|
51
|
+
* Action buttons at the bottom of Dialog/IllustrationDialog on mobile ([b924001](https://github.com/cozy/cozy-ui/commit/b924001))
|
|
52
|
+
|
|
1
53
|
## [67.0.2](https://github.com/cozy/cozy-ui/compare/v67.0.1...v67.0.2) (2022-05-12)
|
|
2
54
|
|
|
3
55
|
|
package/package.json
CHANGED
package/react/Buttons/index.jsx
CHANGED
|
@@ -37,12 +37,12 @@ DefaultButton.defaultProps = {
|
|
|
37
37
|
color: 'primary'
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
const Buttons = forwardRef(({ variant, ...props }, ref) => {
|
|
40
|
+
const Buttons = forwardRef(({ variant, className = '', ...props }, ref) => {
|
|
41
41
|
switch (variant) {
|
|
42
42
|
case 'ghost':
|
|
43
43
|
return (
|
|
44
44
|
<DefaultButton
|
|
45
|
-
className=
|
|
45
|
+
className={`ghost ${className}`}
|
|
46
46
|
variant="outlined"
|
|
47
47
|
{...props}
|
|
48
48
|
ref={ref}
|
|
@@ -50,16 +50,30 @@ const Buttons = forwardRef(({ variant, ...props }, ref) => {
|
|
|
50
50
|
)
|
|
51
51
|
|
|
52
52
|
case 'secondary':
|
|
53
|
-
return
|
|
53
|
+
return (
|
|
54
|
+
<DefaultButton
|
|
55
|
+
variant="outlined"
|
|
56
|
+
className={className}
|
|
57
|
+
{...props}
|
|
58
|
+
ref={ref}
|
|
59
|
+
/>
|
|
60
|
+
)
|
|
54
61
|
|
|
55
62
|
case 'text':
|
|
56
|
-
return
|
|
63
|
+
return (
|
|
64
|
+
<DefaultButton
|
|
65
|
+
variant="text"
|
|
66
|
+
className={className}
|
|
67
|
+
{...props}
|
|
68
|
+
ref={ref}
|
|
69
|
+
/>
|
|
70
|
+
)
|
|
57
71
|
|
|
58
72
|
case 'primary':
|
|
59
|
-
return <DefaultButton {...props} ref={ref} />
|
|
73
|
+
return <DefaultButton className={className} {...props} ref={ref} />
|
|
60
74
|
|
|
61
75
|
default:
|
|
62
|
-
return <DefaultButton {...props} ref={ref} />
|
|
76
|
+
return <DefaultButton className={className} {...props} ref={ref} />
|
|
63
77
|
}
|
|
64
78
|
})
|
|
65
79
|
Buttons.displayName = 'Buttons'
|
|
@@ -48,7 +48,13 @@ const ConfirmDialog = props => {
|
|
|
48
48
|
<DialogTitle {...dialogTitleProps}>{title}</DialogTitle>
|
|
49
49
|
</div>
|
|
50
50
|
)}
|
|
51
|
-
|
|
51
|
+
<div
|
|
52
|
+
className={cx('dialogContentWrapper', {
|
|
53
|
+
withActions: Boolean(actions)
|
|
54
|
+
})}
|
|
55
|
+
>
|
|
56
|
+
{content}
|
|
57
|
+
</div>
|
|
52
58
|
{actions && (
|
|
53
59
|
<DialogActions
|
|
54
60
|
{...dialogActionsProps}
|
|
@@ -50,7 +50,13 @@ const Dialog = props => {
|
|
|
50
50
|
)}
|
|
51
51
|
<DialogContent {...dialogContentProps}>
|
|
52
52
|
<div className="dialogContentInner withFluidActions">
|
|
53
|
-
|
|
53
|
+
<div
|
|
54
|
+
className={cx('dialogContentWrapper', {
|
|
55
|
+
withActions: Boolean(actions)
|
|
56
|
+
})}
|
|
57
|
+
>
|
|
58
|
+
{content}
|
|
59
|
+
</div>
|
|
54
60
|
{actions && (
|
|
55
61
|
<DialogActions
|
|
56
62
|
{...dialogActionsProps}
|
|
@@ -48,7 +48,13 @@ const IllustrationDialog = props => {
|
|
|
48
48
|
<div className="u-flex u-flex-justify-center">{title}</div>
|
|
49
49
|
</DialogTitle>
|
|
50
50
|
)}
|
|
51
|
-
|
|
51
|
+
<div
|
|
52
|
+
className={cx('dialogContentWrapper', {
|
|
53
|
+
withActions: Boolean(actions)
|
|
54
|
+
})}
|
|
55
|
+
>
|
|
56
|
+
{content}
|
|
57
|
+
</div>
|
|
52
58
|
{actions && (
|
|
53
59
|
<DialogActions
|
|
54
60
|
{...dialogActionsProps}
|
|
@@ -46,10 +46,16 @@ import {
|
|
|
46
46
|
|
|
47
47
|
import { BreakpointsProvider } from 'cozy-ui/transpiled/react/hooks/useBreakpoints'
|
|
48
48
|
|
|
49
|
-
import Button from 'cozy-ui/transpiled/react/
|
|
49
|
+
import Button from 'cozy-ui/transpiled/react/Buttons'
|
|
50
50
|
import Alerter from 'cozy-ui/transpiled/react/Alerter'
|
|
51
51
|
import Icon from 'cozy-ui/transpiled/react/Icon'
|
|
52
52
|
import Typography from 'cozy-ui/transpiled/react/Typography'
|
|
53
|
+
import Variants from 'cozy-ui/docs/components/Variants'
|
|
54
|
+
import FormControlLabel from 'cozy-ui/transpiled/react/FormControlLabel'
|
|
55
|
+
import RadioGroup from 'cozy-ui/transpiled/react/RadioGroup'
|
|
56
|
+
import Radio from 'cozy-ui/transpiled/react/Radios'
|
|
57
|
+
import FormControl from 'cozy-ui/transpiled/react/FormControl'
|
|
58
|
+
import FormLabel from 'cozy-ui/transpiled/react/FormLabel'
|
|
53
59
|
|
|
54
60
|
import CloudIcon from "cozy-ui/transpiled/react/Icons/Cloud"
|
|
55
61
|
|
|
@@ -65,12 +71,12 @@ const ExampleDialogActions = () => {
|
|
|
65
71
|
return (
|
|
66
72
|
<>
|
|
67
73
|
<Button
|
|
68
|
-
|
|
69
|
-
onClick={handleClose}
|
|
74
|
+
variant="secondary"
|
|
70
75
|
label={'Close Modal'}
|
|
76
|
+
onClick={handleClose}
|
|
71
77
|
/>
|
|
72
78
|
<Button
|
|
73
|
-
|
|
79
|
+
variant="primary"
|
|
74
80
|
label='Do something'
|
|
75
81
|
onClick={() => alert('click')}
|
|
76
82
|
/>
|
|
@@ -82,12 +88,12 @@ const ConfirmDialogActions = () => {
|
|
|
82
88
|
return (
|
|
83
89
|
<>
|
|
84
90
|
<Button
|
|
85
|
-
|
|
86
|
-
onClick={handleClose}
|
|
91
|
+
variant="secondary"
|
|
87
92
|
label={'Close Modal'}
|
|
93
|
+
onClick={handleClose}
|
|
88
94
|
/>
|
|
89
95
|
<Button
|
|
90
|
-
|
|
96
|
+
color="error"
|
|
91
97
|
label='Do something destructive'
|
|
92
98
|
onClick={() => alert('click')}
|
|
93
99
|
/>
|
|
@@ -148,105 +154,122 @@ initialState = {
|
|
|
148
154
|
modalOpened: isTesting(),
|
|
149
155
|
modal: Dialog,
|
|
150
156
|
size: 'medium',
|
|
151
|
-
|
|
152
|
-
|
|
157
|
+
content: 'default',
|
|
158
|
+
theme: 'normal',
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const initialVariants = [{
|
|
162
|
+
actionsLayoutColumn: false,
|
|
163
|
+
titleLong: false,
|
|
153
164
|
disableTitleAutoPadding: false,
|
|
154
165
|
withCloseButton: true,
|
|
155
166
|
withBackButton: false,
|
|
156
|
-
|
|
157
|
-
theme: 'normal',
|
|
158
|
-
align: 'middle',
|
|
167
|
+
alignTop: false,
|
|
159
168
|
showActions: true,
|
|
160
169
|
disableGutters: false,
|
|
161
170
|
hideTitle: false
|
|
162
|
-
}
|
|
171
|
+
}]
|
|
163
172
|
|
|
164
173
|
;
|
|
165
174
|
|
|
166
|
-
|
|
167
|
-
<
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
175
|
+
<BreakpointsProvider>
|
|
176
|
+
<Variants initialVariants={initialVariants}>
|
|
177
|
+
{variant => (
|
|
178
|
+
<>
|
|
179
|
+
<FormControl component="fieldset" fullWidth>
|
|
180
|
+
<FormLabel component="legend">Content</FormLabel>
|
|
181
|
+
<RadioGroup
|
|
182
|
+
aria-label="radio"
|
|
183
|
+
name="content"
|
|
184
|
+
row
|
|
185
|
+
value={state.content}
|
|
186
|
+
onChange={event => { setState({ content: event.target.value }) }}
|
|
187
|
+
>
|
|
188
|
+
<FormControlLabel
|
|
189
|
+
value="default"
|
|
190
|
+
label="Default"
|
|
191
|
+
control={<Radio />}
|
|
192
|
+
/>
|
|
193
|
+
<FormControlLabel
|
|
194
|
+
value="short"
|
|
195
|
+
label="Short"
|
|
196
|
+
control={<Radio />}
|
|
197
|
+
/>
|
|
198
|
+
<FormControlLabel
|
|
199
|
+
value="long"
|
|
200
|
+
label="Long"
|
|
201
|
+
control={<Radio />}
|
|
202
|
+
/>
|
|
203
|
+
</RadioGroup>
|
|
204
|
+
</FormControl>
|
|
205
|
+
<FormControl component="fieldset" >
|
|
206
|
+
<FormLabel component="legend">Size</FormLabel>
|
|
207
|
+
<RadioGroup
|
|
208
|
+
aria-label="radio"
|
|
209
|
+
name="size"
|
|
210
|
+
row
|
|
211
|
+
value={state.size}
|
|
212
|
+
onChange={event => { setState({ size: event.target.value }) }}
|
|
213
|
+
>
|
|
214
|
+
<FormControlLabel
|
|
215
|
+
value="small"
|
|
216
|
+
label="Small"
|
|
217
|
+
control={<Radio />}
|
|
218
|
+
/>
|
|
219
|
+
<FormControlLabel
|
|
220
|
+
value="medium"
|
|
221
|
+
label="Medium"
|
|
222
|
+
control={<Radio />}
|
|
223
|
+
/>
|
|
224
|
+
<FormControlLabel
|
|
225
|
+
value="large"
|
|
226
|
+
label="Large"
|
|
227
|
+
control={<Radio />}
|
|
228
|
+
/>
|
|
229
|
+
</RadioGroup>
|
|
230
|
+
</FormControl>
|
|
231
|
+
<div className="u-mt-1">
|
|
232
|
+
{dialogs.map(dialog => (
|
|
233
|
+
<Button
|
|
234
|
+
key={`open-btn-${dialog.name}`}
|
|
235
|
+
data-testid={`open-btn-${dialog.name}`}
|
|
236
|
+
className="u-m-half"
|
|
237
|
+
label={`Open ${dialog.name}`}
|
|
238
|
+
variant="ghost"
|
|
239
|
+
size="small"
|
|
240
|
+
onClick={() => toggleDialog(dialog)}
|
|
241
|
+
/>
|
|
242
|
+
))}
|
|
243
|
+
</div>
|
|
244
|
+
|
|
245
|
+
<DialogComponent
|
|
246
|
+
size={DialogComponent !== ConfirmDialog ? state.size : undefined}
|
|
247
|
+
open={state.modalOpened}
|
|
248
|
+
onClose={variant.withCloseButton ? handleClose : undefined}
|
|
249
|
+
onBack={variant.withBackButton ? handleBack : undefined}
|
|
250
|
+
disableTitleAutoPadding={variant.disableTitleAutoPadding}
|
|
251
|
+
align={variant.alignTop ? 'top': 'middle'}
|
|
252
|
+
title={variant.hideTitle
|
|
253
|
+
? undefined
|
|
254
|
+
: DialogComponent !== IllustrationDialog && variant.titleLong
|
|
255
|
+
? `${dialogTitles[DialogComponent.name]} - ${content.ada.short}`
|
|
256
|
+
: dialogTitles[DialogComponent.name]
|
|
257
|
+
}
|
|
258
|
+
disableGutters={variant.disableGutters}
|
|
259
|
+
content={
|
|
260
|
+
<Typography variant='body1' color='textPrimary'>
|
|
261
|
+
{ state.content == 'default'
|
|
262
|
+
? dialogContents[DialogComponent.name]
|
|
263
|
+
: state.content == 'long'
|
|
264
|
+
? content.ada.long
|
|
265
|
+
: content.ada.short}<br/>
|
|
266
|
+
<Button className='u-mt-1 u-ml-0' label="Show an alert" onClick={() => Alerter.success('Hello', { duration: 100000 })}/>
|
|
267
|
+
</Typography>}
|
|
268
|
+
actions={variant.showActions && dialogActions[DialogComponent.name]}
|
|
269
|
+
actionsLayout={variant.actionsLayoutColumn ? 'column' : 'row'}
|
|
270
|
+
/>
|
|
271
|
+
</>
|
|
272
|
+
)}
|
|
273
|
+
</Variants>
|
|
274
|
+
</BreakpointsProvider>
|
|
252
275
|
```
|
|
@@ -577,7 +577,19 @@ const makeOverrides = theme => ({
|
|
|
577
577
|
marginBottom: '24px',
|
|
578
578
|
'&.withFluidActions': {
|
|
579
579
|
[theme.breakpoints.down('sm')]: {
|
|
580
|
-
marginBottom:
|
|
580
|
+
marginBottom: 0,
|
|
581
|
+
display: 'flex',
|
|
582
|
+
flexDirection: 'column',
|
|
583
|
+
height: '100%',
|
|
584
|
+
'& .dialogContentWrapper': {
|
|
585
|
+
flexGrow: 1,
|
|
586
|
+
'&:not(.withActions)': {
|
|
587
|
+
paddingBottom: '16px'
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
'& .cozyDialogActions': {
|
|
591
|
+
paddingBottom: '16px'
|
|
592
|
+
}
|
|
581
593
|
}
|
|
582
594
|
},
|
|
583
595
|
'& .dialogTitleFluidContainer': {
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { cloneElement } from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
|
|
4
|
+
import { mapToAllChildren } from './helpers'
|
|
5
|
+
|
|
6
|
+
const FooterActionButtons = ({ children, file }) => {
|
|
7
|
+
if (!children) return null
|
|
8
|
+
|
|
9
|
+
return mapToAllChildren(children, child => cloneElement(child, { file }))
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
FooterActionButtons.propTypes = {
|
|
13
|
+
children: PropTypes.oneOfType([
|
|
14
|
+
PropTypes.node,
|
|
15
|
+
PropTypes.arrayOf(PropTypes.node)
|
|
16
|
+
]),
|
|
17
|
+
file: PropTypes.object
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default FooterActionButtons
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { render } from '@testing-library/react'
|
|
3
|
+
|
|
4
|
+
import FooterActionButtons from './FooterActionButtons'
|
|
5
|
+
|
|
6
|
+
describe('FooterActionButtons', () => {
|
|
7
|
+
it('should not return children', () => {
|
|
8
|
+
const { container } = render(<FooterActionButtons />)
|
|
9
|
+
|
|
10
|
+
expect(container).toMatchInlineSnapshot('<div />')
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('should render all childrens', () => {
|
|
14
|
+
const { getByText } = render(
|
|
15
|
+
<FooterActionButtons>
|
|
16
|
+
<div>
|
|
17
|
+
<p>First child</p>
|
|
18
|
+
<div>
|
|
19
|
+
<p>Sub first children</p>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
<div>Second child</div>
|
|
23
|
+
</FooterActionButtons>
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
expect(getByText('First child'))
|
|
27
|
+
expect(getByText('Sub first children'))
|
|
28
|
+
expect(getByText('Second child'))
|
|
29
|
+
})
|
|
30
|
+
})
|
|
@@ -1,22 +1,12 @@
|
|
|
1
|
-
import React, { useMemo } from 'react'
|
|
1
|
+
import React, { useMemo, Children, cloneElement } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import { makeStyles } from '@material-ui/core/styles'
|
|
4
4
|
|
|
5
|
-
import { getReferencedBy, useQuery, models, useClient } from 'cozy-client'
|
|
6
|
-
|
|
7
5
|
import BottomSheet, { BottomSheetHeader } from '../../BottomSheet'
|
|
8
6
|
|
|
9
|
-
import { buildContactByIdsQuery } from '../queries'
|
|
10
7
|
import { isValidForPanel } from '../helpers'
|
|
11
|
-
import Sharing from './Sharing'
|
|
12
|
-
import ForwardButton from './ForwardButton'
|
|
13
|
-
import DownloadButton from './DownloadButton'
|
|
14
8
|
import BottomSheetContent from './BottomSheetContent'
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
const {
|
|
18
|
-
contact: { getDisplayName }
|
|
19
|
-
} = models
|
|
9
|
+
import useReferencedContactName from './useReferencedContactName'
|
|
20
10
|
|
|
21
11
|
const useStyles = makeStyles(theme => ({
|
|
22
12
|
footer: {
|
|
@@ -30,54 +20,49 @@ const useStyles = makeStyles(theme => ({
|
|
|
30
20
|
}
|
|
31
21
|
}))
|
|
32
22
|
|
|
33
|
-
const FooterContent = ({ file, toolbarRef,
|
|
23
|
+
const FooterContent = ({ file, toolbarRef, children }) => {
|
|
34
24
|
const styles = useStyles()
|
|
35
|
-
|
|
36
|
-
const FileActionButton = shouldBeForwardButton(client)
|
|
37
|
-
? ForwardButton
|
|
38
|
-
: DownloadButton
|
|
25
|
+
|
|
39
26
|
const toolbarProps = useMemo(() => ({ ref: toolbarRef }), [toolbarRef])
|
|
40
27
|
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
28
|
+
const { contactName, isLoadingContacts } = useReferencedContactName(file)
|
|
29
|
+
|
|
30
|
+
const FooterActionButtons = Children.toArray(children).find(child => {
|
|
31
|
+
return (
|
|
32
|
+
child.type.name === 'FooterActionButtons' ||
|
|
33
|
+
child.type.displayName === 'FooterActionButtons'
|
|
34
|
+
)
|
|
48
35
|
})
|
|
49
36
|
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
37
|
+
const FooterActionButtonsWithFile = cloneElement(FooterActionButtons, {
|
|
38
|
+
file
|
|
39
|
+
})
|
|
53
40
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
(contactsFullname || contactIds.length === 0)
|
|
57
|
-
) {
|
|
41
|
+
// We have to wait for the Contact request to finish before rendering `BottomSheet`, because it doesn't handle async well.
|
|
42
|
+
if (isValidForPanel({ file }) && !isLoadingContacts) {
|
|
58
43
|
return (
|
|
59
44
|
<BottomSheet toolbarProps={toolbarProps}>
|
|
60
45
|
<BottomSheetHeader className="u-ph-1 u-pb-1">
|
|
61
|
-
{
|
|
62
|
-
<FileActionButton file={file} />
|
|
46
|
+
{FooterActionButtonsWithFile}
|
|
63
47
|
</BottomSheetHeader>
|
|
64
|
-
<BottomSheetContent file={file} contactsFullname={
|
|
48
|
+
<BottomSheetContent file={file} contactsFullname={contactName} />
|
|
65
49
|
</BottomSheet>
|
|
66
50
|
)
|
|
67
51
|
}
|
|
68
52
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
</div>
|
|
74
|
-
)
|
|
53
|
+
// If `FooterActionButtons` hasn't children
|
|
54
|
+
if (!FooterActionButtons) return null
|
|
55
|
+
|
|
56
|
+
return <div className={styles.footer}>{FooterActionButtonsWithFile}</div>
|
|
75
57
|
}
|
|
76
58
|
|
|
77
59
|
FooterContent.propTypes = {
|
|
78
60
|
file: PropTypes.object.isRequired,
|
|
79
61
|
toolbarRef: PropTypes.object,
|
|
80
|
-
|
|
62
|
+
children: PropTypes.oneOfType([
|
|
63
|
+
PropTypes.node,
|
|
64
|
+
PropTypes.arrayOf(PropTypes.node)
|
|
65
|
+
])
|
|
81
66
|
}
|
|
82
67
|
|
|
83
68
|
export default FooterContent
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
|
|
4
|
+
import { useClient } from 'cozy-client'
|
|
5
|
+
|
|
6
|
+
import ForwardButton from './ForwardButton'
|
|
7
|
+
import DownloadButton from './DownloadButton'
|
|
8
|
+
import { shouldBeForwardButton } from './helpers'
|
|
9
|
+
|
|
10
|
+
const ForwardOrDownloadButton = ({ file }) => {
|
|
11
|
+
const client = useClient()
|
|
12
|
+
|
|
13
|
+
const FileActionButton = shouldBeForwardButton(client)
|
|
14
|
+
? ForwardButton
|
|
15
|
+
: DownloadButton
|
|
16
|
+
|
|
17
|
+
return <FileActionButton file={file} />
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
ForwardOrDownloadButton.propTypes = {
|
|
21
|
+
file: PropTypes.object
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default ForwardOrDownloadButton
|