feat: global fullscreen fileupload (#777)
* feat: init upload from global gcode file upload Signed-off-by: Stefan Dej <meteyou@gmail.com> * feat: global fileupload & fileupload status snackbar Signed-off-by: Stefan Dej <meteyou@gmail.com> * feat: implement cancel upload Signed-off-by: Stefan Dej <meteyou@gmail.com> * chore: update config file upload to global file upload Signed-off-by: Stefan Dej <meteyou@gmail.com> * chore: fix eslint issue Signed-off-by: Stefan Dej <meteyou@gmail.com> * lcoale: add fullscreenUpload to i18n Signed-off-by: Stefan Dej <meteyou@gmail.com> * chore: fix toast position with upload snackbar Signed-off-by: Stefan Dej <meteyou@gmail.com> * chore: fix IDE code analyzer issues Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix: app favicon draw function Signed-off-by: Stefan Dej <meteyou@gmail.com> * style: fix favicon source code Signed-off-by: Stefan Dej <meteyou@gmail.com> * chore: fix type in TheFullscreenUpload.vue Signed-off-by: Stefan Dej <meteyou@gmail.com> * chore: fix type in TheFullscreenUpload.vue Signed-off-by: Stefan Dej <meteyou@gmail.com> * fix: fullscreen upload dont work in firefox Signed-off-by: Stefan Dej <meteyou@gmail.com> * feat: add icon to TheFullscreenUpload.vue Signed-off-by: Stefan Dej <meteyou@gmail.com> * locale(en): remove blank line Signed-off-by: Stefan Dej <meteyou@gmail.com> * locale(en): add missing translation Signed-off-by: Stefan Dej <meteyou@gmail.com> * locale(de): add DE translations Signed-off-by: Stefan Dej <meteyou@gmail.com>
This commit is contained in:
parent
c94e70f876
commit
654785fedf
36
src/App.vue
36
src/App.vue
@ -16,7 +16,9 @@
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
/*noinspection CssUnusedSymbol*/
|
||||
.v-btn:not(.v-btn--outlined).primary {
|
||||
/*noinspection CssUnresolvedCustomProperty*/
|
||||
color: var(--v-btn-text-primary);
|
||||
}
|
||||
|
||||
@ -42,6 +44,8 @@
|
||||
<the-update-dialog></the-update-dialog>
|
||||
<the-editor></the-editor>
|
||||
<the-timelapse-rendering-snackbar></the-timelapse-rendering-snackbar>
|
||||
<the-fullscreen-upload></the-fullscreen-upload>
|
||||
<the-upload-snackbar></the-upload-snackbar>
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
@ -57,6 +61,8 @@ import TheSelectPrinterDialog from '@/components/TheSelectPrinterDialog.vue'
|
||||
import TheEditor from '@/components/TheEditor.vue'
|
||||
import { panelToolbarHeight, topbarHeight, navigationItemHeight } from '@/store/variables'
|
||||
import TheTimelapseRenderingSnackbar from '@/components/TheTimelapseRenderingSnackbar.vue'
|
||||
import TheFullscreenUpload from '@/components/TheFullscreenUpload.vue'
|
||||
import TheUploadSnackbar from '@/components/TheUploadSnackbar.vue'
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
@ -67,6 +73,8 @@ import TheTimelapseRenderingSnackbar from '@/components/TheTimelapseRenderingSna
|
||||
TheUpdateDialog,
|
||||
TheTopbar,
|
||||
TheSidebar,
|
||||
TheFullscreenUpload,
|
||||
TheUploadSnackbar,
|
||||
},
|
||||
metaInfo() {
|
||||
const title = this.$store.getters['getTitle']
|
||||
@ -76,10 +84,6 @@ import TheTimelapseRenderingSnackbar from '@/components/TheTimelapseRenderingSna
|
||||
},
|
||||
})
|
||||
export default class App extends Mixins(BaseMixin) {
|
||||
panelToolbarHeight = panelToolbarHeight
|
||||
topbarHeight = topbarHeight
|
||||
navigationItemHeight = navigationItemHeight
|
||||
|
||||
get title(): string {
|
||||
return this.$store.getters['getTitle']
|
||||
}
|
||||
@ -242,21 +246,15 @@ export default class App extends Mixins(BaseMixin) {
|
||||
} else {
|
||||
const favicon =
|
||||
'data:image/svg+xml;base64,' +
|
||||
btoa(
|
||||
'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 599.38 523.11" xml:space="preserve">' +
|
||||
'<g>' +
|
||||
'<path style="fill:' +
|
||||
this.logoColor +
|
||||
';" d="M382.29,142.98L132.98,522.82L0,522.68L344.3,0l0,0C352.18,49.06,365.2,97.68,382.29,142.98"/>' +
|
||||
'<path style="fill:' +
|
||||
this.logoColor +
|
||||
';" d="M413.28,213.54L208.5,522.92l132.94,0.19l135.03-206.33l0,0C452.69,284.29,431.53,249.77,413.28,213.54 L413.28,213.54"/>' +
|
||||
'<path style="fill:' +
|
||||
this.logoColor +
|
||||
';" d="M599.38,447.69l-49.25,75.42L417,522.82l101.6-153.67l0,0C543.48,397.35,570.49,423.61,599.38,447.69 L599.38,447.69z"/>' +
|
||||
'</g>' +
|
||||
'</svg>'
|
||||
)
|
||||
window.btoa(`
|
||||
<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 599.38 523.11" xml:space="preserve">
|
||||
<g>
|
||||
<path style="fill:${this.logoColor};" d="M382.29,142.98L132.98,522.82L0,522.68L344.3,0l0,0C352.18,49.06,365.2,97.68,382.29,142.98"/>
|
||||
<path style="fill:${this.logoColor};" d="M413.28,213.54L208.5,522.92l132.94,0.19l135.03-206.33l0,0C452.69,284.29,431.53,249.77,413.28,213.54 L413.28,213.54"/>
|
||||
<path style="fill:${this.logoColor};" d="M599.38,447.69l-49.25,75.42L417,522.82l101.6-153.67l0,0C543.48,397.35,570.49,423.61,599.38,447.69 L599.38,447.69z"/>
|
||||
</g>
|
||||
</svg>
|
||||
`)
|
||||
|
||||
favicon16.href = favicon
|
||||
favicon32.href = favicon
|
||||
|
@ -13,3 +13,7 @@
|
||||
.v-toast__text {
|
||||
font-family: 'Roboto', sans-serif;
|
||||
}
|
||||
|
||||
.fullscreenUpload--active .v-toast--bottom {
|
||||
bottom: 88px;
|
||||
}
|
||||
|
@ -52,6 +52,10 @@
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
|
||||
.v-toast {
|
||||
padding: 8px !important;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
|
153
src/components/TheFullscreenUpload.vue
Normal file
153
src/components/TheFullscreenUpload.vue
Normal file
@ -0,0 +1,153 @@
|
||||
<template>
|
||||
<div class="d-flex justify-center flex-column fullscreen-upload__dragzone" :class="dropzoneClasses" @drop="onDrop">
|
||||
<v-icon class="fullscreen-upload__icon">{{ mdiTrayArrowDown }}</v-icon>
|
||||
<div class="textnode">{{ $t('FullscreenUpload.DropFilesToUploadFiles') }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Mixins } from 'vue-property-decorator'
|
||||
import BaseMixin from '@/components/mixins/base'
|
||||
import Component from 'vue-class-component'
|
||||
import { validGcodeExtensions } from '@/store/variables'
|
||||
import { mdiTrayArrowDown } from '@mdi/js'
|
||||
|
||||
@Component
|
||||
export default class TheFullscreenUpload extends Mixins(BaseMixin) {
|
||||
mdiTrayArrowDown = mdiTrayArrowDown
|
||||
private visible = false
|
||||
|
||||
get dropzoneClasses() {
|
||||
return {
|
||||
'fullscreen-upload__dragzone--visible': this.visible,
|
||||
}
|
||||
}
|
||||
|
||||
get currentRoute() {
|
||||
return this.$route.path ?? ''
|
||||
}
|
||||
|
||||
get currentPathGcodes() {
|
||||
return this.$store.state.gui.view.gcodefiles.currentPath ?? ''
|
||||
}
|
||||
|
||||
get currentPathConfig() {
|
||||
return this.$store.state.gui.view.configfiles.currentPath ?? ''
|
||||
}
|
||||
|
||||
mounted() {
|
||||
window.addEventListener('dragenter', this.onDragOverWindow)
|
||||
window.addEventListener('dragover', this.onDragOverWindow)
|
||||
window.addEventListener('dragleave', this.onDragLeaveWindow)
|
||||
}
|
||||
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('dragenter', this.onDragOverWindow)
|
||||
window.removeEventListener('dragover', this.onDragOverWindow)
|
||||
window.removeEventListener('dragleave', this.onDragLeaveWindow)
|
||||
}
|
||||
|
||||
showDropZone() {
|
||||
this.visible = true
|
||||
}
|
||||
|
||||
hideDropZone() {
|
||||
this.visible = false
|
||||
}
|
||||
|
||||
onDragOverWindow(e: any) {
|
||||
const types = e.dataTransfer?.types ?? []
|
||||
if (!types.includes('Files')) return
|
||||
|
||||
e.preventDefault()
|
||||
if (this.visible) return
|
||||
|
||||
this.showDropZone()
|
||||
}
|
||||
|
||||
onDragLeaveWindow(e: any) {
|
||||
e.preventDefault()
|
||||
this.hideDropZone()
|
||||
}
|
||||
|
||||
async onDrop(e: any) {
|
||||
e.preventDefault()
|
||||
this.hideDropZone()
|
||||
|
||||
if (e.dataTransfer?.files?.length) {
|
||||
const files = [...e.dataTransfer.files]
|
||||
|
||||
await this.$store.dispatch('socket/addLoading', { name: 'gcodeUpload' })
|
||||
await this.$store.dispatch('files/uploadSetCurrentNumber', 0)
|
||||
await this.$store.dispatch('files/uploadSetMaxNumber', files.length)
|
||||
|
||||
for (const file of files) {
|
||||
const extensionPos = file.name.lastIndexOf('.')
|
||||
const extension = file.name.slice(extensionPos)
|
||||
const isGcode = validGcodeExtensions.includes(extension)
|
||||
|
||||
let path = ''
|
||||
if (this.currentRoute === '/files' && isGcode) path = this.currentPathGcodes
|
||||
else if (this.currentRoute === '/config' && !isGcode) path = this.currentPathConfig
|
||||
|
||||
const root = isGcode ? 'gcodes' : 'config'
|
||||
await this.$store.dispatch('files/uploadIncrementCurrentNumber')
|
||||
const result = await this.$store.dispatch('files/uploadFile', { file, path, root })
|
||||
|
||||
if (result !== false)
|
||||
this.$toast.success(this.$t('Files.SuccessfullyUploaded', { filename: result }).toString())
|
||||
}
|
||||
|
||||
await this.$store.dispatch('socket/removeLoading', { name: 'gcodeUpload' })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.fullscreen-upload__dragzone {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 99999;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: visibility 200ms, opacity 200ms;
|
||||
font: bold 42px Oswald, DejaVu Sans, Tahoma, sans-serif;
|
||||
}
|
||||
|
||||
/*noinspection CssUnusedSymbol*/
|
||||
.fullscreen-upload__dragzone--visible {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
/*noinspection CssUnusedSymbol*/
|
||||
.fullscreen-upload__dragzone:before {
|
||||
display: block;
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
top: 1em;
|
||||
right: 1em;
|
||||
bottom: 1em;
|
||||
left: 1em;
|
||||
border: 3px dashed white;
|
||||
border-radius: 1em;
|
||||
}
|
||||
|
||||
/*noinspection CssUnusedSymbol*/
|
||||
.fullscreen-upload__icon .v-icon__svg {
|
||||
width: 250px;
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
.fullscreen-upload__dragzone .textnode {
|
||||
text-align: center;
|
||||
transition: font-size 175ms;
|
||||
font-size: 82px;
|
||||
}
|
||||
</style>
|
74
src/components/TheUploadSnackbar.vue
Normal file
74
src/components/TheUploadSnackbar.vue
Normal file
@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<v-snackbar v-if="show" :timeout="-1" :value="true" fixed right bottom dark>
|
||||
<span v-if="maxNumber > 1" class="mr-1">({{ currentNumber }}/{{ maxNumber }})</span>
|
||||
<strong>{{ $t('Files.Uploading') + ' ' + filename }}</strong>
|
||||
<br />
|
||||
{{ percent }} % @ {{ speed }}/s
|
||||
<br />
|
||||
<v-progress-linear class="mt-2" :value="percent"></v-progress-linear>
|
||||
<template #action="{ attrs }">
|
||||
<v-btn color="red" text v-bind="attrs" style="min-width: auto" @click="cancelUpload">
|
||||
<v-icon class="0">{{ mdiClose }}</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-snackbar>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Component from 'vue-class-component'
|
||||
import { Mixins, Watch } from 'vue-property-decorator'
|
||||
import BaseMixin from '@/components/mixins/base'
|
||||
import { mdiClose } from '@mdi/js'
|
||||
import { formatFilesize } from '@/plugins/helpers'
|
||||
|
||||
@Component({
|
||||
components: {},
|
||||
})
|
||||
export default class TheUploadSnackbar extends Mixins(BaseMixin) {
|
||||
mdiClose = mdiClose
|
||||
formatFilesize = formatFilesize
|
||||
|
||||
get show() {
|
||||
return this.$store.state.files.upload.show ?? false
|
||||
}
|
||||
|
||||
get cancelTokenSource() {
|
||||
return this.$store.state.files.upload.cancelTokenSource
|
||||
}
|
||||
|
||||
get filename() {
|
||||
return this.$store.state.files.upload.filename ?? ''
|
||||
}
|
||||
|
||||
get currentNumber() {
|
||||
return this.$store.state.files.upload.currentNumber ?? 0
|
||||
}
|
||||
|
||||
get maxNumber() {
|
||||
return this.$store.state.files.upload.maxNumber ?? 0
|
||||
}
|
||||
|
||||
get speed() {
|
||||
return formatFilesize(Math.round(this.$store.state.files.upload.speed ?? 0))
|
||||
}
|
||||
|
||||
get percent() {
|
||||
return Math.round(this.$store.state.files.upload.percent ?? 0)
|
||||
}
|
||||
|
||||
cancelUpload() {
|
||||
this.cancelTokenSource?.cancel()
|
||||
this.$store.dispatch('files/uploadSetShow', false)
|
||||
this.$store.dispatch('socket/removeLoading', { name: 'gcodeUpload' })
|
||||
this.$store.dispatch('socket/removeLoading', { name: 'configFileUpload' })
|
||||
}
|
||||
|
||||
@Watch('show')
|
||||
showChanged(newVal: boolean) {
|
||||
const body = document.getElementsByTagName('body')[0]
|
||||
|
||||
if (newVal) body.classList.add('fullscreenUpload--active')
|
||||
else body.classList.remove('fullscreenUpload--active')
|
||||
}
|
||||
}
|
||||
</script>
|
@ -7,10 +7,6 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.fileupload-card {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.file-list--select-td {
|
||||
width: 20px;
|
||||
}
|
||||
@ -19,36 +15,6 @@
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
|
||||
.file-list__dragzone {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 100%;
|
||||
z-index: 9999999999;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
transition: visibility 175ms, opacity 175ms;
|
||||
font: bold 42px Oswald, DejaVu Sans, Tahoma, sans-serif;
|
||||
}
|
||||
|
||||
.file-list__dragzone:before {
|
||||
display: block;
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 15px;
|
||||
bottom: 15px;
|
||||
left: 15px;
|
||||
border: 3px dashed white;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.file-list__dragzone .textnode {
|
||||
text-align: center;
|
||||
transition: font-size 175ms;
|
||||
}
|
||||
|
||||
.v-chip.minimum-chip {
|
||||
padding: 0;
|
||||
min-width: 24px;
|
||||
@ -65,7 +31,7 @@
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<div @dragover="dragOverUpload" @dragleave="dragLeaveUpload" @drop.prevent.stop="dragDropUpload">
|
||||
<div>
|
||||
<panel :title="$t('Files.GCodeFiles')" :icon="mdiFileDocumentMultipleOutline" card-class="gcode-files-panel">
|
||||
<v-card-text>
|
||||
<v-row>
|
||||
@ -373,27 +339,7 @@
|
||||
</tr>
|
||||
</template>
|
||||
</v-data-table>
|
||||
<div
|
||||
class="file-list__dragzone d-flex justify-center flex-column"
|
||||
:style="'visibility: ' + dropzone.visibility + '; opacity: ' + dropzone.hidden">
|
||||
<div class="textnode">{{ $t('Files.DropFilesToAddGcode') }}</div>
|
||||
</div>
|
||||
</panel>
|
||||
<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 }})
|
||||
</span>
|
||||
<strong>{{ $t('Files.Uploading') + ' ' + uploadSnackbar.filename }}</strong>
|
||||
<br />
|
||||
{{ Math.round(uploadSnackbar.percent) }} % @ {{ formatFilesize(Math.round(uploadSnackbar.speed)) }}/s
|
||||
<br />
|
||||
<v-progress-linear class="mt-2" :value="uploadSnackbar.percent"></v-progress-linear>
|
||||
<template #action="{ attrs }">
|
||||
<v-btn color="red" text v-bind="attrs" style="min-width: auto" @click="cancelUpload">
|
||||
<v-icon class="0">{{ mdiClose }}</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
</v-snackbar>
|
||||
<v-dialog v-model="dialogPrintFile.show" :max-width="dialogPrintFile.item.big_thumbnail_width">
|
||||
<v-card>
|
||||
<v-img
|
||||
@ -608,7 +554,6 @@
|
||||
<script lang="ts">
|
||||
import { Component, Mixins, Watch } from 'vue-property-decorator'
|
||||
import BaseMixin from '@/components/mixins/base'
|
||||
import axios from 'axios'
|
||||
import { validGcodeExtensions } from '@/store/variables'
|
||||
import { formatFilesize, formatDate, sortFiles, formatPrintTime } from '@/plugins/helpers'
|
||||
import { FileStateFile, FileStateGcodefile } from '@/store/files/types'
|
||||
@ -641,7 +586,6 @@ import {
|
||||
} from '@mdi/js'
|
||||
|
||||
interface draggingFile {
|
||||
status: boolean
|
||||
item: FileStateGcodefile
|
||||
}
|
||||
|
||||
@ -740,7 +684,6 @@ export default class GcodefilesPanel extends Mixins(BaseMixin) {
|
||||
opacity: 0,
|
||||
}
|
||||
private draggingFile: draggingFile = {
|
||||
status: false,
|
||||
item: {
|
||||
isDirectory: false,
|
||||
filename: '',
|
||||
@ -1130,171 +1073,61 @@ export default class GcodefilesPanel extends Mixins(BaseMixin) {
|
||||
return this.$store.getters['server/history/getPrintStatusIconColor'](status)
|
||||
}
|
||||
|
||||
dragOverUpload(e: Event) {
|
||||
if (!this.draggingFile.status) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
|
||||
this.dropzone.visibility = 'visible'
|
||||
this.dropzone.opacity = 1
|
||||
}
|
||||
}
|
||||
|
||||
dragLeaveUpload(e: Event) {
|
||||
if (!this.draggingFile.status) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
|
||||
this.dropzone.visibility = 'hidden'
|
||||
this.dropzone.opacity = 0
|
||||
}
|
||||
}
|
||||
|
||||
async dragDropUpload(e: any) {
|
||||
if (!this.draggingFile.status) {
|
||||
e.preventDefault()
|
||||
|
||||
this.dropzone.visibility = 'hidden'
|
||||
this.dropzone.opacity = 0
|
||||
|
||||
if (e.dataTransfer.files.length) {
|
||||
const files = [...e.dataTransfer.files].filter((file: File) => {
|
||||
const format = file.name.slice(file.name.lastIndexOf('.'))
|
||||
|
||||
if (!validGcodeExtensions.includes(format)) {
|
||||
this.$toast.error(this.$t('Files.WrongFileUploaded', { filename: file.name }).toString())
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
this.$store.dispatch('socket/addLoading', { name: 'gcodeUpload' })
|
||||
let successFiles = []
|
||||
this.uploadSnackbar.number = 0
|
||||
this.uploadSnackbar.max = files.length
|
||||
for (const file of files) {
|
||||
this.uploadSnackbar.number++
|
||||
const result = await this.doUploadFile(file)
|
||||
successFiles.push(result)
|
||||
}
|
||||
|
||||
this.$store.dispatch('socket/removeLoading', { name: 'gcodeUpload' })
|
||||
for (const file of successFiles) {
|
||||
this.$toast.success(this.$t('Files.SuccessfullyUploaded', { filename: file }).toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doUploadFile(file: File) {
|
||||
let formData = new FormData()
|
||||
let filename = file.name
|
||||
|
||||
this.uploadSnackbar.filename = filename
|
||||
this.uploadSnackbar.status = true
|
||||
this.uploadSnackbar.percent = 0
|
||||
this.uploadSnackbar.speed = 0
|
||||
this.uploadSnackbar.lastProgress.loaded = 0
|
||||
this.uploadSnackbar.lastProgress.time = 0
|
||||
|
||||
formData.append('file', file, this.currentPath + '/' + filename)
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.uploadSnackbar.cancelTokenSource = axios.CancelToken.source()
|
||||
axios
|
||||
.post(this.apiUrl + '/server/files/upload', formData, {
|
||||
cancelToken: this.uploadSnackbar.cancelTokenSource.token,
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
onUploadProgress: (progressEvent: any) => {
|
||||
this.uploadSnackbar.percent = (progressEvent.loaded * 100) / progressEvent.total
|
||||
if (this.uploadSnackbar.lastProgress.time) {
|
||||
const time = progressEvent.timeStamp - this.uploadSnackbar.lastProgress.time
|
||||
const data = progressEvent.loaded - this.uploadSnackbar.lastProgress.loaded
|
||||
|
||||
if (time) this.uploadSnackbar.speed = data / (time / 1000)
|
||||
}
|
||||
|
||||
this.uploadSnackbar.lastProgress.time = progressEvent.timeStamp
|
||||
this.uploadSnackbar.lastProgress.loaded = progressEvent.loaded
|
||||
this.uploadSnackbar.total = progressEvent.total
|
||||
},
|
||||
})
|
||||
.then((result: any) => {
|
||||
const filename = result.data.item.path.slice(result.data.item.path.indexOf('/') + 1)
|
||||
this.uploadSnackbar.status = false
|
||||
resolve(filename)
|
||||
})
|
||||
.catch(() => {
|
||||
this.uploadSnackbar.status = false
|
||||
this.$store.dispatch('socket/removeLoading', { name: 'gcodeUpload' })
|
||||
this.$toast.error('Cannot upload the file!')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
dragOverFilelist(e: any, row: any) {
|
||||
if (this.draggingFile.status) {
|
||||
e.preventDefault()
|
||||
//e.stopPropagation()
|
||||
e.preventDefault()
|
||||
|
||||
if (row.isDirectory) {
|
||||
e.target.parentElement.style.backgroundColor = '#43A04720'
|
||||
}
|
||||
}
|
||||
if (row.isDirectory) e.target.parentElement.style.backgroundColor = '#43A04720'
|
||||
}
|
||||
|
||||
dragLeaveFilelist(e: any) {
|
||||
if (this.draggingFile.status) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
|
||||
e.target.parentElement.style.backgroundColor = 'transparent'
|
||||
}
|
||||
e.target.parentElement.style.backgroundColor = 'transparent'
|
||||
}
|
||||
|
||||
async dragDropFilelist(e: any, row: any) {
|
||||
if (this.draggingFile.status) {
|
||||
e.preventDefault()
|
||||
e.target.parentElement.style.backgroundColor = 'transparent'
|
||||
e.preventDefault()
|
||||
e.target.parentElement.style.backgroundColor = 'transparent'
|
||||
|
||||
let dest = ''
|
||||
if (row.filename === '..') {
|
||||
dest =
|
||||
this.currentPath.substring(0, this.currentPath.lastIndexOf('/') + 1) +
|
||||
this.draggingFile.item.filename
|
||||
} else dest = this.currentPath + '/' + row.filename + '/' + this.draggingFile.item.filename
|
||||
let dest = ''
|
||||
if (row.filename === '..') {
|
||||
dest =
|
||||
this.currentPath.substring(0, this.currentPath.lastIndexOf('/') + 1) + this.draggingFile.item.filename
|
||||
} else dest = this.currentPath + '/' + row.filename + '/' + this.draggingFile.item.filename
|
||||
|
||||
this.$socket.emit(
|
||||
'server.files.move',
|
||||
{
|
||||
source: 'gcodes' + this.currentPath + '/' + this.draggingFile.item.filename,
|
||||
dest: 'gcodes' + dest,
|
||||
},
|
||||
{ action: 'files/getMove' }
|
||||
)
|
||||
}
|
||||
this.$socket.emit(
|
||||
'server.files.move',
|
||||
{
|
||||
source: 'gcodes' + this.currentPath + '/' + this.draggingFile.item.filename,
|
||||
dest: 'gcodes' + dest,
|
||||
},
|
||||
{ action: 'files/getMove' }
|
||||
)
|
||||
}
|
||||
|
||||
async uploadFile() {
|
||||
if (this.$refs.fileUpload.files?.length) {
|
||||
this.$store.dispatch('socket/addLoading', { name: 'gcodeUpload' })
|
||||
let successFiles = []
|
||||
this.uploadSnackbar.number = 0
|
||||
this.uploadSnackbar.max = this.$refs.fileUpload.files.length
|
||||
for (const file of this.$refs.fileUpload.files) {
|
||||
this.uploadSnackbar.number++
|
||||
const result = await this.doUploadFile(file)
|
||||
successFiles.push(result)
|
||||
}
|
||||
|
||||
this.$store.dispatch('socket/removeLoading', { name: 'gcodeUpload' })
|
||||
for (const file of successFiles) {
|
||||
this.$toast.success(this.$t('Files.SuccessfullyUploaded', { filename: file }).toString())
|
||||
}
|
||||
|
||||
const files = [...this.$refs.fileUpload.files]
|
||||
this.$refs.fileUpload.value = ''
|
||||
|
||||
await this.$store.dispatch('socket/addLoading', { name: 'gcodeUpload' })
|
||||
await this.$store.dispatch('files/uploadSetCurrentNumber', 0)
|
||||
await this.$store.dispatch('files/uploadSetMaxNumber', this.$refs.fileUpload.files.length)
|
||||
for (const file of files) {
|
||||
await this.$store.dispatch('files/uploadIncrementCurrentNumber')
|
||||
const path = this.currentPath.slice(0, 1) === '/' ? this.currentPath.slice(1) : this.currentPath
|
||||
const result = await this.$store.dispatch('files/uploadFile', {
|
||||
file,
|
||||
path,
|
||||
root: 'gcodes',
|
||||
})
|
||||
|
||||
if (result !== false)
|
||||
this.$toast.success(this.$t('Files.SuccessfullyUploaded', { filename: result }).toString())
|
||||
}
|
||||
|
||||
await this.$store.dispatch('socket/removeLoading', { name: 'gcodeUpload' })
|
||||
}
|
||||
}
|
||||
|
||||
@ -1385,12 +1218,6 @@ export default class GcodefilesPanel extends Mixins(BaseMixin) {
|
||||
this.$store.dispatch('gui/setGcodefilesMetadata', { name: name, value: value })
|
||||
}
|
||||
|
||||
cancelUpload() {
|
||||
this.uploadSnackbar.cancelTokenSource.cancel()
|
||||
this.uploadSnackbar.status = false
|
||||
this.$refs.fileUpload.value = ''
|
||||
}
|
||||
|
||||
showContextMenu(e: any, item: FileStateFile) {
|
||||
if (!this.contextMenu.shown) {
|
||||
e?.preventDefault()
|
||||
@ -1521,13 +1348,11 @@ export default class GcodefilesPanel extends Mixins(BaseMixin) {
|
||||
|
||||
dragFile(e: Event, item: FileStateGcodefile) {
|
||||
e.preventDefault()
|
||||
this.draggingFile.status = true
|
||||
this.draggingFile.item = item
|
||||
}
|
||||
|
||||
dragendFile(e: Event) {
|
||||
e.preventDefault()
|
||||
this.draggingFile.status = false
|
||||
this.draggingFile.item = {
|
||||
isDirectory: false,
|
||||
filename: '',
|
||||
|
@ -11,12 +11,13 @@
|
||||
<v-col class="col-12 col-lg pr-lg-0">
|
||||
<v-select
|
||||
v-model="root"
|
||||
class="machine-configfiles-panel__root-select"
|
||||
:items="registeredDirectories"
|
||||
:label="$t('Machine.ConfigFilesPanel.Root')"
|
||||
outlined
|
||||
hide-details
|
||||
dense
|
||||
attach
|
||||
attach=".machine-configfiles-panel__root-select"
|
||||
@change="changeRoot"></v-select>
|
||||
</v-col>
|
||||
<v-col class="col col-lg-auto pl-lg-0 text-right">
|
||||
@ -34,10 +35,10 @@
|
||||
<span>{{ button.text }}</span>
|
||||
</v-tooltip>
|
||||
</v-btn>
|
||||
<v-menu offset-y left :title="$t('Machine.ConfigFilesPanel.SetupCurrentList')" attach>
|
||||
<v-menu offset-y left :title="$t('Machine.ConfigFilesPanel.SetupCurrentList')">
|
||||
<template #activator="{ on, attrs }">
|
||||
<v-btn class="px-2 minwidth-0 ml-3" v-bind="attrs" v-on="on">
|
||||
<v-icon>{{ mdiCog }}</v-icon>
|
||||
<v-icon class="machine-configfiles-panel__settings-icon">{{ mdiCog }}</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-list>
|
||||
@ -93,7 +94,6 @@
|
||||
:items="files"
|
||||
class="files-table"
|
||||
:headers="headers"
|
||||
:options="options"
|
||||
:page.sync="currentPage"
|
||||
:custom-sort="sortFiles"
|
||||
:sort-by.sync="sortBy"
|
||||
@ -464,7 +464,6 @@ interface uploadSnackbar {
|
||||
}
|
||||
|
||||
interface draggingFile {
|
||||
status: boolean
|
||||
item: FileStateFile
|
||||
}
|
||||
|
||||
@ -496,8 +495,6 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin) {
|
||||
inputDialogRenameDirectoryName: HTMLInputElement
|
||||
}
|
||||
|
||||
private selected = []
|
||||
private options = {}
|
||||
private currentPage = 1
|
||||
private contextMenu: contextMenu = {
|
||||
shown: false,
|
||||
@ -572,7 +569,6 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin) {
|
||||
},
|
||||
}
|
||||
private draggingFile: draggingFile = {
|
||||
status: false,
|
||||
item: {
|
||||
isDirectory: false,
|
||||
filename: '',
|
||||
@ -581,6 +577,14 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin) {
|
||||
},
|
||||
}
|
||||
|
||||
get blockFileUpload() {
|
||||
return this.$store.state.gui.view.blockFileUpload ?? false
|
||||
}
|
||||
|
||||
set blockFileUpload(newVal) {
|
||||
this.$store.dispatch('gui/saveSettingWithoutUpload', { name: 'view.blockFileUpload', value: newVal })
|
||||
}
|
||||
|
||||
get toolbarButtons() {
|
||||
return [
|
||||
{
|
||||
@ -934,74 +938,30 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin) {
|
||||
|
||||
async uploadFile() {
|
||||
if (this.$refs.fileUpload.files?.length) {
|
||||
this.$store.dispatch('socket/addLoading', { name: 'configFileUpload' })
|
||||
let successFiles = []
|
||||
this.uploadSnackbar.number = 0
|
||||
this.uploadSnackbar.max = this.$refs.fileUpload.files.length
|
||||
for (const file of this.$refs.fileUpload.files) {
|
||||
this.uploadSnackbar.number++
|
||||
const result = await this.doUploadFile(file)
|
||||
successFiles.push(result)
|
||||
}
|
||||
|
||||
this.$store.dispatch('socket/removeLoading', { name: 'configFileUpload' })
|
||||
for (const file of successFiles) {
|
||||
this.$toast.success('Upload of ' + file + ' successful!')
|
||||
}
|
||||
|
||||
const files = [...this.$refs.fileUpload.files]
|
||||
this.$refs.fileUpload.value = ''
|
||||
|
||||
await this.$store.dispatch('socket/addLoading', { name: 'configFileUpload' })
|
||||
await this.$store.dispatch('files/uploadSetCurrentNumber', 0)
|
||||
await this.$store.dispatch('files/uploadSetMaxNumber', this.$refs.fileUpload.files.length)
|
||||
|
||||
for (const file of files) {
|
||||
await this.$store.dispatch('files/uploadIncrementCurrentNumber')
|
||||
const path = this.currentPath.slice(0, 1) === '/' ? this.currentPath.slice(1) : this.currentPath
|
||||
const result = await this.$store.dispatch('files/uploadFile', {
|
||||
file,
|
||||
path,
|
||||
root: 'config',
|
||||
})
|
||||
|
||||
if (result !== false)
|
||||
this.$toast.success(this.$t('Files.SuccessfullyUploaded', { filename: result }).toString())
|
||||
}
|
||||
|
||||
await this.$store.dispatch('socket/removeLoading', { name: 'configFileUpload' })
|
||||
}
|
||||
}
|
||||
|
||||
doUploadFile(file: File) {
|
||||
let toast = this.$toast
|
||||
let formData = new FormData()
|
||||
let filename = file.name.replace(' ', '_')
|
||||
|
||||
this.uploadSnackbar.filename = filename
|
||||
this.uploadSnackbar.status = true
|
||||
this.uploadSnackbar.percent = 0
|
||||
this.uploadSnackbar.speed = 0
|
||||
this.uploadSnackbar.lastProgress.loaded = 0
|
||||
this.uploadSnackbar.lastProgress.time = 0
|
||||
|
||||
formData.append('root', this.root)
|
||||
formData.append('file', file, this.currentPath + '/' + filename)
|
||||
this.$store.dispatch('socket/addLoading', { name: 'configFileUpload' })
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.uploadSnackbar.cancelTokenSource = axios.CancelToken.source()
|
||||
axios
|
||||
.post(this.apiUrl + '/server/files/upload', formData, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
cancelToken: this.uploadSnackbar.cancelTokenSource.token,
|
||||
onUploadProgress: (progressEvent) => {
|
||||
this.uploadSnackbar.percent = (progressEvent.loaded * 100) / progressEvent.total
|
||||
if (this.uploadSnackbar.lastProgress.time) {
|
||||
const time = progressEvent.timeStamp - this.uploadSnackbar.lastProgress.time
|
||||
const data = progressEvent.loaded - this.uploadSnackbar.lastProgress.loaded
|
||||
|
||||
if (time) this.uploadSnackbar.speed = data / (time / 1000)
|
||||
}
|
||||
|
||||
this.uploadSnackbar.lastProgress.time = progressEvent.timeStamp
|
||||
this.uploadSnackbar.lastProgress.loaded = progressEvent.loaded
|
||||
this.uploadSnackbar.total = progressEvent.total
|
||||
},
|
||||
})
|
||||
.then((result) => {
|
||||
const filename = result.data.item.path.substr(result.data.item.path.indexOf('/') + 1)
|
||||
this.uploadSnackbar.status = false
|
||||
resolve(filename)
|
||||
})
|
||||
.catch(() => {
|
||||
this.uploadSnackbar.status = false
|
||||
this.$store.dispatch('socket/removeLoading', { name: 'configFileUpload' })
|
||||
toast.error('Cannot upload the file!')
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
cancelUpload() {
|
||||
this.uploadSnackbar.cancelTokenSource.cancel()
|
||||
this.uploadSnackbar.status = false
|
||||
@ -1009,13 +969,13 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin) {
|
||||
|
||||
dragFile(e: Event, item: FileStateFile) {
|
||||
e.preventDefault()
|
||||
this.draggingFile.status = true
|
||||
this.blockFileUpload = true
|
||||
this.draggingFile.item = item
|
||||
}
|
||||
|
||||
dragendFile(e: Event) {
|
||||
e.preventDefault()
|
||||
this.draggingFile.status = false
|
||||
this.blockFileUpload = false
|
||||
this.draggingFile.item = {
|
||||
isDirectory: false,
|
||||
filename: '',
|
||||
@ -1025,7 +985,7 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin) {
|
||||
}
|
||||
|
||||
dragOverFilelist(e: any, row: any) {
|
||||
if (this.draggingFile.status) {
|
||||
if (this.blockFileUpload) {
|
||||
e.preventDefault()
|
||||
//e.stopPropagation()
|
||||
|
||||
@ -1034,7 +994,7 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin) {
|
||||
}
|
||||
|
||||
dragLeaveFilelist(e: any) {
|
||||
if (this.draggingFile.status) {
|
||||
if (this.blockFileUpload) {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
|
||||
@ -1043,11 +1003,11 @@ export default class ConfigFilesPanel extends Mixins(BaseMixin) {
|
||||
}
|
||||
|
||||
async dragDropFilelist(e: any, row: any) {
|
||||
if (this.draggingFile.status) {
|
||||
if (this.blockFileUpload) {
|
||||
e.preventDefault()
|
||||
e.target.parentElement.style.backgroundColor = 'transparent'
|
||||
|
||||
let dest = ''
|
||||
let dest: string
|
||||
if (row.filename === '..') {
|
||||
dest =
|
||||
this.absolutePath.slice(1, this.absolutePath.lastIndexOf('/') + 1) + this.draggingFile.item.filename
|
||||
|
@ -205,6 +205,10 @@
|
||||
"View3D": "3D Betrachtung",
|
||||
"WrongFileUploaded": "Hochladen von {filename} verweigert. Falsches Dateiformat!"
|
||||
},
|
||||
"FullscreenUpload": {
|
||||
"CannotUploadFile": "Datei konnte nicht hochgeladen werden!",
|
||||
"DropFilesToUploadFiles": "Datei ablegen zum Hochladen"
|
||||
},
|
||||
"GCodeViewer": {
|
||||
"ClearLoadedFile": "Löschen",
|
||||
"ColorMode": "Farbmodus",
|
||||
|
@ -157,7 +157,6 @@
|
||||
"Download": "Download",
|
||||
"Downloading": "Downloading",
|
||||
"DoYouWantToStartFilename": "Do you want to start {filename}?",
|
||||
"DropFilesToAddGcode": "Drag & Drop files to add G-Code.",
|
||||
"EditFile": "Edit File",
|
||||
"Empty": "Empty",
|
||||
"Filament": "Filament",
|
||||
@ -203,6 +202,10 @@
|
||||
"View3D": "View 3D",
|
||||
"WrongFileUploaded": "Upload was denied for {filename}. Wrong file format!"
|
||||
},
|
||||
"FullscreenUpload": {
|
||||
"CannotUploadFile": "Cannot upload file!",
|
||||
"DropFilesToUploadFiles": "Drop files to upload"
|
||||
},
|
||||
"GCodeViewer": {
|
||||
"ClearLoadedFile": "Clear",
|
||||
"ColorMode": "Color Mode",
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
import { RootState } from '@/store/types'
|
||||
import i18n from '@/plugins/i18n'
|
||||
import { validGcodeExtensions } from '@/store/variables'
|
||||
import axios from 'axios'
|
||||
|
||||
export const actions: ActionTree<FileState, RootState> = {
|
||||
reset({ commit }) {
|
||||
@ -258,4 +259,80 @@ export const actions: ActionTree<FileState, RootState> = {
|
||||
Vue.$toast.success(<string>i18n.t('Files.SuccessfullyDeleted', { filename: delPath }))
|
||||
}
|
||||
},
|
||||
|
||||
async uploadFile(
|
||||
{ dispatch, commit, rootGetters },
|
||||
payload: { file: File; path: string; root: 'gcodes' | 'config' }
|
||||
) {
|
||||
const apiUrl = rootGetters['socket/getUrl']
|
||||
const formData = new FormData()
|
||||
formData.append('file', payload.file, payload.file.name)
|
||||
formData.append('root', payload.root)
|
||||
formData.append('path', payload.path)
|
||||
const cancelTokenSource = axios.CancelToken.source()
|
||||
|
||||
await commit('uploadClearState')
|
||||
await commit('uploadSetCancelTokenSource', cancelTokenSource)
|
||||
await commit('uploadSetFilename', payload.file.name)
|
||||
await commit('uploadSetShow', true)
|
||||
|
||||
let lastTime = 0
|
||||
let lastLoaded = 0
|
||||
|
||||
return new Promise((resolve) => {
|
||||
axios
|
||||
.post(apiUrl + '/server/files/upload', formData, {
|
||||
cancelToken: cancelTokenSource.token,
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
onUploadProgress: (progressEvent: any) => {
|
||||
const percent = (progressEvent.loaded * 100) / progressEvent.total
|
||||
commit('uploadSetPercent', percent)
|
||||
|
||||
if (lastTime === 0) {
|
||||
lastTime = progressEvent.timeStamp
|
||||
lastLoaded = progressEvent.loaded
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const time = progressEvent.timeStamp - lastTime
|
||||
if (time < 1000) return
|
||||
|
||||
const data = progressEvent.loaded - lastLoaded
|
||||
const speed = data / (time / 1000)
|
||||
commit('uploadSetSpeed', speed)
|
||||
|
||||
lastTime = progressEvent.timeStamp
|
||||
lastLoaded = progressEvent.loaded
|
||||
},
|
||||
})
|
||||
.then((result: any) => {
|
||||
commit('uploadSetShow', false)
|
||||
const lastPos = result.data.item.path.lastIndexOf('/')
|
||||
const filename = result.data.item.path.slice(lastPos + 1)
|
||||
resolve(filename)
|
||||
})
|
||||
.catch(() => {
|
||||
commit('uploadSetShow', false)
|
||||
Vue.$toast.error(i18n.t('FullscreenUpload.CannotUploadFile').toString())
|
||||
resolve(false)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
uploadSetShow({ commit }, payload) {
|
||||
commit('uploadSetShow', payload)
|
||||
},
|
||||
|
||||
uploadSetCurrentNumber({ commit }, payload) {
|
||||
commit('uploadSetCurrentNumber', payload)
|
||||
},
|
||||
|
||||
uploadIncrementCurrentNumber({ state, commit }) {
|
||||
commit('uploadSetCurrentNumber', state.upload.currentNumber + 1)
|
||||
},
|
||||
|
||||
uploadSetMaxNumber({ commit }, payload) {
|
||||
commit('uploadSetMaxNumber', payload)
|
||||
},
|
||||
}
|
||||
|
@ -7,6 +7,15 @@ import { getters } from '@/store/files/getters'
|
||||
export const getDefaultState = (): FileState => {
|
||||
return {
|
||||
filetree: [],
|
||||
upload: {
|
||||
show: false,
|
||||
filename: '',
|
||||
currentNumber: 0,
|
||||
maxNumber: 0,
|
||||
cancelTokenSource: null,
|
||||
percent: 0,
|
||||
speed: 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,4 +255,43 @@ export const mutations: MutationTree<FileState> = {
|
||||
const rootState = state.filetree.find((dir: FileStateFile) => dir.filename === payload.name)
|
||||
if (rootState) Vue.set(rootState, 'permissions', payload.permissions)
|
||||
},
|
||||
|
||||
uploadClearState(state) {
|
||||
const upload = { ...state.upload }
|
||||
upload.show = false
|
||||
upload.filename = ''
|
||||
upload.cancelTokenSource = null
|
||||
upload.speed = 0
|
||||
upload.percent = 0
|
||||
|
||||
Vue.set(state, 'upload', upload)
|
||||
},
|
||||
|
||||
uploadSetShow(state, payload) {
|
||||
Vue.set(state.upload, 'show', payload)
|
||||
},
|
||||
|
||||
uploadSetFilename(state, payload) {
|
||||
Vue.set(state.upload, 'filename', payload)
|
||||
},
|
||||
|
||||
uploadSetCancelTokenSource(state, payload) {
|
||||
Vue.set(state.upload, 'cancelTokenSource', payload)
|
||||
},
|
||||
|
||||
uploadSetCurrentNumber(state, payload) {
|
||||
Vue.set(state.upload, 'currentNumber', payload)
|
||||
},
|
||||
|
||||
uploadSetMaxNumber(state, payload) {
|
||||
Vue.set(state.upload, 'maxNumber', payload)
|
||||
},
|
||||
|
||||
uploadSetPercent(state, payload) {
|
||||
if (state.upload.percent !== payload) Vue.set(state.upload, 'percent', payload)
|
||||
},
|
||||
|
||||
uploadSetSpeed(state, payload) {
|
||||
if (state.upload.speed !== payload) Vue.set(state.upload, 'speed', payload)
|
||||
},
|
||||
}
|
||||
|
@ -1,5 +1,16 @@
|
||||
import { CancelTokenSource } from 'axios'
|
||||
|
||||
export interface FileState {
|
||||
filetree: FileStateFile[]
|
||||
upload: {
|
||||
show: boolean
|
||||
filename: string
|
||||
currentNumber: number
|
||||
maxNumber: number
|
||||
cancelTokenSource: CancelTokenSource | null
|
||||
percent: number
|
||||
speed: number
|
||||
}
|
||||
}
|
||||
|
||||
export interface FileStateFile {
|
||||
|
@ -150,6 +150,7 @@ export const getDefaultState = (): GuiState => {
|
||||
navigationStyle: 'iconsAndText',
|
||||
},
|
||||
view: {
|
||||
blockFileUpload: false,
|
||||
configfiles: {
|
||||
countPerPage: 10,
|
||||
sortBy: 'filename',
|
||||
@ -180,7 +181,7 @@ export const getDefaultState = (): GuiState => {
|
||||
'last_print_duration',
|
||||
'slicer',
|
||||
],
|
||||
currentPath: 'gcodes',
|
||||
currentPath: '',
|
||||
selectedFiles: [],
|
||||
},
|
||||
heightmap: {
|
||||
|
@ -103,6 +103,7 @@ export interface GuiState {
|
||||
navigationStyle: 'iconsAndText' | 'iconsOnly'
|
||||
}
|
||||
view: {
|
||||
blockFileUpload: boolean
|
||||
configfiles: {
|
||||
countPerPage: number
|
||||
sortBy: string
|
||||
|
Loading…
x
Reference in New Issue
Block a user