Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add multi select for config files #790

Merged
merged 10 commits into from
May 11, 2022
20 changes: 14 additions & 6 deletions src/components/panels/GcodefilesPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -555,13 +555,13 @@ import {
mdiFolderPlus,
mdiFolderUpload,
mdiMagnify,
mdiPencil,
mdiPlay,
mdiPlaylistPlus,
mdiRefresh,
mdiRenameBox,
mdiUpload,
mdiVideo3d,
mdiPencil,
} from '@mdi/js'
import StartPrintDialog from '@/components/dialogs/StartPrintDialog.vue'

Expand Down Expand Up @@ -1331,11 +1331,19 @@ export default class GcodefilesPanel extends Mixins(BaseMixin) {

deleteSelectedFiles() {
this.selectedFiles.forEach((item: FileStateGcodefile) => {
this.$socket.emit(
'server.files.delete_file',
{ path: 'gcodes' + this.currentPath + '/' + item.filename },
{ action: 'files/getDeleteFile' }
)
if (item.isDirectory) {
this.$socket.emit(
'server.files.delete_directory',
{ path: 'gcodes' + this.currentPath + '/' + item.filename, force: true },
{ action: 'files/getDeleteDir' }
)
} else {
this.$socket.emit(
'server.files.delete_file',
{ path: 'gcodes' + this.currentPath + '/' + item.filename },
{ action: 'files/getDeleteFile' }
)
}
})

this.selectedFiles = []
Expand Down
99 changes: 92 additions & 7 deletions src/components/panels/Machine/ConfigFilesPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
v-for="button in filteredToolbarButtons"
:key="button.loadingName"
class="px-2 minwidth-0 ml-3"
:color="button.color"
:loading="button.loadingName !== null && loadings.includes(button.loadingName)"
@click="button.click">
<v-tooltip top>
Expand Down Expand Up @@ -91,6 +92,7 @@
</v-card-text>
<v-divider></v-divider>
<v-data-table
v-model="selectedFiles"
:items="files"
class="files-table"
:headers="headers"
Expand All @@ -105,7 +107,8 @@
itemsPerPageOptions: [10, 25, 50, 100, -1],
}"
mobile-breakpoint="0"
item-key="name">
item-key="filename"
show-select>
<template #no-data>
<div class="text-center">{{ $t('Machine.ConfigFilesPanel.Empty') }}</div>
</template>
Expand All @@ -117,14 +120,17 @@
@dragover="dragOverFilelist($event, { isDirectory: true, filename: '..' })"
@dragleave="dragLeaveFilelist"
@drop.prevent.stop="dragDropFilelist($event, { isDirectory: true, filename: '..' })">
<td class="pr-0 text-center" style="width: 32px">
<td class="file-list__select-td pr-0">
<v-simple-checkbox v-ripple disabled class="pa-0 mr-0"></v-simple-checkbox>
</td>
<td class="px-0 text-center" style="width: 32px">
<v-icon>{{ mdiFolderUpload }}</v-icon>
</td>
<td class=" " colspan="4">..</td>
</tr>
</template>

<template #item="{ index, item }">
<template #item="{ index, item, isSelected, select }">
<tr
:key="`${index} ${item.filename}`"
v-longpress:600="(e) => showContextMenu(e, item)"
Expand All @@ -138,7 +144,14 @@
@dragover="dragOverFilelist($event, item)"
@dragleave="dragLeaveFilelist"
@drop.prevent.stop="dragDropFilelist($event, item)">
<td class="pr-0 text-center" style="width: 32px">
<td class="file-list__select-td pr-0">
<v-simple-checkbox
v-ripple
:value="isSelected"
class="pa-0 mr-0"
@click.stop="select(!isSelected)"></v-simple-checkbox>
</td>
<td class="px-0 text-center" style="width: 32px">
<v-icon v-if="item.isDirectory">{{ mdiFolder }}</v-icon>
<v-icon v-if="!item.isDirectory">{{ mdiFile }}</v-icon>
</td>
Expand Down Expand Up @@ -375,6 +388,32 @@
</v-card-actions>
</panel>
</v-dialog>
<v-dialog v-model="deleteSelectedDialog" max-width="400">
<panel
:title="$t('Machine.ConfigFilesPanel.Delete')"
card-class="gcode-files-delete-selected-dialog"
:margin-bottom="false">
<template #buttons>
<v-btn icon tile @click="deleteSelectedDialog = false">
<v-icon>{{ mdiCloseThick }}</v-icon>
</v-btn>
</template>
<v-card-text>
<p class="mb-0">
{{ $t('Machine.ConfigFilesPanel.DeleteSelectedQuestion', { count: selectedFiles.length }) }}
</p>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="" text @click="deleteSelectedDialog = false">
{{ $t('Machine.ConfigFilesPanel.Cancel') }}
</v-btn>
<v-btn color="error" text @click="deleteSelectedFiles">
{{ $t('Machine.ConfigFilesPanel.Delete') }}
</v-btn>
</v-card-actions>
</panel>
</v-dialog>
<v-snackbar v-model="uploadSnackbar.status" :timeout="-1" :value="true" fixed right bottom dark>
<span v-if="uploadSnackbar.max > 1" class="mr-1">
({{ uploadSnackbar.number }}/{{ uploadSnackbar.max }})
Expand All @@ -397,7 +436,7 @@
import { Component, Mixins } from 'vue-property-decorator'
import BaseMixin from '@/components/mixins/base'
import { formatDate, formatFilesize, sortFiles } from '@/plugins/helpers'
import { FileStateFile } from '@/store/files/types'
import { FileStateFile, FileStateGcodefile } from '@/store/files/types'
import axios from 'axios'
import Panel from '@/components/ui/Panel.vue'
import { hiddenRootDirectories } from '@/store/variables'
Expand Down Expand Up @@ -577,6 +616,8 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin) {
},
}

private deleteSelectedDialog = false

get blockFileUpload() {
return this.$store.state.gui.view.blockFileUpload ?? false
}
Expand All @@ -587,12 +628,24 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin) {

get toolbarButtons() {
return [
{
text: this.$t('Machine.ConfigFilesPanel.Delete'),
color: 'error',
icon: mdiDelete,
loadingName: null,
onlyWriteable: true,
condition: this.selectedFiles.length > 0,
click: () => {
this.deleteSelectedDialog = true
},
},
{
text: this.$t('Machine.ConfigFilesPanel.UploadFile'),
color: 'grey darken-3',
icon: mdiFileUpload,
loadingName: null,
onlyWriteable: true,
condition: true,
click: this.uploadFileButton,
},
{
Expand All @@ -601,6 +654,7 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin) {
icon: mdiFilePlus,
loadingName: null,
onlyWriteable: true,
condition: true,
click: this.createFile,
},
{
Expand All @@ -609,6 +663,7 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin) {
icon: mdiFolderPlus,
loadingName: null,
onlyWriteable: true,
condition: true,
click: this.createDirecotry,
},
{
Expand All @@ -617,9 +672,10 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin) {
icon: mdiRefresh,
loadingName: null,
onlyWriteable: false,
condition: true,
click: this.refreshFileList,
},
]
].filter((rule: any) => rule.condition)
}

get filteredToolbarButtons() {
Expand Down Expand Up @@ -664,13 +720,21 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin) {

get headers() {
return [
{ text: '', value: '' },
{ text: '', value: '', sortable: false },
{ text: this.$t('Machine.ConfigFilesPanel.Name'), value: 'filename' },
{ text: this.$t('Machine.ConfigFilesPanel.Filesize'), value: 'size', align: 'right' },
{ text: this.$t('Machine.ConfigFilesPanel.LastModified'), value: 'modified', align: 'right' },
]
}

get selectedFiles() {
return this.$store.state.gui.view.configfiles.selectedFiles ?? []
}

set selectedFiles(newVal) {
this.$store.dispatch('gui/saveSettingWithoutUpload', { name: 'view.configfiles.selectedFiles', value: newVal })
}

get countPerPage() {
return this.$store.state.gui.view.configfiles.countPerPage
}
Expand Down Expand Up @@ -932,6 +996,27 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin) {
)
}

deleteSelectedFiles() {
this.selectedFiles.forEach((item: FileStateGcodefile) => {
if (item.isDirectory) {
this.$socket.emit(
'server.files.delete_directory',
{ path: this.absolutePath + '/' + item.filename, force: true },
{ action: 'files/getDeleteDir' }
)
} else {
this.$socket.emit(
'server.files.delete_file',
{ path: this.absolutePath + '/' + item.filename },
{ action: 'files/getDeleteFile' }
)
}
})

this.selectedFiles = []
this.deleteSelectedDialog = false
}

uploadFileButton() {
this.$refs.fileUpload.click()
}
Expand Down
3 changes: 2 additions & 1 deletion src/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,8 @@
"CurrentPath": "Aktueller Pfad",
"Delete": "Löschen",
"DeleteDirectory": "Verzeichnis löschen",
"DeleteDirectoryQuestion": "Wills du wirklich das Verzeichnis \"{name}\" mit seinem gesamten Inhalt löschen?",
"DeleteDirectoryQuestion": "Verzeichnis \"{name}\" und den gesamten Inhalt löschen?",
"DeleteSelectedQuestion": "{count} ausgewählte Elemente löschen?",
"Download": "Herunterladen",
"EditFile": "Bearbeite Datei",
"Empty": "Leer",
Expand Down
3 changes: 2 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,8 @@
"CurrentPath": "Current path",
"Delete": "Delete",
"DeleteDirectory": "Delete Directory",
"DeleteDirectoryQuestion": "Do you really want to delete the \"{name}\" directory with all its contents?",
"DeleteDirectoryQuestion": "Delete directory \"{name}\" and all its contents?",
"DeleteSelectedQuestion": "Delete {count} selected elements?",
"Download": "Download",
"EditFile": "Edit file",
"Empty": "Empty",
Expand Down
1 change: 1 addition & 0 deletions src/store/gui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ export const getDefaultState = (): GuiState => {
hideBackupFiles: false,
currentPath: '',
rootPath: 'config',
selectedFiles: [],
},
gcodefiles: {
countPerPage: 10,
Expand Down
3 changes: 2 additions & 1 deletion src/store/gui/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { GuiPresetsState } from '@/store/gui/presets/types'
import { GuiRemoteprintersState } from '@/store/gui/remoteprinters/types'
import { ServerHistoryStateJob } from '@/store/server/history/types'
import { GuiNotificationState } from '@/store/gui/notifications/types'
import { FileStateGcodefile } from '@/store/files/types'
import { FileStateFile, FileStateGcodefile } from '@/store/files/types'

export interface GuiState {
general: {
Expand Down Expand Up @@ -112,6 +112,7 @@ export interface GuiState {
hideBackupFiles: boolean
currentPath: string
rootPath: string
selectedFiles: FileStateFile[]
}
gcodefiles: {
countPerPage: number
Expand Down