UBERF-7678 Fix folder upload to drive (#6159)

Signed-off-by: Alexander Onnikov <Alexander.Onnikov@xored.com>
This commit is contained in:
Alexander Onnikov 2024-07-29 13:50:56 +07:00 committed by GitHub
parent ff610b4d82
commit 81429df8cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 99 additions and 61 deletions

View File

@ -20,8 +20,7 @@
"Upload": "Upload",
"CreateDrive": "Create Drive",
"CreateFolder": "Create Folder",
"UploadFile": "Upload File",
"UploadFolder": "Upload Folder",
"UploadFile": "Upload Files",
"EditDrive": "Edit Drive",
"Rename": "Rename",
"Restore": "Restore",

View File

@ -20,8 +20,7 @@
"Upload": "Subir",
"CreateDrive": "Crear unidad",
"CreateFolder": "Crear carpeta",
"UploadFile": "Subir archivo",
"UploadFolder": "Subir carpeta",
"UploadFile": "Subir archivos",
"EditDrive": "Editar unidad",
"Rename": "Renombrar",
"Restore": "Restaurar",

View File

@ -20,8 +20,7 @@
"Upload": "Téléverser",
"CreateDrive": "Créer un disque",
"CreateFolder": "Créer un dossier",
"UploadFile": "Télécharger un fichier",
"UploadFolder": "Télécharger un dossier",
"UploadFile": "Télécharger des fichiers",
"EditDrive": "Modifier le disque",
"Rename": "Renommer",
"Restore": "Restaurer",

View File

@ -20,8 +20,7 @@
"Upload": "Carregar",
"CreateDrive": "Criar unidade",
"CreateFolder": "Criar pasta",
"UploadFile": "Carregar ficheiro",
"UploadFolder": "Carregar pasta",
"UploadFile": "Carregar ficheiros",
"EditDrive": "Editar unidade",
"Rename": "Renomear",
"Restore": "Restaurar",

View File

@ -20,8 +20,7 @@
"Upload": "Загрузить",
"CreateDrive": "Создать диск",
"CreateFolder": "Создать папку",
"UploadFile": "Загрузить файл",
"UploadFolder": "Загрузить папку",
"UploadFile": "Загрузить файлы",
"EditDrive": "Редактировать",
"Rename": "Переименовать",
"Restore": "Восстановить",

View File

@ -21,7 +21,6 @@
"CreateDrive": "创建磁盘",
"CreateFolder": "创建文件夹",
"UploadFile": "上传文件",
"UploadFolder": "上传文件夹",
"EditDrive": "编辑磁盘",
"Rename": "重命名",
"Restore": "恢复",

View File

@ -14,22 +14,19 @@
-->
<script lang="ts">
import { AccountRole, Ref, getCurrentAccount, hasAccountRole } from '@hcengineering/core'
import { createFile, type Drive } from '@hcengineering/drive'
import { setPlatformStatus, unknownError } from '@hcengineering/platform'
import { createQuery, getClient } from '@hcengineering/presentation'
import { type Drive } from '@hcengineering/drive'
import { createQuery } from '@hcengineering/presentation'
import { Button, ButtonWithDropdown, IconAdd, IconDropdown, Loading, SelectPopupValueType } from '@hcengineering/ui'
import { showFilesUploadPopup } from '@hcengineering/uploader'
import drive from '../plugin'
import { getFolderIdFromFragment } from '../navigation'
import { showCreateDrivePopup, showCreateFolderPopup } from '../utils'
import { showCreateDrivePopup, showCreateFolderPopup, uploadFilesToDrivePopup } from '../utils'
export let currentSpace: Ref<Drive> | undefined
export let currentFragment: string | undefined
const me = getCurrentAccount()
const client = getClient()
const query = createQuery()
let loading = true
@ -66,27 +63,7 @@
async function handleUploadFile (): Promise<void> {
if (currentSpace !== undefined) {
const space = currentSpace
const target =
parent !== drive.ids.Root
? { objectId: parent, objectClass: drive.class.Folder }
: { objectId: space, objectClass: drive.class.Drive }
await showFilesUploadPopup(target, {}, async (uuid, name, file, path, metadata) => {
try {
const data = {
file: uuid,
size: file.size,
type: file.type,
lastModified: file instanceof File ? file.lastModified : Date.now(),
name,
metadata
}
await createFile(client, space, parent, data)
} catch (err) {
void setPlatformStatus(unknownError(err))
}
})
await uploadFilesToDrivePopup(currentSpace, parent)
}
}
@ -95,12 +72,10 @@
{ id: drive.string.CreateDrive, label: drive.string.CreateDrive, icon: drive.icon.Drive },
{ id: drive.string.CreateFolder, label: drive.string.CreateFolder, icon: drive.icon.Folder },
{ id: drive.string.UploadFile, label: drive.string.UploadFile, icon: drive.icon.File }
// { id: drive.string.UploadFolder, label: drive.string.UploadFolder }
]
: [
{ id: drive.string.CreateFolder, label: drive.string.CreateFolder, icon: drive.icon.Folder },
{ id: drive.string.UploadFile, label: drive.string.UploadFile, icon: drive.icon.File }
// { id: drive.string.UploadFolder, label: drive.string.UploadFolder }
]
</script>

View File

@ -73,6 +73,7 @@
maxNumberOfFiles: 1,
hideProgress: true
},
{},
async (uuid, name, file, path, metadata) => {
const data = {
file: uuid,

View File

@ -21,7 +21,6 @@ export default mergeIds(driveId, drive, {
CreateDrive: '' as IntlString,
CreateFolder: '' as IntlString,
UploadFile: '' as IntlString,
UploadFolder: '' as IntlString,
Download: '' as IntlString,
Upload: '' as IntlString,
EditDrive: '' as IntlString,

View File

@ -19,7 +19,12 @@ import drive, { createFile } from '@hcengineering/drive'
import { type Asset, setPlatformStatus, unknownError } from '@hcengineering/platform'
import { getClient } from '@hcengineering/presentation'
import { type AnySvelteComponent, showPopup } from '@hcengineering/ui'
import { uploadFiles } from '@hcengineering/uploader'
import {
type FileUploadCallback,
getDataTransferFiles,
showFilesUploadPopup,
uploadFiles
} from '@hcengineering/uploader'
import { openDoc } from '@hcengineering/view-resources'
import CreateDrive from './components/CreateDrive.svelte'
@ -154,7 +159,38 @@ export async function resolveParents (object: Resource): Promise<Doc[]> {
return parents.reverse()
}
export async function uploadFilesToDrive (files: DataTransfer, space: Ref<Drive>, parent: Ref<Folder>): Promise<void> {
export async function uploadFilesToDrive (dt: DataTransfer, space: Ref<Drive>, parent: Ref<Folder>): Promise<void> {
const files = await getDataTransferFiles(dt)
const onFileUploaded = await fileUploadCallback(space, parent)
const target =
parent !== drive.ids.Root
? { objectId: parent, objectClass: drive.class.Folder }
: { objectId: space, objectClass: drive.class.Drive }
await uploadFiles(files, target, {}, onFileUploaded)
}
export async function uploadFilesToDrivePopup (space: Ref<Drive>, parent: Ref<Folder>): Promise<void> {
const onFileUploaded = await fileUploadCallback(space, parent)
const target =
parent !== drive.ids.Root
? { objectId: parent, objectClass: drive.class.Folder }
: { objectId: space, objectClass: drive.class.Drive }
await showFilesUploadPopup(
target,
{},
{
fileManagerSelectionType: 'both'
},
onFileUploaded
)
}
async function fileUploadCallback (space: Ref<Drive>, parent: Ref<Folder>): Promise<FileUploadCallback> {
const client = getClient()
const query = parent !== drive.ids.Root ? { space, path: parent } : { space }
@ -190,12 +226,7 @@ export async function uploadFilesToDrive (files: DataTransfer, space: Ref<Drive>
return current
}
const target =
parent !== drive.ids.Root
? { objectId: parent, objectClass: drive.class.Folder }
: { objectId: space, objectClass: drive.class.Drive }
await uploadFiles(files, target, {}, async (uuid, name, file, path, metadata) => {
const callback: FileUploadCallback = async (uuid, name, file, path, metadata) => {
const folder = await findParent(path)
try {
const data = {
@ -211,5 +242,7 @@ export async function uploadFilesToDrive (files: DataTransfer, space: Ref<Drive>
} catch (err) {
void setPlatformStatus(unknownError(err))
}
})
}
return callback
}

View File

@ -14,6 +14,7 @@
-->
<script lang="ts">
import { themeStore } from '@hcengineering/ui'
import { type FileUploadPopupOptions } from '@hcengineering/uploader'
import { type Uppy } from '@uppy/core'
import Dashboard from '@uppy/dashboard'
@ -25,6 +26,7 @@
const dispatch = createEventDispatcher()
export let uppy: Uppy<any, any>
export let options: FileUploadPopupOptions
let container: HTMLElement
@ -46,7 +48,8 @@
width: 750,
disableInformer: true,
proudlyDisplayPoweredByUppy: false,
theme: dark ? 'dark' : 'light'
theme: dark ? 'dark' : 'light',
fileManagerSelectionType: options.fileManagerSelectionType
})
})

View File

@ -79,7 +79,7 @@
class="container flex-row-center flex-gap-2 active"
class:error={state.error}
on:click={handleClick}
use:tooltip={state.error != null ? { label: getEmbeddedLabel(state.error) } : undefined}
use:tooltip={state.error !== undefined ? { label: getEmbeddedLabel(state.error) } : undefined}
>
{#if state.error}
<IconError size={'small'} fill={'var(--negative-button-default)'} />

View File

@ -70,6 +70,10 @@
}
}
function handleCancelAll (): void {
upload.uppy.cancelAll()
}
function handleCancelFile (file: UppyFile<any, any>): void {
upload.uppy.removeFile(file.id)
}
@ -123,6 +127,17 @@
noUnderline
/>
</div>
{#if state.error}
<Button
kind={'icon'}
icon={IconClose}
iconProps={{ size: 'small' }}
showTooltip={{ label: uploader.string.Cancel }}
on:click={() => {
handleCancelAll()
}}
/>
{/if}
</div>
<Scroller>
<div class="upload-popup__content flex-col flex-no-shrink flex-gap-4">
@ -209,6 +224,8 @@
.upload-popup__header {
padding-bottom: 1rem;
margin-left: 0.5rem;
margin-right: 0.625rem;
}
.upload-popup__content {

View File

@ -17,8 +17,8 @@ import { showPopup } from '@hcengineering/ui'
import {
type FileUploadCallback,
type FileUploadOptions,
type FileUploadPopupOptions,
type FileUploadTarget,
getDataTransferFiles,
toFileWithPath
} from '@hcengineering/uploader'
@ -31,11 +31,12 @@ import { getUppy } from './uppy'
export async function showFilesUploadPopup (
target: FileUploadTarget,
options: FileUploadOptions,
popupOptions: FileUploadPopupOptions,
onFileUploaded: FileUploadCallback
): Promise<void> {
const uppy = getUppy(options, onFileUploaded)
showPopup(FileUploadPopup, { uppy, target }, undefined, (res) => {
showPopup(FileUploadPopup, { uppy, target, options: popupOptions }, undefined, (res) => {
if (res === true && options.hideProgress !== true) {
dockFileUpload(target, uppy)
}
@ -44,13 +45,12 @@ export async function showFilesUploadPopup (
/** @public */
export async function uploadFiles (
files: File[] | FileList | DataTransfer,
files: File[] | FileList,
target: FileUploadTarget,
options: FileUploadOptions,
onFileUploaded: FileUploadCallback
): Promise<void> {
const items =
files instanceof DataTransfer ? await getDataTransferFiles(files) : Array.from(files, (p) => toFileWithPath(p))
const items = Array.from(files, (p) => toFileWithPath(p))
if (items.length === 0) return

View File

@ -24,12 +24,13 @@ export interface FileWithPath extends File {
export type UploadFilesPopupFn = (
target: FileUploadTarget,
options: FileUploadOptions,
popupOptions: FileUploadPopupOptions,
onFileUploaded: FileUploadCallback
) => Promise<void>
/** @public */
export type UploadFilesFn = (
files: File[] | FileList | DataTransfer,
files: File[] | FileList,
target: FileUploadTarget,
options: FileUploadOptions,
onFileUploaded: FileUploadCallback
@ -49,6 +50,11 @@ export interface FileUploadOptions {
hideProgress?: boolean
}
/** @public */
export interface FileUploadPopupOptions {
fileManagerSelectionType?: 'files' | 'folders' | 'both'
}
/** @public */
export type FileUploadCallback = (
uuid: Ref<PlatformBlob>,

View File

@ -16,21 +16,28 @@
import { getResource } from '@hcengineering/platform'
import uploader from './plugin'
import type { FileUploadCallback, FileUploadOptions, FileUploadTarget, FileWithPath } from './types'
import type {
FileUploadCallback,
FileUploadOptions,
FileUploadPopupOptions,
FileUploadTarget,
FileWithPath
} from './types'
/** @public */
export async function showFilesUploadPopup (
target: FileUploadTarget,
options: FileUploadOptions,
popupOptions: FileUploadPopupOptions,
onFileUploaded: FileUploadCallback
): Promise<void> {
const fn = await getResource(uploader.function.ShowFilesUploadPopup)
await fn(target, options, onFileUploaded)
await fn(target, options, popupOptions, onFileUploaded)
}
/** @public */
export async function uploadFiles (
files: File[] | FileList | DataTransfer,
files: File[] | FileList,
target: FileUploadTarget,
options: FileUploadOptions,
onFileUploaded: FileUploadCallback
@ -63,6 +70,9 @@ export async function getDataTransferFiles (dataTransfer: DataTransfer): Promise
/** @public */
export function toFileWithPath (file: File, path?: string): FileWithPath {
const { webkitRelativePath } = file
if ('relativePath' in file) {
return file as FileWithPath
}
Object.defineProperty(file, 'relativePath', {
value:
typeof path === 'string'