Skip to content

Commit

Permalink
feat: adds drag&drop across File Manager cards
Browse files Browse the repository at this point in the history
Signed-off-by: Pedro Lamas <[email protected]>
  • Loading branch information
pedrolamas committed Nov 17, 2023
1 parent 7476593 commit cf32644
Show file tree
Hide file tree
Showing 18 changed files with 94 additions and 48 deletions.
53 changes: 37 additions & 16 deletions src/components/widgets/filesystem/FileSystem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ import FileSystemGoToFileDialog from './FileSystemGoToFileDialog.vue'
import FilePreviewDialog from './FilePreviewDialog.vue'
import type { AppTableHeader, FileWithPath } from '@/types'
import { getFilesFromDataTransfer, hasFilesInDataTransfer } from '@/util/file-system-entry'
import { getFileDataTransferDataFromDataTransfer, hasFileDataTransferTypeInDataTransfer, setFileDataTransferDataInDataTransfer } from '@/util/file-data-transfer'
/**
* Represents the filesystem, bound to moonrakers supplied roots.
Expand Down Expand Up @@ -796,22 +797,29 @@ export default class FileSystem extends Mixins(StateMixin, FilesMixin, ServicesM
})
}
handleDragStart (source: FileBrowserEntry| FileBrowserEntry[], dataTransfer: DataTransfer) {
if (this.currentRoot === 'gcodes') {
const items = Array.isArray(source)
? source.filter(item => item.name !== '..')
: [source]
handleDragStart (item: FileBrowserEntry, items: FileBrowserEntry[], dataTransfer: DataTransfer) {
if (item.type === 'file') {
const url = this.createFileUrl(item.name, this.currentPath)
dataTransfer.setData('text/html', `<A HREF="${encodeURI(url)}">${item.filename}</A>`)
dataTransfer.setData('text/plain', url)
dataTransfer.setData('text/uri-list', url)
}
setFileDataTransferDataInDataTransfer(dataTransfer, 'files', {
path: this.currentPath,
items: items.map(file => file.name)
})
if (this.currentRoot === 'gcodes') {
const files = items
.filter((item): item is AppFile => item.type === 'file' && this.rootProperties.accepts.includes(`.${item.extension}`))
if (files.length > 0) {
const data = {
setFileDataTransferDataInDataTransfer(dataTransfer, 'jobs', {
path: files[0].path,
jobs: files.map(file => file.name)
}
dataTransfer.setData('x-fluidd-jobs', JSON.stringify(data))
items: files.map(file => file.name)
})
}
}
}
Expand Down Expand Up @@ -950,7 +958,10 @@ export default class FileSystem extends Mixins(StateMixin, FilesMixin, ServicesM
!this.rootProperties.readonly &&
!this.dragState.browserState &&
event.dataTransfer &&
hasFilesInDataTransfer(event.dataTransfer)
(
hasFilesInDataTransfer(event.dataTransfer) ||
hasFileDataTransferTypeInDataTransfer(event.dataTransfer, 'files')
)
) {
event.preventDefault()
Expand All @@ -969,13 +980,23 @@ export default class FileSystem extends Mixins(StateMixin, FilesMixin, ServicesM
if (
!this.fileDropRoot &&
event.dataTransfer &&
!this.rootProperties.readonly
!this.rootProperties.readonly &&
event.dataTransfer
) {
const files = await getFilesFromDataTransfer(event.dataTransfer)
if (hasFileDataTransferTypeInDataTransfer(event.dataTransfer, 'files')) {
const files = getFileDataTransferDataFromDataTransfer(event.dataTransfer, 'files')
if (files) {
this.handleUpload(files, false)
for (const file of files.items) {
const src = `${files.path}/${file}`
const dest = `${this.currentPath}/${file}`
SocketActions.serverFilesCopy(src, dest)
}
} else if (hasFilesInDataTransfer(event.dataTransfer)) {
const files = await getFilesFromDataTransfer(event.dataTransfer)
if (files) {
this.handleUpload(files, false)
}
}
}
}
Expand Down
15 changes: 5 additions & 10 deletions src/components/widgets/filesystem/FileSystemBrowser.vue
Original file line number Diff line number Diff line change
Expand Up @@ -442,19 +442,14 @@ export default class FileSystemBrowser extends Mixins(FilesMixin) {
this.ghost = document.createElement('div')
this.ghost.classList.add('bulk-drag')
this.ghost.classList.add((this.$vuetify.theme.dark) ? 'theme--dark' : 'theme--light')
this.ghost.innerHTML = this.$tc('app.file_system.tooltip.move_item', draggedItems.length)
this.ghost.innerHTML = draggedItems.length > 1
? this.$tc('app.file_system.tooltip.items_count', draggedItems.length)
: item.name
document.body.appendChild(this.ghost)
event.dataTransfer.effectAllowed = 'linkMove'
event.dataTransfer.effectAllowed = 'all'
event.dataTransfer.setDragImage(this.ghost, 0, 0)
if (item.type === 'file') {
const filepath = item.path ? `${this.root}/${item.path}` : this.root
const url = this.createFileUrl(item.filename, filepath)
event.dataTransfer.setData('text/html', `<A HREF="${encodeURI(url)}">${item.filename}</A>`)
event.dataTransfer.setData('text/plain', url)
event.dataTransfer.setData('text/uri-list', url)
}
this.$emit('drag-start', draggedItems, event.dataTransfer)
this.$emit('drag-start', item, draggedItems, event.dataTransfer)
}
}
Expand Down
16 changes: 11 additions & 5 deletions src/components/widgets/gcode-preview/GcodePreviewCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ import GcodePreview from './GcodePreview.vue'
import GcodePreviewParserProgressDialog from './GcodePreviewParserProgressDialog.vue'
import type { AppFile } from '@/store/files/types'
import type { MinMax } from '@/store/gcodePreview/types'
import { getFileDataTransferDataFromDataTransfer, hasFileDataTransferTypeInDataTransfer } from '@/util/file-data-transfer'
@Component({
components: {
Expand Down Expand Up @@ -396,7 +397,10 @@ export default class GcodePreviewCard extends Mixins(StateMixin, FilesMixin, Bro
}
handleDragOver (event: DragEvent) {
if (event.dataTransfer?.types.includes('x-fluidd-jobs')) {
if (
event.dataTransfer &&
hasFileDataTransferTypeInDataTransfer(event.dataTransfer, 'jobs')
) {
event.preventDefault()
event.dataTransfer.dropEffect = 'link'
Expand All @@ -412,12 +416,14 @@ export default class GcodePreviewCard extends Mixins(StateMixin, FilesMixin, Bro
handleDrop (event: DragEvent) {
this.overlay = false
if (event.dataTransfer?.types.includes('x-fluidd-jobs')) {
const data = event.dataTransfer.getData('x-fluidd-jobs')
const files: { path: string, jobs: string[] } = JSON.parse(data)
if (
event.dataTransfer &&
hasFileDataTransferTypeInDataTransfer(event.dataTransfer, 'jobs')
) {
const files = getFileDataTransferDataFromDataTransfer(event.dataTransfer, 'jobs')
const path = files.path ? `gcodes/${files.path}` : 'gcodes'
const file = this.$store.getters['files/getFile'](path, files.jobs[0]) as AppFile | undefined
const file = this.$store.getters['files/getFile'](path, files.items[0]) as AppFile | undefined
if (file) {
this.loadFile(file)
Expand Down
16 changes: 11 additions & 5 deletions src/components/widgets/job-queue/JobQueue.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import JobQueueBrowser from './JobQueueBrowser.vue'
import JobQueueContextMenu from './JobQueueContextMenu.vue'
import JobQueueMultiplyJobDialog from './JobQueueMultiplyJobDialog.vue'
import type { AppTableHeader } from '@/types'
import { getFileDataTransferDataFromDataTransfer, hasFileDataTransferTypeInDataTransfer } from '@/util/file-data-transfer'
@Component({
components: {
Expand Down Expand Up @@ -180,7 +181,10 @@ export default class JobQueue extends Vue {
}
handleDragOver (event: DragEvent) {
if (event.dataTransfer?.types.includes('x-fluidd-jobs')) {
if (
event.dataTransfer &&
hasFileDataTransferTypeInDataTransfer(event.dataTransfer, 'jobs')
) {
event.preventDefault()
event.dataTransfer.dropEffect = 'link'
Expand All @@ -196,11 +200,13 @@ export default class JobQueue extends Vue {
handleDrop (event: DragEvent) {
this.overlay = false
if (event.dataTransfer?.types.includes('x-fluidd-jobs')) {
const data = event.dataTransfer.getData('x-fluidd-jobs')
const files: { path: string, jobs: string[] } = JSON.parse(data)
if (
event.dataTransfer &&
hasFileDataTransferTypeInDataTransfer(event.dataTransfer, 'jobs')
) {
const files = getFileDataTransferDataFromDataTransfer(event.dataTransfer, 'jobs')
const filePath = files.path ? `${files.path}/` : ''
const filenames = files.jobs
const filenames = files.items
.map(file => `${filePath}${file}`)
SocketActions.serverJobQueuePostJob(filenames)
Expand Down
4 changes: 4 additions & 0 deletions src/globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ export const Globals = Object.freeze({
{ filename: 'telegram.conf', service: 'moonraker-telegram-bot', link: 'https://github.com/nlef/moonraker-telegram-bot/wiki/Sample-config' },
{ suffix: '.cfg', service: 'klipper', link: 'https://www.klipper3d.org/Config_Reference.html' }
],
FILE_DATA_TRANSFER_TYPES: {
files: 'x-fluidd-files',
jobs: 'x-fluidd-jobs'
},
FILTERED_FOLDER_NAMES: ['.git'],
FILTERED_FILES_PREFIX: ['.thumbs', 'thumbs'],
FILTERED_FILES_EXTENSION: ['.ignoreme'],
Expand Down
1 change: 0 additions & 1 deletion src/locales/af.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ app:
upload_file: Lêer word opgelaai | Lêers word opgelaai
tooltip:
low_on_space: Stoorspasie is min
move_item: Skuif item | Skuif {count} items
root_disabled: '{root} root is nie beskikbaar nie. Sien die logs.'
url:
klipper_config: 'https://www.klipper3d.org/Config_Reference.html#%{hash}'
Expand Down
1 change: 0 additions & 1 deletion src/locales/de.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ app:
tooltip:
low_on_space: Wenig Speicherplatz auf der Festplatte
root_disabled: '{root} ist nicht verfügbar. Bitte überprüfen Sie Ihre Logdateien.'
move_item: Eintrag verschieben | {count} Einträge verschieben
url:
klipper_config: 'https://www.klipper3d.org/Config_Reference.html#%{hash}'
moonraker_config: 'https://moonraker.readthedocs.io/en/latest/configuration/#%{hash}'
Expand Down
2 changes: 1 addition & 1 deletion src/locales/en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ app:
upload_file: Uploading file | Uploading files
tooltip:
low_on_space: Low on disk space
move_item: Move item | Move {count} items
items_count: '{count} item | {count} items'
root_disabled: '{root} root is not available. Please check your logs.'
url:
klipper_config: 'https://www.klipper3d.org/Config_Reference.html#%{hash}'
Expand Down
1 change: 0 additions & 1 deletion src/locales/hu.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ app:
upload_file: Fájl feltöltése
tooltip:
low_on_space: Kevés a lemezterület
move_item: Elem mozgatása | {count} elem mozgatása
root_disabled: '{root} nem elérhető. Kérjük, ellenőrizd a naplókat.'
url:
klipper_config: 'https://www.klipper3d.org/Config_Reference.html#%{hash}'
Expand Down
1 change: 0 additions & 1 deletion src/locales/ja.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ app:
upload_file: ファイルをアップロードする|ファイルをアップロードする
tooltip:
low_on_space: ディスク容量が少なくなりました。
move_item: 'アイテムの移動| {count} 個のアイテムを移動'
root_disabled: '{root} rootは使用できません。ログを確認してください。'
url:
klipper_config: 'https://www.klipper3d.org/Config_Reference.html#%{hash}'
Expand Down
1 change: 0 additions & 1 deletion src/locales/pl.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ app:
aby je wgrać
tooltip:
low_on_space: Mało miejsca na dysku
move_item: Przenieś element | Przenieś {count} elementy
root_disabled: '{root} root jest niedostępny. Sprawdź logi.'
url:
klipper_config: https://www.klipper3d.org/Config_Reference.html#%{hash}
Expand Down
1 change: 0 additions & 1 deletion src/locales/pt.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ app:
duplicate_file: Duplicar ficheiro
tooltip:
low_on_space: Pouco espaço em disco
move_item: Mover item | Mover {count} itemes
general:
btn:
add: Adicionar
Expand Down
1 change: 0 additions & 1 deletion src/locales/ru.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ app:
upload_file: Загрузка файла | Загрузка файлов
tooltip:
low_on_space: Мало места на диске
move_item: Переместить элемент | Переместить {count}
root_disabled: Root недоступен. Проверьте файлы логов.
url:
klipper_config: 'https://www.klipper3d.org/Config_Reference.html#%{hash}'
Expand Down
1 change: 0 additions & 1 deletion src/locales/sl.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ app:
upload_file: Nalaganje datoteke | Nalaganje datotek
tooltip:
low_on_space: Na disku primanjkuje prostora
move_item: Premakni element | Premakni {count} elementov
root_disabled: '{root} root ni na voljo. Prosimo, preverite dnevnike.'
url:
klipper_config: 'https://www.klipper3d.org/Config_Reference.html#%{hash}'
Expand Down
1 change: 0 additions & 1 deletion src/locales/zh-CN.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ app:
upload_file: 上传文件
tooltip:
low_on_space: 磁盘空间不足
move_item: 移动项目|移动{count}个项目
root_disabled: '{root} G代码文件目录不可用,请首先连接打印机或者检查G代码存放目录的路径与读权限'
url:
klipper_config: 'https://www.klipper3d.org/zh/Config_Reference.html#%{hash}'
Expand Down
1 change: 0 additions & 1 deletion src/locales/zh-HK.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ app:
upload_file: 上傳文件
tooltip:
low_on_space: 磁盤空間不足
move_item: '移動項目 | 移動 {count} 項'
root_disabled: '{root} G代碼文件目錄不可用,請首先連接打印機或者檢查G代碼存放目錄的路徑與讀權限'
url:
klipper_config: 'https://www.klipper3d.org/zh-Hant/Config_Reference.html#%{hash}'
Expand Down
4 changes: 3 additions & 1 deletion src/scss/file-system.scss
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,11 @@
position: absolute;
top: -1000px;
right: 0;
width: 170px;
width: auto;
min-width: 170px;
height: 40px;
align-items: center;
padding: 0 16px 0 32px;
border-radius: 6px;
text-wrap: nowrap;
}
22 changes: 22 additions & 0 deletions src/util/file-data-transfer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Globals } from '@/globals'

export type FileDataTransferData = {
path: string,
items: string[]
}

export const hasFileDataTransferTypeInDataTransfer = (dataTransfer: DataTransfer, type: keyof typeof Globals.FILE_DATA_TRANSFER_TYPES) => {
return dataTransfer.types.includes(Globals.FILE_DATA_TRANSFER_TYPES[type])
}

export const setFileDataTransferDataInDataTransfer = (dataTransfer: DataTransfer, type: keyof typeof Globals.FILE_DATA_TRANSFER_TYPES, fileDataTransferData: FileDataTransferData) => {
dataTransfer.setData(Globals.FILE_DATA_TRANSFER_TYPES[type], JSON.stringify(fileDataTransferData))
}

export const getFileDataTransferDataFromDataTransfer = (dataTransfer: DataTransfer, type: keyof typeof Globals.FILE_DATA_TRANSFER_TYPES) => {
const data = dataTransfer.getData(Globals.FILE_DATA_TRANSFER_TYPES[type])

const fileDataTransferData: FileDataTransferData = JSON.parse(data)

return fileDataTransferData
}

0 comments on commit cf32644

Please sign in to comment.