Skip to content

Commit

Permalink
feat: Ability to upload multiple attachments at once
Browse files Browse the repository at this point in the history
Closes #908
  • Loading branch information
meltyshev committed Oct 9, 2024
1 parent 52f8abc commit 1948bd4
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 29 deletions.
2 changes: 1 addition & 1 deletion client/src/components/CardModal/AttachmentAddStep.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const AttachmentAddStep = React.memo(({ onCreate, onClose }) => {
</Popup.Header>
<Popup.Content>
<Menu secondary vertical className={styles.menu}>
<FilePicker onSelect={handleFileSelect}>
<FilePicker multiple onSelect={handleFileSelect}>
<Menu.Item className={styles.menuItem}>
{t('common.fromComputer', {
context: 'title',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next';
import { closePopup } from '../../../lib/popup';

import { useModal } from '../../../hooks';
import { isActiveTextElement } from '../../../utils/element-helpers';
import TextFileAddModal from './TextFileAddModal';

import styles from './AttachmentAddZone.module.scss';
Expand All @@ -24,13 +25,14 @@ const AttachmentAddZone = React.memo(({ children, onCreate }) => {

const handleDropAccepted = useCallback(
(files) => {
submit(files[0]);
files.forEach((file) => {
submit(file);
});
},
[submit],
);

const { getRootProps, getInputProps, isDragActive } = useDropzone({
multiple: false,
noClick: true,
noKeyboard: true,
onDropAccepted: handleDropAccepted,
Expand All @@ -49,38 +51,43 @@ const AttachmentAddZone = React.memo(({ children, onCreate }) => {
return;
}

const file = event.clipboardData.files[0];
const { files, items } = event.clipboardData;

if (file) {
submit(file);
return;
}

const item = event.clipboardData.items[0];
if (files.length > 0) {
[...files].forEach((file) => {
submit(file);
});

if (!item) {
return;
}

if (item.kind === 'file') {
submit(item.getAsFile());
if (items.length === 0) {
return;
}

if (
['input', 'textarea'].includes(event.target.tagName.toLowerCase()) &&
event.target === document.activeElement
) {
if (items[0].kind === 'string') {
if (isActiveTextElement(event.target)) {
return;
}

closePopup();
event.preventDefault();

items[0].getAsString((content) => {
openModal({
content,
});
});

return;
}

closePopup();
event.preventDefault();
[...items].forEach((item) => {
if (item.kind !== 'file') {
return;
}

item.getAsString((content) => {
openModal({
content,
});
submit(item.getAsFile());
});
};

Expand Down
13 changes: 8 additions & 5 deletions client/src/lib/custom-ui/components/FilePicker/FilePicker.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from 'prop-types';

import styles from './FilePicker.module.css';

const FilePicker = React.memo(({ children, accept, onSelect }) => {
const FilePicker = React.memo(({ children, accept, multiple, onSelect }) => {
const field = useRef(null);

const handleTriggerClick = useCallback(() => {
Expand All @@ -12,11 +12,11 @@ const FilePicker = React.memo(({ children, accept, onSelect }) => {

const handleFieldChange = useCallback(
({ target }) => {
if (target.files[0]) {
onSelect(target.files[0]);
[...target.files].forEach((file) => {
onSelect(file);
});

target.value = null; // eslint-disable-line no-param-reassign
}
target.value = null; // eslint-disable-line no-param-reassign
},
[onSelect],
);
Expand All @@ -32,6 +32,7 @@ const FilePicker = React.memo(({ children, accept, onSelect }) => {
ref={field}
type="file"
accept={accept}
multiple={multiple}
className={styles.field}
onChange={handleFieldChange}
/>
Expand All @@ -42,11 +43,13 @@ const FilePicker = React.memo(({ children, accept, onSelect }) => {
FilePicker.propTypes = {
children: PropTypes.element.isRequired,
accept: PropTypes.string,
multiple: PropTypes.bool,
onSelect: PropTypes.func.isRequired,
};

FilePicker.defaultProps = {
accept: undefined,
multiple: false,
};

export default FilePicker;
5 changes: 4 additions & 1 deletion client/src/utils/element-helpers.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// eslint-disable-next-line import/prefer-default-export
export const focusEnd = (element) => {
element.focus();
element.setSelectionRange(element.value.length + 1, element.value.length + 1);
};

export const isActiveTextElement = (element) =>
['input', 'textarea'].includes(element.tagName.toLowerCase()) &&
element === document.activeElement;

0 comments on commit 1948bd4

Please sign in to comment.