diff --git a/css/main.css b/css/main.css index 43c4a467..9a25a17a 100644 --- a/css/main.css +++ b/css/main.css @@ -122,3 +122,34 @@ color: var(--color-error); } + +/* File drag and drop */ + +.filesListDragDropNotice{ + display: flex; + align-items: center; + justify-content: center; + width: 100%; + min-height: 113px; + margin: 0; + user-select: none; + color: var(--color-text-maxcontrast); + background-color: var(--color-main-background); + border-color: #000; +} + +.filesListDragDropNoticeWrapper{ + display: flex; + align-items: center; + justify-content: center; + height: 15vh; + max-height: 70%; + padding: 0 5vw; + border: 2px var(--color-border-dark) dashed; + border-radius: var(--border-radius-large); +} + +.filesListDragDropNoticeTitle{ + margin-left: 16px; + color: inherit; +} diff --git a/src/composables/UseFileSelection.js b/src/composables/UseFileSelection.js new file mode 100644 index 00000000..69b79672 --- /dev/null +++ b/src/composables/UseFileSelection.js @@ -0,0 +1,95 @@ +import { useDropZone, useFileDialog } from '@vueuse/core' +import { ref, computed } from 'vue' +import { publicationStore } from './../store/store.js' + +/** + * File selection composable + * @param options + * + * Special thanks to Github user adamreisnz for creating most of this file + * https://github.com/adamreisnz + * https://github.com/vueuse/vueuse/issues/4085 + * + */ +export function useFileSelection(options) { + + // Extract options + const { + dropzone, + allowMultiple, + allowedFileTypes, + onFileDrop, + } = options + + // Data types computed ref + const dataTypes = computed(() => { + if (allowedFileTypes?.value) { + if (!Array.isArray(allowedFileTypes.value)) { + return [allowedFileTypes.value] + } + return allowedFileTypes.value + } + return null + }) + + // Accept string computed ref + const accept = computed(() => { + if (Array.isArray(dataTypes.value)) { + return dataTypes.value.join(',') + } + return '*' + }) + + // Handling of files drop + const onDrop = files => { + if (!files || files.length === 0) { + return + } + if (files instanceof FileList) { + files = Array.from(files) + } + if (files.length > 1 && !allowMultiple.value) { + files = [files[0]] + } + filesList.value = files + onFileDrop && onFileDrop() + } + + const reset = () => { + filesList.value = null + } + + // const onLeave = () => { + // let timer + // document.addEventListener('mousemove', () => { + // clearTimeout(timer) + // timer = setTimeout(isOverDropZone.value = false, 300) + // }) + // } + + const setFiles = (files) => { + filesList.value = files + publicationStore.setAttachmentFile(null) + } + + // Setup dropzone and file dialog composables + const { isOverDropZone } = useDropZone(dropzone, { dataTypes, onDrop }) + const { onChange, open } = useFileDialog({ + accept: accept.value, + multiple: allowMultiple?.value, + }) + + const filesList = ref(null) + + // Use onChange handler + onChange(fileList => onDrop(fileList)) + + // Expose interface + return { + isOverDropZone, + openFileUpload: open, + files: filesList, + reset, + setFiles, + } +} diff --git a/src/modals/Modals.vue b/src/modals/Modals.vue index 224a7064..e3422dd1 100644 --- a/src/modals/Modals.vue +++ b/src/modals/Modals.vue @@ -1,7 +1,11 @@ + +