update FileItem context strategy by reading File content on File change

This commit is contained in:
axolotle 2022-03-01 16:29:00 +01:00
parent 9b57063572
commit fd19dcebf6
3 changed files with 75 additions and 43 deletions

View file

@ -1,19 +1,24 @@
<template>
<b-button-group class="w-100">
<b-button @click="clearFiles" variant="danger" v-if="!this.required && this.value !== null && !this.value._removed">
<b-button
v-if="!this.required && this.value.file !== null"
@click="clearFiles" variant="danger"
>
<span class="sr-only">{{ $t('delete') }}</span>
<icon iname="trash" />
</b-button>
<b-form-file
v-model="file"
ref="input-file"
:id="id"
v-on="$listeners"
:required="required"
:placeholder="_placeholder"
:accept="accept"
:drop-placeholder="dropPlaceholder"
:state="state"
:browse-text="$t('words.browse')"
@input="onInput"
@blur="$parent.$emit('touch', name)"
@focusout.native="$parent.$emit('touch', name)"
/>
@ -21,18 +26,14 @@
</template>
<script>
import { getFileContent } from '@/helpers/commons'
export default {
name: 'FileItem',
data () {
return {
file: this.value
}
},
props: {
id: { type: String, default: null },
value: { type: [File, null], default: null },
value: { type: Object, default: () => ({}) },
placeholder: { type: String, default: 'Choose a file or drop it here...' },
dropPlaceholder: { type: String, default: null },
accept: { type: String, default: null },
@ -41,24 +42,43 @@ export default {
name: { type: String, default: null }
},
data () {
return {
file: this.value.file
}
},
computed: {
_placeholder: function () {
return (this.value === null) ? this.placeholder : this.value.name
return this.value.file === null ? this.placeholder : this.value.file.name
}
},
methods: {
clearFiles () {
const f = new File([''], this.placeholder)
f._removed = true
if (this.value && this.value.currentfile) {
this.$refs['input-file'].reset()
this.$emit('input', f)
} else {
this.$refs['input-file'].setFiles([f])
this.file = f
this.$emit('input', f)
onInput (file) {
const value = {
file,
content: '',
currentfile: false,
removed: false
}
// Update the value with the new File and an empty content for now
this.$emit('input', value)
// Asynchronously load the File content and update the value again
getFileContent(file).then(content => {
this.$emit('input', { ...value, content })
})
},
clearFiles () {
this.$refs['input-file'].reset()
this.$emit('input', {
file: null,
content: '',
current_file: false,
removed: true
})
}
}
}

View file

@ -100,3 +100,26 @@ export function escapeHtml (unsafe) {
export function randint (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
}
/**
* Returns a File content.
*
* @param {File} file
* @param {Object} [extraParams] - Optionnal params
* @param {Boolean} [extraParams.base64] - returns a base64 representation of the file.
* @return {Promise<String>}
*/
export function getFileContent (file, { base64 = false } = {}) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onerror = reject
reader.onload = () => resolve(reader.result)
if (base64) {
reader.readAsDataURL(file)
} else {
reader.readAsText(file)
}
})
}

View file

@ -2,7 +2,12 @@ import i18n from '@/i18n'
import store from '@/store'
import evaluate from 'simple-evaluate'
import * as validators from '@/helpers/validators'
import { isObjectLiteral, isEmptyValue, flattenObjectLiteral } from '@/helpers/commons'
import {
isObjectLiteral,
isEmptyValue,
flattenObjectLiteral,
getFileContent
} from '@/helpers/commons'
/**
@ -125,9 +130,12 @@ export function formatYunoHostArgument (arg) {
name: 'FileItem',
props: defaultProps.concat(['accept']),
callback: function () {
if (value) {
value = new File([''], value)
value.currentfile = true
value = {
// in case of already defined file, we receive only the file path (not the actual file)
file: value ? new File([''], value) : null,
content: '',
current_file: !!value,
removed: false
}
}
},
@ -353,25 +361,6 @@ export function configPanelsFieldIsVisible (expression, field, forms) {
}
export function pFileReader (file, output, key, base64 = true) {
return new Promise((resolve, reject) => {
const fr = new FileReader()
fr.onerror = reject
fr.onload = () => {
output[key] = fr.result
if (base64) {
output[key] = fr.result.replace(/data:[^;]*;base64,/, '')
}
output[key + '[name]'] = file.name
resolve()
}
if (base64) {
fr.readAsDataURL(file)
} else {
fr.readAsText(file)
}
})
}
/**