cozy-sharing 32.1.1 → 32.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +27 -0
- package/.storybook/main.js +8 -1
- package/.storybook/preview.jsx +11 -6
- package/AGENTS.md +7 -0
- package/CHANGELOG.md +22 -0
- package/dist/RefreshableSharings.spec.js +40 -0
- package/dist/assets/illustrations/illustration-shared-drives.svg +1 -0
- package/dist/components/EditLinkPermissionDialog.js +72 -0
- package/dist/components/EditLinkPermissionDialog.spec.js +48 -0
- package/dist/components/FederatedFolder/DumbFederatedFolderModal.js +65 -0
- package/dist/components/FederatedFolder/DumbFederatedFolderModal.spec.js +107 -0
- package/dist/components/FederatedFolder/FederatedFolderModal.js +41 -4
- package/dist/components/FederatedFolder/FederatedFolderModal.jsx.tmp.179197.1773939270471 +172 -0
- package/dist/components/FederatedFolder/FederatedFolderModal.spec.js +79 -8
- package/dist/components/Recipient/LinkRecipient.stories.js +3 -0
- package/dist/components/Recipient/LinkRecipientPermissions.stories.js +5 -1
- package/dist/components/Recipient/actions/revokeGroup.js +42 -0
- package/dist/components/Recipient/actions/revokeMember.js +42 -0
- package/dist/components/Recipient/actions/revokeSharedDriveMember.js +41 -0
- package/dist/components/ShareAutosuggest.js +1 -0
- package/dist/components/ShareAutosuggest.spec.js +12 -4
- package/dist/components/ShareDialogCozyToCozy.spec.js +55 -8
- package/dist/components/ShareDiscardChangesModal.js +35 -0
- package/dist/components/ShareModal/ShareModal copy.js +43 -0
- package/dist/components/ShareModal/ShareModal.spec.js +197 -0
- package/dist/components/ShareModal/ShareModalBatchContainer.js +276 -0
- package/dist/components/ShareModal/ShareModalBatchContainer.spec.js +131 -0
- package/dist/components/ShareModal/SharedDriveEditModal.js +59 -0
- package/dist/components/ShareRecipientsInput.js +13 -3
- package/dist/components/ShareRecipientsInput.spec.js +63 -4
- package/dist/components/SharedDrive/DumbSharedDriveModal.js +78 -0
- package/dist/components/SharedDrive/DumbSharedDriveModal.spec.js +126 -0
- package/dist/components/SharedDrive/SharedDriveEditModal.js +110 -0
- package/dist/components/SharedDrive/SharedDriveModal copy.js +356 -0
- package/dist/components/SharedDrive/helpers.js +102 -0
- package/dist/components/SharedDrive/helpers.spec.js +208 -0
- package/dist/components/SharedDriveEditModal.js +43 -0
- package/dist/components/SharedFolder/DumbBatchSharedFolderModal.spec.js +321 -0
- package/dist/components/SharedStatus.js +61 -0
- package/dist/components/SharedStatus.spec.js +44 -0
- package/dist/components/Sharesubmit.js +28 -0
- package/dist/components/__snapshots__/SharedStatus.spec.js.snap +94 -0
- package/dist/helpers/owner.js +14 -0
- package/dist/helpers/owner.spec.js +34 -0
- package/dist/hooks/useConfirmDiscardChanges.js +33 -0
- package/dist/hooks/useContactsAndGroups.js +65 -0
- package/dist/hooks/useSharedDrive.js +130 -0
- package/dist/hooks/useSharedDriveContactsAndGroups.js +65 -0
- package/dist/propTypes.js +26 -0
- package/dist/styles/shareddrive.styl +8 -0
- package/locales/en.json +10 -5
- package/locales/fr.json +10 -5
- package/locales/ru.json +10 -5
- package/locales/vi.json +10 -5
- package/package.json +2 -2
- package/src/components/FederatedFolder/FederatedFolderModal.jsx +184 -138
- package/src/components/FederatedFolder/FederatedFolderModal.spec.jsx +47 -0
- package/src/components/Recipient/LinkRecipient.stories.jsx +1 -0
- package/src/components/Recipient/LinkRecipientPermissions.stories.jsx +3 -1
- package/src/components/ShareAutosuggest.jsx +1 -0
- package/src/components/ShareAutosuggest.spec.jsx +10 -5
- package/src/components/ShareDialogCozyToCozy.spec.jsx +50 -4
- package/src/components/ShareDiscardChangesModal.jsx +40 -0
- package/src/components/ShareRecipientsInput.jsx +11 -6
- package/src/components/ShareRecipientsInput.spec.jsx +59 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import PropTypes from 'prop-types'
|
|
2
|
+
import React, { useState, useEffect } from 'react'
|
|
3
|
+
|
|
4
|
+
import { useClient } from 'cozy-client'
|
|
5
|
+
import { useAlert } from 'cozy-ui/transpiled/react/providers/Alert'
|
|
6
|
+
import { useI18n } from 'twake-i18n'
|
|
7
|
+
|
|
8
|
+
import { DumbFederatedFolderModal } from './DumbFederatedFolderModal'
|
|
9
|
+
import withLocales from '../../hoc/withLocales'
|
|
10
|
+
import { useSharingContext } from '../../hooks/useSharingContext'
|
|
11
|
+
import {
|
|
12
|
+
formatRecipients,
|
|
13
|
+
mergeAndDeduplicateRecipients,
|
|
14
|
+
moveRecipientToReadWrite,
|
|
15
|
+
moveRecipientToReadOnly,
|
|
16
|
+
RECIPIENT_INDEX_PREFIX
|
|
17
|
+
} from '../SharedDrive/helpers'
|
|
18
|
+
|
|
19
|
+
export const FederatedFolderModal = withLocales(
|
|
20
|
+
({ onClose, document: existingDocument }) => {
|
|
21
|
+
const client = useClient()
|
|
22
|
+
const { t } = useI18n()
|
|
23
|
+
const {
|
|
24
|
+
share,
|
|
25
|
+
getSharingLink,
|
|
26
|
+
getFederatedShareLink,
|
|
27
|
+
getDocumentPermissions,
|
|
28
|
+
getOwner,
|
|
29
|
+
getSharingById,
|
|
30
|
+
getRecipients,
|
|
31
|
+
revoke
|
|
32
|
+
} = useSharingContext()
|
|
33
|
+
const { showAlert } = useAlert()
|
|
34
|
+
|
|
35
|
+
const [sharingLink, setSharingLink] = useState(null)
|
|
36
|
+
|
|
37
|
+
const documentPermissions = existingDocument
|
|
38
|
+
? getDocumentPermissions(existingDocument._id)
|
|
39
|
+
: []
|
|
40
|
+
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
const fetchSharingLink = async () => {
|
|
43
|
+
if (!existingDocument) return
|
|
44
|
+
|
|
45
|
+
if (existingDocument.driveId) {
|
|
46
|
+
const link = await getFederatedShareLink(existingDocument)
|
|
47
|
+
setSharingLink(link)
|
|
48
|
+
} else {
|
|
49
|
+
setSharingLink(getSharingLink(existingDocument._id))
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
fetchSharingLink()
|
|
54
|
+
}, [
|
|
55
|
+
existingDocument,
|
|
56
|
+
documentPermissions,
|
|
57
|
+
getFederatedShareLink,
|
|
58
|
+
getSharingLink,
|
|
59
|
+
getOwner,
|
|
60
|
+
getSharingById
|
|
61
|
+
])
|
|
62
|
+
|
|
63
|
+
const [federatedRecipients, setFederatedRecipients] = useState({
|
|
64
|
+
recipients: [],
|
|
65
|
+
readOnlyRecipients: []
|
|
66
|
+
})
|
|
67
|
+
const [folderName] = useState(existingDocument?.name || '')
|
|
68
|
+
|
|
69
|
+
const onShare = params => {
|
|
70
|
+
setFederatedRecipients(prev => ({
|
|
71
|
+
recipients: mergeAndDeduplicateRecipients([
|
|
72
|
+
prev.recipients,
|
|
73
|
+
params.recipients || []
|
|
74
|
+
]),
|
|
75
|
+
readOnlyRecipients: mergeAndDeduplicateRecipients([
|
|
76
|
+
prev.readOnlyRecipients,
|
|
77
|
+
params.readOnlyRecipients || []
|
|
78
|
+
])
|
|
79
|
+
}))
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const onSend = async () => {
|
|
83
|
+
try {
|
|
84
|
+
await share({
|
|
85
|
+
description: folderName,
|
|
86
|
+
document: existingDocument,
|
|
87
|
+
recipients: federatedRecipients.recipients,
|
|
88
|
+
readOnlyRecipients: federatedRecipients.readOnlyRecipients,
|
|
89
|
+
sharedDrive: true,
|
|
90
|
+
openSharing: false
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
showAlert({
|
|
94
|
+
message: t('FederatedFolder.successNotification'),
|
|
95
|
+
severity: 'success',
|
|
96
|
+
variant: 'filled'
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
onClose()
|
|
100
|
+
} catch (_err) {
|
|
101
|
+
showAlert({
|
|
102
|
+
message: t('FederatedFolder.errorNotification'),
|
|
103
|
+
severity: 'error',
|
|
104
|
+
variant: 'filled'
|
|
105
|
+
})
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const onSetType = (index, newType) => {
|
|
110
|
+
const _id = index.split(RECIPIENT_INDEX_PREFIX)[1]
|
|
111
|
+
|
|
112
|
+
if (newType === 'two-way') {
|
|
113
|
+
setFederatedRecipients(prev => moveRecipientToReadWrite(prev, _id))
|
|
114
|
+
} else {
|
|
115
|
+
setFederatedRecipients(prev => moveRecipientToReadOnly(prev, _id))
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const onRevoke = async (documentOrIndex, sharingId, memberIndex) => {
|
|
120
|
+
if (
|
|
121
|
+
typeof documentOrIndex === 'string' &&
|
|
122
|
+
documentOrIndex.startsWith(RECIPIENT_INDEX_PREFIX)
|
|
123
|
+
) {
|
|
124
|
+
const _id = documentOrIndex.split(RECIPIENT_INDEX_PREFIX)[1]
|
|
125
|
+
setFederatedRecipients(prev => ({
|
|
126
|
+
recipients: prev.recipients.filter(r => r._id !== _id),
|
|
127
|
+
readOnlyRecipients: prev.readOnlyRecipients.filter(r => r._id !== _id)
|
|
128
|
+
}))
|
|
129
|
+
} else {
|
|
130
|
+
await revoke(documentOrIndex, sharingId, memberIndex)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const existingRecipients = existingDocument
|
|
135
|
+
? getRecipients(existingDocument._id)
|
|
136
|
+
: []
|
|
137
|
+
|
|
138
|
+
const recipients = [
|
|
139
|
+
...existingRecipients,
|
|
140
|
+
...formatRecipients(federatedRecipients)
|
|
141
|
+
]
|
|
142
|
+
|
|
143
|
+
const modalTitle = t('FederatedFolder.shareTitle', { name: folderName })
|
|
144
|
+
|
|
145
|
+
const isSharedDrive = Boolean(existingDocument?.driveId)
|
|
146
|
+
|
|
147
|
+
return (
|
|
148
|
+
<DumbFederatedFolderModal
|
|
149
|
+
title={modalTitle}
|
|
150
|
+
document={existingDocument}
|
|
151
|
+
createContact={contact => client.create('io.cozy.contacts', contact)}
|
|
152
|
+
recipients={recipients}
|
|
153
|
+
readOnlyRecipients={federatedRecipients.readOnlyRecipients}
|
|
154
|
+
currentRecipients={existingRecipients}
|
|
155
|
+
onRevoke={onRevoke}
|
|
156
|
+
onSetType={onSetType}
|
|
157
|
+
onSend={onSend}
|
|
158
|
+
onClose={onClose}
|
|
159
|
+
onShare={onShare}
|
|
160
|
+
sharingLink={sharingLink}
|
|
161
|
+
showShareByEmail={!isSharedDrive}
|
|
162
|
+
/>
|
|
163
|
+
)
|
|
164
|
+
}
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
FederatedFolderModal.propTypes = {
|
|
168
|
+
onClose: PropTypes.func.isRequired,
|
|
169
|
+
document: PropTypes.object.isRequired
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export default FederatedFolderModal
|
|
@@ -462,6 +462,77 @@ describe('FederatedFolderModal', function () {
|
|
|
462
462
|
}
|
|
463
463
|
}, _callee11);
|
|
464
464
|
})));
|
|
465
|
+
it('should ask confirmation when close button is clicked with pending recipients', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee12() {
|
|
466
|
+
var _setup12, getByRole, getByTestId, getByText;
|
|
467
|
+
|
|
468
|
+
return _regeneratorRuntime.wrap(function _callee12$(_context12) {
|
|
469
|
+
while (1) switch (_context12.prev = _context12.next) {
|
|
470
|
+
case 0:
|
|
471
|
+
usePendingRecipients.mockReturnValue({
|
|
472
|
+
pendingRecipients: [{
|
|
473
|
+
name: 'Alice',
|
|
474
|
+
email: 'alice@example.com'
|
|
475
|
+
}],
|
|
476
|
+
setPendingRecipients: jest.fn(),
|
|
477
|
+
selectedOption: 'readWrite',
|
|
478
|
+
setSelectedOption: jest.fn()
|
|
479
|
+
});
|
|
480
|
+
_setup12 = setup(), getByRole = _setup12.getByRole, getByTestId = _setup12.getByTestId, getByText = _setup12.getByText;
|
|
481
|
+
_context12.next = 4;
|
|
482
|
+
return waitFor(function () {
|
|
483
|
+
expect(getByTestId('btn-close')).toBeTruthy();
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
case 4:
|
|
487
|
+
fireEvent.click(getByTestId('btn-close'));
|
|
488
|
+
expect(getByText("Discard the changes you haven't saved?")).toBeTruthy();
|
|
489
|
+
expect(mockOnClose).not.toHaveBeenCalled();
|
|
490
|
+
fireEvent.click(getByRole('button', {
|
|
491
|
+
name: 'Cancel'
|
|
492
|
+
}));
|
|
493
|
+
expect(mockOnClose).not.toHaveBeenCalled();
|
|
494
|
+
|
|
495
|
+
case 9:
|
|
496
|
+
case "end":
|
|
497
|
+
return _context12.stop();
|
|
498
|
+
}
|
|
499
|
+
}, _callee12);
|
|
500
|
+
})));
|
|
501
|
+
it('should close after discard confirmation', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee13() {
|
|
502
|
+
var _setup13, getByRole, getByTestId, getByText;
|
|
503
|
+
|
|
504
|
+
return _regeneratorRuntime.wrap(function _callee13$(_context13) {
|
|
505
|
+
while (1) switch (_context13.prev = _context13.next) {
|
|
506
|
+
case 0:
|
|
507
|
+
usePendingRecipients.mockReturnValue({
|
|
508
|
+
pendingRecipients: [{
|
|
509
|
+
name: 'Alice',
|
|
510
|
+
email: 'alice@example.com'
|
|
511
|
+
}],
|
|
512
|
+
setPendingRecipients: jest.fn(),
|
|
513
|
+
selectedOption: 'readWrite',
|
|
514
|
+
setSelectedOption: jest.fn()
|
|
515
|
+
});
|
|
516
|
+
_setup13 = setup(), getByRole = _setup13.getByRole, getByTestId = _setup13.getByTestId, getByText = _setup13.getByText;
|
|
517
|
+
_context13.next = 4;
|
|
518
|
+
return waitFor(function () {
|
|
519
|
+
expect(getByTestId('btn-close')).toBeTruthy();
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
case 4:
|
|
523
|
+
fireEvent.click(getByTestId('btn-close'));
|
|
524
|
+
expect(getByText("Discard the changes you haven't saved?")).toBeTruthy();
|
|
525
|
+
fireEvent.click(getByRole('button', {
|
|
526
|
+
name: 'Discard'
|
|
527
|
+
}));
|
|
528
|
+
expect(mockOnClose).toHaveBeenCalledTimes(1);
|
|
529
|
+
|
|
530
|
+
case 8:
|
|
531
|
+
case "end":
|
|
532
|
+
return _context13.stop();
|
|
533
|
+
}
|
|
534
|
+
}, _callee13);
|
|
535
|
+
})));
|
|
465
536
|
});
|
|
466
537
|
describe('existing recipients', function () {
|
|
467
538
|
var existingRecipients = [{
|
|
@@ -481,24 +552,24 @@ describe('FederatedFolderModal', function () {
|
|
|
481
552
|
sharingId: 'abc',
|
|
482
553
|
memberIndex: 1
|
|
483
554
|
}];
|
|
484
|
-
it('should display existing recipients from getRecipients', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function
|
|
485
|
-
var
|
|
555
|
+
it('should display existing recipients from getRecipients', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee14() {
|
|
556
|
+
var _setup14, getByTestId;
|
|
486
557
|
|
|
487
|
-
return _regeneratorRuntime.wrap(function
|
|
488
|
-
while (1) switch (
|
|
558
|
+
return _regeneratorRuntime.wrap(function _callee14$(_context14) {
|
|
559
|
+
while (1) switch (_context14.prev = _context14.next) {
|
|
489
560
|
case 0:
|
|
490
561
|
mockGetRecipients.mockReturnValue(existingRecipients);
|
|
491
|
-
|
|
492
|
-
|
|
562
|
+
_setup14 = setup(), getByTestId = _setup14.getByTestId;
|
|
563
|
+
_context14.next = 4;
|
|
493
564
|
return waitFor(function () {
|
|
494
565
|
expect(getByTestId('recipients-count').textContent).toBe('2');
|
|
495
566
|
});
|
|
496
567
|
|
|
497
568
|
case 4:
|
|
498
569
|
case "end":
|
|
499
|
-
return
|
|
570
|
+
return _context14.stop();
|
|
500
571
|
}
|
|
501
|
-
},
|
|
572
|
+
}, _callee14);
|
|
502
573
|
})));
|
|
503
574
|
});
|
|
504
575
|
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import React, { forwardRef } from 'react';
|
|
3
|
+
import ActionsMenuItem from 'cozy-ui/transpiled/react/ActionsMenu/ActionsMenuItem';
|
|
4
|
+
import Icon from 'cozy-ui/transpiled/react/Icon';
|
|
5
|
+
import ForbiddenIcon from 'cozy-ui/transpiled/react/Icons/Forbidden';
|
|
6
|
+
import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon';
|
|
7
|
+
import ListItemText from 'cozy-ui/transpiled/react/ListItemText';
|
|
8
|
+
import Typography from 'cozy-ui/transpiled/react/Typography';
|
|
9
|
+
|
|
10
|
+
var revokeGroup = function revokeGroup(_ref) {
|
|
11
|
+
var t = _ref.t,
|
|
12
|
+
isOwner = _ref.isOwner,
|
|
13
|
+
isSharedDrive = _ref.isSharedDrive,
|
|
14
|
+
handleRevocation = _ref.handleRevocation;
|
|
15
|
+
var revokeType = isOwner ? 'revoke' : 'revokeSelf';
|
|
16
|
+
var title = t("RevokeGroupItem.".concat(revokeType, ".title"));
|
|
17
|
+
var desc = isOwner && isSharedDrive ? t("RevokeGroupItem.revoke.sharedDriveDesc") : t("RevokeGroupItem.".concat(revokeType, ".desc"));
|
|
18
|
+
var icon = ForbiddenIcon;
|
|
19
|
+
return {
|
|
20
|
+
name: 'revokeMember',
|
|
21
|
+
label: title,
|
|
22
|
+
icon: icon,
|
|
23
|
+
action: function action() {
|
|
24
|
+
handleRevocation();
|
|
25
|
+
},
|
|
26
|
+
Component: /*#__PURE__*/forwardRef(function RevokeMemberItem(props, ref) {
|
|
27
|
+
return /*#__PURE__*/React.createElement(ActionsMenuItem, _extends({}, props, {
|
|
28
|
+
ref: ref
|
|
29
|
+
}), /*#__PURE__*/React.createElement(ListItemIcon, null, /*#__PURE__*/React.createElement(Icon, {
|
|
30
|
+
icon: icon,
|
|
31
|
+
color: "var(--errorColor)"
|
|
32
|
+
})), /*#__PURE__*/React.createElement(ListItemText, {
|
|
33
|
+
primary: /*#__PURE__*/React.createElement(Typography, {
|
|
34
|
+
color: "error"
|
|
35
|
+
}, title),
|
|
36
|
+
secondary: desc
|
|
37
|
+
}));
|
|
38
|
+
})
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export { revokeGroup };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import React, { forwardRef } from 'react';
|
|
3
|
+
import ActionsMenuItem from 'cozy-ui/transpiled/react/ActionsMenu/ActionsMenuItem';
|
|
4
|
+
import Icon from 'cozy-ui/transpiled/react/Icon';
|
|
5
|
+
import TrashIcon from 'cozy-ui/transpiled/react/Icons/Trash';
|
|
6
|
+
import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon';
|
|
7
|
+
import ListItemText from 'cozy-ui/transpiled/react/ListItemText';
|
|
8
|
+
import Typography from 'cozy-ui/transpiled/react/Typography';
|
|
9
|
+
|
|
10
|
+
var revokeMember = function revokeMember(_ref) {
|
|
11
|
+
var t = _ref.t,
|
|
12
|
+
isOwner = _ref.isOwner,
|
|
13
|
+
isSharedDrive = _ref.isSharedDrive,
|
|
14
|
+
handleRevocation = _ref.handleRevocation;
|
|
15
|
+
var revokeType = isOwner ? 'revoke' : 'revokeSelf';
|
|
16
|
+
var title = t("RevokeMemberItem.".concat(revokeType, ".title"));
|
|
17
|
+
var desc = isOwner && isSharedDrive ? t("RevokeMemberItem.revoke.sharedDriveDesc") : t("RevokeMemberItem.".concat(revokeType, ".desc"));
|
|
18
|
+
var icon = TrashIcon;
|
|
19
|
+
return {
|
|
20
|
+
name: 'revokeMember',
|
|
21
|
+
label: title,
|
|
22
|
+
icon: icon,
|
|
23
|
+
action: function action() {
|
|
24
|
+
handleRevocation();
|
|
25
|
+
},
|
|
26
|
+
Component: /*#__PURE__*/forwardRef(function RevokeMemberItem(props, ref) {
|
|
27
|
+
return /*#__PURE__*/React.createElement(ActionsMenuItem, _extends({}, props, {
|
|
28
|
+
ref: ref
|
|
29
|
+
}), /*#__PURE__*/React.createElement(ListItemIcon, null, /*#__PURE__*/React.createElement(Icon, {
|
|
30
|
+
icon: icon,
|
|
31
|
+
color: "var(--errorColor)"
|
|
32
|
+
})), /*#__PURE__*/React.createElement(ListItemText, {
|
|
33
|
+
primary: /*#__PURE__*/React.createElement(Typography, {
|
|
34
|
+
color: "error"
|
|
35
|
+
}, title),
|
|
36
|
+
secondary: desc
|
|
37
|
+
}));
|
|
38
|
+
})
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export { revokeMember };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import React, { forwardRef } from 'react';
|
|
3
|
+
import ActionsMenuItem from 'cozy-ui/transpiled/react/ActionsMenu/ActionsMenuItem';
|
|
4
|
+
import Icon from 'cozy-ui/transpiled/react/Icon';
|
|
5
|
+
import TrashIcon from 'cozy-ui/transpiled/react/Icons/Trash';
|
|
6
|
+
import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon';
|
|
7
|
+
import ListItemText from 'cozy-ui/transpiled/react/ListItemText';
|
|
8
|
+
import Typography from 'cozy-ui/transpiled/react/Typography';
|
|
9
|
+
|
|
10
|
+
var makeComponent = function makeComponent(title) {
|
|
11
|
+
var Component = /*#__PURE__*/forwardRef(function (props, ref) {
|
|
12
|
+
return /*#__PURE__*/React.createElement(ActionsMenuItem, _extends({}, props, {
|
|
13
|
+
ref: ref
|
|
14
|
+
}), /*#__PURE__*/React.createElement(ListItemIcon, null, /*#__PURE__*/React.createElement(Icon, {
|
|
15
|
+
icon: TrashIcon,
|
|
16
|
+
color: "var(--errorColor)"
|
|
17
|
+
})), /*#__PURE__*/React.createElement(ListItemText, {
|
|
18
|
+
primary: /*#__PURE__*/React.createElement(Typography, {
|
|
19
|
+
color: "error"
|
|
20
|
+
}, title)
|
|
21
|
+
}));
|
|
22
|
+
});
|
|
23
|
+
Component.displayName = 'RevokeSharedDriveMember';
|
|
24
|
+
return Component;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
var revokeSharedDriveMember = function revokeSharedDriveMember(_ref) {
|
|
28
|
+
var t = _ref.t,
|
|
29
|
+
handleRevocation = _ref.handleRevocation;
|
|
30
|
+
var title = t("RevokeSharedDriveMemberItem.revoke.title");
|
|
31
|
+
return {
|
|
32
|
+
name: 'revokeSharedDriveMember',
|
|
33
|
+
label: title,
|
|
34
|
+
action: function action() {
|
|
35
|
+
handleRevocation();
|
|
36
|
+
},
|
|
37
|
+
Component: makeComponent(title)
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export { revokeSharedDriveMember };
|
|
@@ -220,6 +220,7 @@ var ShareAutocomplete = function ShareAutocomplete(_ref) {
|
|
|
220
220
|
renderInputComponent: renderInput,
|
|
221
221
|
highlightFirstSuggestion: true,
|
|
222
222
|
inputProps: {
|
|
223
|
+
autoFocus: true,
|
|
223
224
|
onFocus: onAutosuggestFocus,
|
|
224
225
|
onChange: onAutosuggestChange,
|
|
225
226
|
onPaste: onAutosuggestPaste,
|
|
@@ -78,17 +78,25 @@ describe('ShareAutosuggest', function () {
|
|
|
78
78
|
email: 'quentin.valmori@cozycloud.cc'
|
|
79
79
|
});
|
|
80
80
|
});
|
|
81
|
-
it('should show loading
|
|
81
|
+
it('should show loading indicator when loading prop is true (autoFocus triggers onFocus on mount)', function () {
|
|
82
82
|
var onPick = jest.fn();
|
|
83
83
|
var onRemove = jest.fn();
|
|
84
84
|
setup({
|
|
85
85
|
onPick: onPick,
|
|
86
86
|
onRemove: onRemove,
|
|
87
87
|
loading: true
|
|
88
|
+
}); // autoFocus triggers onFocus on mount, which sets isLoadingDisplayed
|
|
89
|
+
|
|
90
|
+
expect(screen.getByText('loading')).toBeInTheDocument();
|
|
91
|
+
});
|
|
92
|
+
it('should not show loading indicator when loading prop is false', function () {
|
|
93
|
+
var onPick = jest.fn();
|
|
94
|
+
var onRemove = jest.fn();
|
|
95
|
+
setup({
|
|
96
|
+
onPick: onPick,
|
|
97
|
+
onRemove: onRemove,
|
|
98
|
+
loading: false
|
|
88
99
|
});
|
|
89
|
-
var inputNode = screen.getByPlaceholderText('myPlaceHolder');
|
|
90
100
|
expect(screen.queryByText('loading')).toBeNull();
|
|
91
|
-
fireEvent.focus(inputNode);
|
|
92
|
-
expect(screen.getByText('loading')).toBeInTheDocument();
|
|
93
101
|
});
|
|
94
102
|
});
|
|
@@ -250,7 +250,7 @@ describe('ShareDialogCozyToCozy', function () {
|
|
|
250
250
|
}
|
|
251
251
|
}, _callee8);
|
|
252
252
|
})));
|
|
253
|
-
it('main
|
|
253
|
+
it('main Done button calls onClose when there are no pending chips', function () {
|
|
254
254
|
var onClose = jest.fn();
|
|
255
255
|
var onShare = jest.fn();
|
|
256
256
|
|
|
@@ -263,13 +263,60 @@ describe('ShareDialogCozyToCozy', function () {
|
|
|
263
263
|
getByRole = _setup6.getByRole;
|
|
264
264
|
|
|
265
265
|
fireEvent.click(getByRole('button', {
|
|
266
|
-
name: '
|
|
266
|
+
name: 'Done'
|
|
267
267
|
}));
|
|
268
268
|
expect(onShare).not.toHaveBeenCalled();
|
|
269
269
|
expect(onClose).toHaveBeenCalledTimes(1);
|
|
270
270
|
});
|
|
271
|
-
it('
|
|
272
|
-
var onClose
|
|
271
|
+
it('close action closes dialog when there are no pending chips', function () {
|
|
272
|
+
var onClose = jest.fn();
|
|
273
|
+
|
|
274
|
+
var props = _objectSpread(_objectSpread({}, getMockProps()), {}, {
|
|
275
|
+
onClose: onClose
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
var _setup7 = setup(props),
|
|
279
|
+
getByRole = _setup7.getByRole;
|
|
280
|
+
|
|
281
|
+
fireEvent.click(getByRole('button', {
|
|
282
|
+
name: 'Close'
|
|
283
|
+
}));
|
|
284
|
+
expect(onClose).toHaveBeenCalledTimes(1);
|
|
285
|
+
});
|
|
286
|
+
it('close action closes dialog when there are pending chips', function () {
|
|
287
|
+
var onClose = jest.fn();
|
|
288
|
+
|
|
289
|
+
var props = _objectSpread(_objectSpread({}, getMockProps()), {}, {
|
|
290
|
+
onClose: onClose
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
var _setup8 = setup(props),
|
|
294
|
+
getByPlaceholderText = _setup8.getByPlaceholderText,
|
|
295
|
+
getByRole = _setup8.getByRole,
|
|
296
|
+
queryByText = _setup8.queryByText;
|
|
297
|
+
|
|
298
|
+
act(function () {
|
|
299
|
+
fireEvent.change(getByPlaceholderText('Enter the email address or name of the recipient'), {
|
|
300
|
+
target: {
|
|
301
|
+
value: 'new@cozycloud.cc'
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
act(function () {
|
|
306
|
+
fireEvent.keyPress(getByPlaceholderText('Enter the email address or name of the recipient'), {
|
|
307
|
+
key: 'Enter',
|
|
308
|
+
code: 'Enter',
|
|
309
|
+
charCode: 13
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
fireEvent.click(getByRole('button', {
|
|
313
|
+
name: 'Close'
|
|
314
|
+
}));
|
|
315
|
+
expect(queryByText("Discard the changes you haven't saved?")).toBe(null);
|
|
316
|
+
expect(onClose).toHaveBeenCalledTimes(1);
|
|
317
|
+
});
|
|
318
|
+
it('main Done button calls onShare with chips then closes', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee10() {
|
|
319
|
+
var onClose, onShare, props, _setup9, getByPlaceholderText, getByRole;
|
|
273
320
|
|
|
274
321
|
return _regeneratorRuntime.wrap(function _callee10$(_context10) {
|
|
275
322
|
while (1) switch (_context10.prev = _context10.next) {
|
|
@@ -280,7 +327,7 @@ describe('ShareDialogCozyToCozy', function () {
|
|
|
280
327
|
onClose: onClose,
|
|
281
328
|
onShare: onShare
|
|
282
329
|
});
|
|
283
|
-
|
|
330
|
+
_setup9 = setup(props), getByPlaceholderText = _setup9.getByPlaceholderText, getByRole = _setup9.getByRole;
|
|
284
331
|
act(function () {
|
|
285
332
|
fireEvent.change(getByPlaceholderText('Enter the email address or name of the recipient'), {
|
|
286
333
|
target: {
|
|
@@ -301,7 +348,7 @@ describe('ShareDialogCozyToCozy', function () {
|
|
|
301
348
|
while (1) switch (_context9.prev = _context9.next) {
|
|
302
349
|
case 0:
|
|
303
350
|
fireEvent.click(getByRole('button', {
|
|
304
|
-
name: '
|
|
351
|
+
name: 'Done'
|
|
305
352
|
}));
|
|
306
353
|
|
|
307
354
|
case 1:
|
|
@@ -330,7 +377,7 @@ describe('ShareDialogCozyToCozy', function () {
|
|
|
330
377
|
}, _callee10);
|
|
331
378
|
})));
|
|
332
379
|
it("should display confirmation of 'contact rejection' when user click on the 'reject' button", /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee15() {
|
|
333
|
-
var _deferablePromise5, promise, resolve, rejectRecipient, props,
|
|
380
|
+
var _deferablePromise5, promise, resolve, rejectRecipient, props, _setup10, getByText, verifyButton, rejectButton, confirmRejectButton;
|
|
334
381
|
|
|
335
382
|
return _regeneratorRuntime.wrap(function _callee15$(_context15) {
|
|
336
383
|
while (1) switch (_context15.prev = _context15.next) {
|
|
@@ -348,7 +395,7 @@ describe('ShareDialogCozyToCozy', function () {
|
|
|
348
395
|
recipientConfirmationDialogContent: CozyPassFingerprintDialogContent
|
|
349
396
|
}
|
|
350
397
|
});
|
|
351
|
-
|
|
398
|
+
_setup10 = setup(props), getByText = _setup10.getByText;
|
|
352
399
|
_context15.next = 6;
|
|
353
400
|
return act( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee11() {
|
|
354
401
|
return _regeneratorRuntime.wrap(function _callee11$(_context11) {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import Button from 'cozy-ui/transpiled/react/Buttons';
|
|
4
|
+
import { ConfirmDialog } from 'cozy-ui/transpiled/react/CozyDialogs';
|
|
5
|
+
import { useI18n } from 'twake-i18n';
|
|
6
|
+
|
|
7
|
+
var ShareDiscardChangesModal = function ShareDiscardChangesModal(_ref) {
|
|
8
|
+
var onCancel = _ref.onCancel,
|
|
9
|
+
onConfirm = _ref.onConfirm;
|
|
10
|
+
|
|
11
|
+
var _useI18n = useI18n(),
|
|
12
|
+
t = _useI18n.t;
|
|
13
|
+
|
|
14
|
+
return /*#__PURE__*/React.createElement(ConfirmDialog, {
|
|
15
|
+
open: true,
|
|
16
|
+
title: t('ShareDiscardChangesModal.title'),
|
|
17
|
+
actions: /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
|
18
|
+
variant: "secondary",
|
|
19
|
+
label: t('ShareDiscardChangesModal.cancel'),
|
|
20
|
+
className: "u-fz-small",
|
|
21
|
+
onClick: onCancel
|
|
22
|
+
}), /*#__PURE__*/React.createElement(Button, {
|
|
23
|
+
variant: "primary",
|
|
24
|
+
label: t('ShareDiscardChangesModal.discard'),
|
|
25
|
+
className: "u-fz-small",
|
|
26
|
+
onClick: onConfirm
|
|
27
|
+
}))
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
ShareDiscardChangesModal.propTypes = {
|
|
32
|
+
onCancel: PropTypes.func.isRequired,
|
|
33
|
+
onConfirm: PropTypes.func.isRequired
|
|
34
|
+
};
|
|
35
|
+
export { ShareDiscardChangesModal };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import omit from 'lodash/omit';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { useLocation } from 'react-router';
|
|
5
|
+
import EditableSharingModal from './EditableSharingModal';
|
|
6
|
+
import { SharingDetailsModal } from './SharingDetailsModal';
|
|
7
|
+
import withLocales from '../../hoc/withLocales';
|
|
8
|
+
import { useSharingContext } from '../../hooks/useSharingContext';
|
|
9
|
+
export var ShareModal = withLocales(function (props) {
|
|
10
|
+
var _location$state;
|
|
11
|
+
|
|
12
|
+
var location = useLocation === null || useLocation === void 0 ? void 0 : useLocation();
|
|
13
|
+
var locationProps = location === null || location === void 0 || (_location$state = location.state) === null || _location$state === void 0 ? void 0 : _location$state.modalProps;
|
|
14
|
+
var document = (locationProps === null || locationProps === void 0 ? void 0 : locationProps.document) || props.document;
|
|
15
|
+
var rest = omit(locationProps || props, 'document');
|
|
16
|
+
|
|
17
|
+
var _useSharingContext = useSharingContext(),
|
|
18
|
+
byDocId = _useSharingContext.byDocId,
|
|
19
|
+
isOwner = _useSharingContext.isOwner,
|
|
20
|
+
canReshare = _useSharingContext.canReshare,
|
|
21
|
+
documentType = _useSharingContext.documentType,
|
|
22
|
+
getOwner = _useSharingContext.getOwner,
|
|
23
|
+
getSharingType = _useSharingContext.getSharingType,
|
|
24
|
+
getRecipients = _useSharingContext.getRecipients,
|
|
25
|
+
revokeSelf = _useSharingContext.revokeSelf;
|
|
26
|
+
|
|
27
|
+
var isEditable = !byDocId[document.id] || isOwner(document.id) || canReshare(document.id);
|
|
28
|
+
|
|
29
|
+
if (isEditable) {
|
|
30
|
+
return /*#__PURE__*/React.createElement(EditableSharingModal, _extends({
|
|
31
|
+
document: document
|
|
32
|
+
}, rest));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return /*#__PURE__*/React.createElement(SharingDetailsModal, _extends({
|
|
36
|
+
document: document,
|
|
37
|
+
documentType: documentType,
|
|
38
|
+
owner: getOwner(document.id),
|
|
39
|
+
sharingType: getSharingType(document.id),
|
|
40
|
+
recipients: getRecipients(document.id),
|
|
41
|
+
onRevoke: revokeSelf
|
|
42
|
+
}, rest));
|
|
43
|
+
});
|