Skip to content

Commit

Permalink
Here’s the revised commit message:
Browse files Browse the repository at this point in the history
[processing#3086] Enable Sidebar Drag and Drop with Multi-level Uploads

Enhanced the Sketch Files sidebar to support drag-and-drop file uploads, improving accessibility and workflow.

Details:
	•	Introduced a wrapper component to handle drag-and-drop functionality.
	•	Enabled multi-level uploads, allowing files to be uploaded into nested directories.
	•	Updated initSidebarUpload to dynamically initialize uploads for the active folder or root directory.
	•	Integrated drag-and-drop with <ConnectedFileNode> for seamless uploads.

Improvements:
	•	Simplified file upload process by removing the need for [+] > [Upload File].
	•	Enhanced user feedback with dynamic drag-over messages.

This update improves user workflow and sets the foundation for future features like cross-sketch file duplication.
  • Loading branch information
sam-shubham committed Dec 24, 2024
1 parent 9bd7c99 commit f4fd180
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 5 deletions.
1 change: 1 addition & 0 deletions client/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export const SHOW_FOLDER_CHILDREN = 'SHOW_FOLDER_CHILDREN';
export const HIDE_FOLDER_CHILDREN = 'HIDE_FOLDER_CHILDREN';
export const OPEN_UPLOAD_FILE_MODAL = 'OPEN_UPLOAD_FILE_MODAL';
export const CLOSE_UPLOAD_FILE_MODAL = 'CLOSE_UPLOAD_FILE_MODAL';
export const INITIALIZE_SIDEBAR_UPLOAD = 'INITIALIZE_SIDEBAR_UPLOAD';

export const SHOW_SHARE_MODAL = 'SHOW_SHARE_MODAL';
export const CLOSE_SHARE_MODAL = 'CLOSE_SHARE_MODAL';
Expand Down
7 changes: 7 additions & 0 deletions client/modules/IDE/actions/ide.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@ export function closeUploadFileModal() {
};
}

export function initSidebarUpload(parentId) {
return {
type: ActionTypes.INITIALIZE_SIDEBAR_UPLOAD,
parentId
};
}

export function expandSidebar() {
return {
type: ActionTypes.EXPAND_SIDEBAR
Expand Down
10 changes: 6 additions & 4 deletions client/modules/IDE/actions/uploader.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ export async function dropzoneAcceptCallback(userId, file, done) {
file.content = await file.text();
// Make it an error so that it won't be sent to S3, but style as a success.
done('Uploading plaintext file locally.');
file.previewElement.classList.remove('dz-error');
file.previewElement.classList.add('dz-success');
file.previewElement.classList.add('dz-processing');
file.previewElement.querySelector('.dz-upload').style.width = '100%';
if (file.previewElement) {
file.previewElement.classList.remove('dz-error');
file.previewElement.classList.add('dz-success');
file.previewElement.classList.add('dz-processing');
file.previewElement.querySelector('.dz-upload').style.width = '100%';
}
} catch (error) {
done(`Failed to download file ${file.name}: ${error}`);
console.warn(file);
Expand Down
5 changes: 4 additions & 1 deletion client/modules/IDE/components/Sidebar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { getAuthenticated, selectCanEditSketch } from '../selectors/users';
import ConnectedFileNode from './FileNode';
import { PlusIcon } from '../../../common/icons';
import { FileDrawer } from './Editor/MobileEditor';
import SidebarFileDragDropUploadWrapper from './SidebarFileDragDropUploadWrapper';

// TODO: use a generic Dropdown UI component

Expand Down Expand Up @@ -130,7 +131,9 @@ export default function SideBar() {
</ul>
</div>
</header>
<ConnectedFileNode id={rootFile.id} canEdit={canEditProject} />
<SidebarFileDragDropUploadWrapper>
<ConnectedFileNode id={rootFile.id} canEdit={canEditProject} />
</SidebarFileDragDropUploadWrapper>
</section>
</FileDrawer>
);
Expand Down
128 changes: 128 additions & 0 deletions client/modules/IDE/components/SidebarFileDragDropUploadWrapper.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import Dropzone from 'dropzone';
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
import { useDispatch, useSelector } from 'react-redux';
import { useTranslation } from 'react-i18next';
import styled from 'styled-components';
import { fileExtensionsAndMimeTypes } from '../../../../server/utils/fileUtils';
import {
dropzoneAcceptCallback,
dropzoneCompleteCallback,
dropzoneSendingCallback,
s3BucketHttps
} from '../actions/uploader';
import { selectActiveFile, selectRootFile } from '../selectors/files';
import { initSidebarUpload } from '../actions/ide';

Dropzone.autoDiscover = false;

// Styled Components
const Wrapper = styled.div`
height: 100%;
display: flex;
position: relative;
`;

const HiddenInputContainer = styled.div``;

const DraggingOverMessage = styled.div`
position: absolute;
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, 0.5);
color: rgba(255, 255, 255, 0.85);
display: none;
justify-content: center;
align-items: center;
text-align: center;
padding: 1rem;
font-weight: semibold;
transition: background-color 0.3s ease;
`;

function SidebarFileDragDropUploadWrapper({ children }) {
const { t } = useTranslation();
const dispatch = useDispatch();
const userId = useSelector((state) => state.user.id);

const rootFile = useSelector(selectRootFile);
const activeFile = useSelector(selectActiveFile);

useEffect(() => {
dispatch(
initSidebarUpload(
activeFile.fileType === 'folder' ? activeFile.id : rootFile.id
)
);

let dragCounter = 0;

const uploader = new Dropzone('div#sidebar-file-drag-drop-upload-wrapper', {
url: s3BucketHttps,
method: 'post',
autoProcessQueue: false,
clickable: false,
hiddenInputContainer: '#sidebar-hidden-input-container',
maxFiles: 6,
parallelUploads: 1,
maxFilesize: 5, // in MB
maxThumbnailFilesize: 8, // in MB
thumbnailWidth: 10,
previewsContainer: false,
thumbnailHeight: 10,
acceptedFiles: fileExtensionsAndMimeTypes,
dictDefaultMessage: t('FileUploader.DictDefaultMessage'),
accept: (file, done) => {
dropzoneAcceptCallback(userId, file, done);
},
sending: dropzoneSendingCallback
});

uploader.on('complete', (file) => {
dispatch(dropzoneCompleteCallback(file));
});

uploader.on('dragenter', () => {
dragCounter += 1;
document.getElementById('dragging-over-message').style.display = 'flex';
});

uploader.on('dragleave', () => {
dragCounter -= 1;

if (dragCounter <= 0) {
dragCounter = 0;
document.getElementById('dragging-over-message').style.display = 'none';
}
});

uploader.on('drop', () => {
dragCounter = 0;
document.getElementById('dragging-over-message').style.display = 'none';
});

return () => {
uploader.off('complete');
uploader.off('dragenter');
uploader.off('dragleave');
uploader.off('drop');
uploader.destroy();
};
}, [userId, dispatch, t, activeFile]);

return (
<Wrapper id="sidebar-file-drag-drop-upload-wrapper">
<HiddenInputContainer id="sidebar-hidden-input-container" />
{children}
<DraggingOverMessage id="dragging-over-message">
{t('FileUploader.DictDefaultMessage')}
</DraggingOverMessage>
</Wrapper>
);
}

SidebarFileDragDropUploadWrapper.propTypes = {
children: PropTypes.node.isRequired
};

export default SidebarFileDragDropUploadWrapper;
2 changes: 2 additions & 0 deletions client/modules/IDE/reducers/ide.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ const ide = (state = initialState, action) => {
});
case ActionTypes.CLOSE_UPLOAD_FILE_MODAL:
return Object.assign({}, state, { uploadFileModalVisible: false });
case ActionTypes.INITIALIZE_SIDEBAR_UPLOAD:
return Object.assign({}, state, { parentId: action.parentId });
default:
return state;
}
Expand Down

0 comments on commit f4fd180

Please sign in to comment.