diff options
-rw-r--r-- | src/components/Global/FormFile.vue | 90 | ||||
-rw-r--r-- | src/locales/en-US.json | 5 | ||||
-rw-r--r-- | src/views/AccessControl/SslCertificates/ModalUploadCertificate.vue | 24 | ||||
-rw-r--r-- | src/views/Configuration/Firmware/Firmware.vue | 36 | ||||
-rw-r--r-- | src/views/Control/VirtualMedia/VirtualMedia.vue | 29 |
5 files changed, 142 insertions, 42 deletions
diff --git a/src/components/Global/FormFile.vue b/src/components/Global/FormFile.vue new file mode 100644 index 00000000..30af00d7 --- /dev/null +++ b/src/components/Global/FormFile.vue @@ -0,0 +1,90 @@ +<template> + <div class="custom-form-file-container"> + <label> + <b-form-file + :id="id" + v-model="file" + :accept="accept" + :disabled="disabled" + :state="state" + plain + @input="$emit('input', file)" + > + </b-form-file> + <span class="add-file-btn btn btn-primary"> + {{ $t('global.fileUpload.browseText') }} + </span> + <slot name="invalid"></slot> + </label> + <div v-if="file" class="clear-selected-file px-3 py-2 mt-2"> + {{ file ? file.name : '' }} + <b-button variant="light" class="px-2 ml-auto" @click="file = null" + ><icon-close :title="$t('global.fileUpload.clearSelectedFile')" + /></b-button> + </div> + </div> +</template> + +<script> +import { BFormFile } from 'bootstrap-vue'; +import IconClose from '@carbon/icons-vue/es/close/20'; + +export default { + name: 'FormFile', + components: { BFormFile, IconClose }, + props: { + id: { + type: String, + default: '', + }, + disabled: { + type: Boolean, + default: false, + }, + accept: { + type: String, + default: '', + }, + state: { + type: Boolean, + default: true, + }, + }, + data() { + return { + file: null, + }; + }, +}; +</script> + +<style lang="scss" scoped> +.form-control-file { + opacity: 0; + height: 0; + &:focus + span { + box-shadow: inset 0 0 0 3px theme-color('primary'), inset 0 0 0 5px $white; + } +} + +// Get mouse pointer on complete element +.add-file-btn { + position: relative; +} + +.clear-selected-file { + display: flex; + align-items: center; + background-color: theme-color('light'); + .btn { + width: 36px; + height: 36px; + display: flex; + align-items: center; + + &:focus { + box-shadow: inset 0 0 0 2px theme-color('primary'); + } + } +} +</style> diff --git a/src/locales/en-US.json b/src/locales/en-US.json index 0c4dcd6d..5c03e396 100644 --- a/src/locales/en-US.json +++ b/src/locales/en-US.json @@ -30,9 +30,8 @@ "useCursorKeysToNavigateCalendarDates": "Use cursor keys to navigate calendar dates" }, "fileUpload": { - "browseText": "Browse", - "dropPlaceholder": "Drop files here", - "placeholder": "No file selected" + "browseText": "Add file", + "clearSelectedFile": "Clear selected file" }, "form": { "dateMustBeAfter": "Date must be after %{date}", diff --git a/src/views/AccessControl/SslCertificates/ModalUploadCertificate.vue b/src/views/AccessControl/SslCertificates/ModalUploadCertificate.vue index 50df9a42..8a719775 100644 --- a/src/views/AccessControl/SslCertificates/ModalUploadCertificate.vue +++ b/src/views/AccessControl/SslCertificates/ModalUploadCertificate.vue @@ -39,24 +39,19 @@ </b-form-group> </template> - <b-form-group - :label="$t('pageSslCertificates.modal.certificateFile')" - label-for="certificate-file" - > - <b-form-file + <b-form-group :label="$t('pageSslCertificates.modal.certificateFile')"> + <form-file id="certificate-file" v-model="form.file" accept=".pem" - :browse-text="$t('global.fileUpload.browseText')" - :drop-placeholder="$t('global.fileUpload.dropPlaceholder')" - :placeholder="$t('global.fileUpload.placeholder')" :state="getValidationState($v.form.file)" - /> - <b-form-invalid-feedback role="alert"> - <template v-if="!$v.form.file.required"> - {{ $t('global.form.required') }} + > + <template #invalid> + <b-form-invalid-feedback role="alert"> + {{ $t('global.form.required') }} + </b-form-invalid-feedback> </template> - </b-form-invalid-feedback> + </form-file> </b-form-group> </b-form> <template #modal-ok> @@ -74,7 +69,10 @@ import { required, requiredIf } from 'vuelidate/lib/validators'; import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; +import FormFile from '@/components/Global/FormFile'; + export default { + components: { FormFile }, mixins: [VuelidateMixin], props: { certificate: { diff --git a/src/views/Configuration/Firmware/Firmware.vue b/src/views/Configuration/Firmware/Firmware.vue index 24ef33c8..d78b43ff 100644 --- a/src/views/Configuration/Firmware/Firmware.vue +++ b/src/views/Configuration/Firmware/Firmware.vue @@ -99,27 +99,26 @@ <!-- Workstation Upload --> <template v-if="isWorkstationSelected"> - <b-form-group - :label="$t('pageFirmware.form.imageFile')" - label-for="image-file" - > + <b-form-group :label="$t('pageFirmware.form.imageFile')"> <b-form-text id="image-file-help-block"> {{ $t('pageFirmware.form.onlyTarFilesAccepted') }} </b-form-text> - <b-form-file + <form-file id="image-file" - v-model="file" accept=".tar" - aria-describedby="image-file-help-block" - :browse-text="$t('global.fileUpload.browseText')" - :drop-placeholder="$t('global.fileUpload.dropPlaceholder')" - :placeholder="$t('global.fileUpload.placeholder')" + :disabled="isPageDisabled" :state="getValidationState($v.file)" - @input="$v.file.$touch()" - /> - <b-form-invalid-feedback role="alert"> - {{ $t('global.form.required') }} - </b-form-invalid-feedback> + aria-describedby="image-file-help-block" + @input="onFileUpload($event)" + > + <template #invalid> + <b-form-invalid-feedback role="alert"> + <template> + {{ $t('global.form.required') }} + </template> + </b-form-invalid-feedback> + </template> + </form-file> </b-form-group> </template> @@ -198,6 +197,7 @@ import PageTitle from '@/components/Global/PageTitle'; import Alert from '@/components/Global/Alert'; import ModalUpload from './FirmwareModalUpload'; import ModalRebootBackupBmc from './FirmwareModalRebootBackupBmc'; +import FormFile from '@/components/Global/FormFile'; import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin'; @@ -212,6 +212,7 @@ export default { ModalUpload, PageSection, PageTitle, + FormFile, }, mixins: [BVToastMixin, LoadingBarMixin, VuelidateMixin], beforeRouteLeave(to, from, next) { @@ -226,6 +227,7 @@ export default { tftpIpAddress: null, tftpFileName: null, timeoutId: null, + isPageDisabled: null, }; }, computed: { @@ -275,6 +277,10 @@ export default { }; }, methods: { + onFileUpload(file) { + this.file = file; + this.$v.file.$touch(); + }, uploadFirmware() { const startTime = this.$options.filters.formatTime(new Date()); this.setRebootTimeout(360000); //6 minute timeout diff --git a/src/views/Control/VirtualMedia/VirtualMedia.vue b/src/views/Control/VirtualMedia/VirtualMedia.vue index a15f2cd9..8264c5a2 100644 --- a/src/views/Control/VirtualMedia/VirtualMedia.vue +++ b/src/views/Control/VirtualMedia/VirtualMedia.vue @@ -8,17 +8,20 @@ > <b-row> <b-col v-for="(dev, $index) in proxyDevices" :key="$index" md="6"> - <b-form-group - :label="dev.id" - :label-for="dev.id" - label-class="bold" - > - <b-form-file - v-show="!dev.isActive" - :id="dev.id" + <b-form-group :label="dev.id" label-class="bold"> + <form-file + v-if="!dev.isActive" + :id="concatId(dev.id)" v-model="dev.file" - /> - <p v-if="dev.isActive">{{ dev.file.name }}</p> + > + <template #invalid> + <b-form-invalid-feedback role="alert"> + <template> + {{ $t('global.form.required') }} + </template> + </b-form-invalid-feedback> + </template> + </form-file> </b-form-group> <b-button v-if="!dev.isActive" @@ -102,10 +105,11 @@ import BVToastMixin from '@/components/Mixins/BVToastMixin'; import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin'; import ModalConfigureConnection from './ModalConfigureConnection'; import NbdServer from '@/utilities/NBDServer'; +import FormFile from '@/components/Global/FormFile'; export default { name: 'VirtualMedia', - components: { PageTitle, PageSection, ModalConfigureConnection }, + components: { PageTitle, PageSection, ModalConfigureConnection, FormFile }, mixins: [BVToastMixin, LoadingBarMixin], data() { return { @@ -211,6 +215,9 @@ export default { this.modalConfigureConnection = connectionData; this.$bvModal.show('configure-connection'); }, + concatId(val) { + return val.split(' ').join('_').toLowerCase(); + }, }, }; </script> |