diff options
author | Andrey V.Kosteltsev <AKosteltsev@IBS.RU> | 2022-07-04 23:11:28 +0300 |
---|---|---|
committer | Andrey V.Kosteltsev <AKosteltsev@IBS.RU> | 2022-07-04 23:11:28 +0300 |
commit | 3f4094d08b873e17464a51c817ea7d41177f848d (patch) | |
tree | 8880a0e7c8c0ac07ed298ce719cfab3278f2aa12 /src/views/_ibs/Settings | |
parent | f5c8dbfa6fb3812a3b3a2aafd3538fbdf8b8c668 (diff) | |
download | webui-vue-3f4094d08b873e17464a51c817ea7d41177f848d.tar.xz |
IBS: _ibs UI Theme
Diffstat (limited to 'src/views/_ibs/Settings')
-rw-r--r-- | src/views/_ibs/Settings/DateTime/DateTime.vue | 417 | ||||
-rw-r--r-- | src/views/_ibs/Settings/DateTime/index.js | 2 | ||||
-rw-r--r-- | src/views/_ibs/Settings/Network/ModalDns.vue | 92 | ||||
-rw-r--r-- | src/views/_ibs/Settings/Network/ModalHostname.vue | 110 | ||||
-rw-r--r-- | src/views/_ibs/Settings/Network/ModalIpv4.vue | 165 | ||||
-rw-r--r-- | src/views/_ibs/Settings/Network/ModalMacAddress.vue | 109 | ||||
-rw-r--r-- | src/views/_ibs/Settings/Network/Network.vue | 167 | ||||
-rw-r--r-- | src/views/_ibs/Settings/Network/NetworkGlobalSettings.vue | 161 | ||||
-rw-r--r-- | src/views/_ibs/Settings/Network/NetworkInterfaceSettings.vue | 117 | ||||
-rw-r--r-- | src/views/_ibs/Settings/Network/TableDns.vue | 145 | ||||
-rw-r--r-- | src/views/_ibs/Settings/Network/TableIpv4.vue | 169 | ||||
-rw-r--r-- | src/views/_ibs/Settings/Network/index.js | 2 | ||||
-rw-r--r-- | src/views/_ibs/Settings/PowerRestorePolicy/PowerRestorePolicy.vue | 91 | ||||
-rw-r--r-- | src/views/_ibs/Settings/PowerRestorePolicy/index.js | 2 |
14 files changed, 1749 insertions, 0 deletions
diff --git a/src/views/_ibs/Settings/DateTime/DateTime.vue b/src/views/_ibs/Settings/DateTime/DateTime.vue new file mode 100644 index 00000000..f5e063d1 --- /dev/null +++ b/src/views/_ibs/Settings/DateTime/DateTime.vue @@ -0,0 +1,417 @@ +<template> + <b-container fluid="xl"> + <page-title /> + <b-row> + <b-col md="8" xl="6"> + <alert variant="info" class="mb-4"> + <span> + {{ $t('pageDateTime.alert.message') }} + <b-link to="/profile-settings"> + {{ $t('pageDateTime.alert.link') }}</b-link + > + </span> + </alert> + </b-col> + </b-row> + <page-section> + <b-row> + <b-col lg="3"> + <dl> + <dt>{{ $t('pageDateTime.form.date') }}</dt> + <dd v-if="bmcTime">{{ bmcTime | formatDate }}</dd> + <dd v-else>--</dd> + </dl> + </b-col> + <b-col lg="3"> + <dl> + <dt>{{ $t('pageDateTime.form.time.label') }}</dt> + <dd v-if="bmcTime">{{ bmcTime | formatTime }}</dd> + <dd v-else>--</dd> + </dl> + </b-col> + </b-row> + </page-section> + <page-section :section-title="$t('pageDateTime.configureSettings')"> + <b-form novalidate @submit.prevent="submitForm"> + <b-form-group + label="Configure date and time" + :disabled="loading" + label-sr-only + > + <b-form-radio + v-model="form.configurationSelected" + value="manual" + data-test-id="dateTime-radio-configureManual" + > + {{ $t('pageDateTime.form.manual') }} + </b-form-radio> + <b-row class="mt-3 ml-3"> + <b-col sm="6" lg="4" xl="3"> + <b-form-group + :label="$t('pageDateTime.form.date')" + label-for="input-manual-date" + > + <b-form-text id="date-format-help">YYYY-MM-DD</b-form-text> + <b-input-group> + <b-form-input + id="input-manual-date" + v-model="form.manual.date" + :state="getValidationState($v.form.manual.date)" + :disabled="ntpOptionSelected" + data-test-id="dateTime-input-manualDate" + class="form-control-with-button" + @blur="$v.form.manual.date.$touch()" + /> + <b-form-invalid-feedback role="alert"> + <div v-if="!$v.form.manual.date.pattern"> + {{ $t('global.form.invalidFormat') }} + </div> + <div v-if="!$v.form.manual.date.required"> + {{ $t('global.form.fieldRequired') }} + </div> + </b-form-invalid-feedback> + <b-form-datepicker + v-model="form.manual.date" + class="btn-datepicker btn-icon-only" + button-only + right + :hide-header="true" + :locale="locale" + :label-help=" + $t('global.calendar.useCursorKeysToNavigateCalendarDates') + " + :title="$t('global.calendar.selectDate')" + :disabled="ntpOptionSelected" + button-variant="link" + aria-controls="input-manual-date" + > + <template #button-content> + <icon-calendar /> + <span class="sr-only"> + {{ $t('global.calendar.selectDate') }} + </span> + </template> + </b-form-datepicker> + </b-input-group> + </b-form-group> + </b-col> + <b-col sm="6" lg="4" xl="3"> + <b-form-group + :label="$t('pageDateTime.form.time.timezone', { timezone })" + label-for="input-manual-time" + > + <b-form-text id="time-format-help">HH:MM</b-form-text> + <b-input-group> + <b-form-input + id="input-manual-time" + v-model="form.manual.time" + :state="getValidationState($v.form.manual.time)" + :disabled="ntpOptionSelected" + data-test-id="dateTime-input-manualTime" + @blur="$v.form.manual.time.$touch()" + /> + <b-form-invalid-feedback role="alert"> + <div v-if="!$v.form.manual.time.pattern"> + {{ $t('global.form.invalidFormat') }} + </div> + <div v-if="!$v.form.manual.time.required"> + {{ $t('global.form.fieldRequired') }} + </div> + </b-form-invalid-feedback> + </b-input-group> + </b-form-group> + </b-col> + </b-row> + <b-form-radio + v-model="form.configurationSelected" + value="ntp" + data-test-id="dateTime-radio-configureNTP" + > + NTP + </b-form-radio> + <b-row class="mt-3 ml-3"> + <b-col sm="6" lg="4" xl="3"> + <b-form-group + :label="$t('pageDateTime.form.ntpServers.server1')" + label-for="input-ntp-1" + > + <b-input-group> + <b-form-input + id="input-ntp-1" + v-model="form.ntp.firstAddress" + :state="getValidationState($v.form.ntp.firstAddress)" + :disabled="manualOptionSelected" + data-test-id="dateTime-input-ntpServer1" + @blur="$v.form.ntp.firstAddress.$touch()" + /> + <b-form-invalid-feedback role="alert"> + <div v-if="!$v.form.ntp.firstAddress.required"> + {{ $t('global.form.fieldRequired') }} + </div> + </b-form-invalid-feedback> + </b-input-group> + </b-form-group> + </b-col> + <b-col sm="6" lg="4" xl="3"> + <b-form-group + :label="$t('pageDateTime.form.ntpServers.server2')" + label-for="input-ntp-2" + > + <b-input-group> + <b-form-input + id="input-ntp-2" + v-model="form.ntp.secondAddress" + :disabled="manualOptionSelected" + data-test-id="dateTime-input-ntpServer2" + /> + </b-input-group> + </b-form-group> + </b-col> + <b-col sm="6" lg="4" xl="3"> + <b-form-group + :label="$t('pageDateTime.form.ntpServers.server3')" + label-for="input-ntp-3" + > + <b-input-group> + <b-form-input + id="input-ntp-3" + v-model="form.ntp.thirdAddress" + :disabled="manualOptionSelected" + data-test-id="dateTime-input-ntpServer3" + /> + </b-input-group> + </b-form-group> + </b-col> + </b-row> + <b-button + variant="primary" + type="submit" + data-test-id="dateTime-button-saveSettings" + > + {{ $t('global.action.saveSettings') }} + </b-button> + </b-form-group> + </b-form> + </page-section> + </b-container> +</template> + +<script> +import Alert from '@/components/Global/Alert'; +import IconCalendar from '@carbon/icons-vue/es/calendar/20'; +import PageTitle from '@/components/Global/PageTitle'; +import PageSection from '@/components/Global/PageSection'; + +import BVToastMixin from '@/components/Mixins/BVToastMixin'; +import LoadingBarMixin, { loading } from '@/components/Mixins/LoadingBarMixin'; +import LocalTimezoneLabelMixin from '@/components/Mixins/LocalTimezoneLabelMixin'; +import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; + +import { mapState } from 'vuex'; +import { requiredIf, helpers } from 'vuelidate/lib/validators'; + +const isoDateRegex = /([12]\d{3}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]))/; +const isoTimeRegex = /^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/; + +export default { + name: 'DateTime', + components: { Alert, IconCalendar, PageTitle, PageSection }, + mixins: [ + BVToastMixin, + LoadingBarMixin, + LocalTimezoneLabelMixin, + VuelidateMixin, + ], + beforeRouteLeave(to, from, next) { + this.hideLoader(); + next(); + }, + data() { + return { + locale: this.$store.getters['global/languagePreference'], + form: { + configurationSelected: 'manual', + manual: { + date: '', + time: '', + }, + ntp: { firstAddress: '', secondAddress: '', thirdAddress: '' }, + }, + loading, + }; + }, + validations() { + return { + form: { + manual: { + date: { + required: requiredIf(function () { + return this.form.configurationSelected === 'manual'; + }), + pattern: helpers.regex('pattern', isoDateRegex), + }, + time: { + required: requiredIf(function () { + return this.form.configurationSelected === 'manual'; + }), + pattern: helpers.regex('pattern', isoTimeRegex), + }, + }, + ntp: { + firstAddress: { + required: requiredIf(function () { + return this.form.configurationSelected === 'ntp'; + }), + }, + }, + }, + }; + }, + computed: { + ...mapState('dateTime', ['ntpServers', 'isNtpProtocolEnabled']), + bmcTime() { + return this.$store.getters['global/bmcTime']; + }, + ntpOptionSelected() { + return this.form.configurationSelected === 'ntp'; + }, + manualOptionSelected() { + return this.form.configurationSelected === 'manual'; + }, + isUtcDisplay() { + return this.$store.getters['global/isUtcDisplay']; + }, + timezone() { + if (this.isUtcDisplay) { + return 'UTC'; + } + return this.localOffset(); + }, + }, + watch: { + ntpServers() { + this.setNtpValues(); + }, + manualDate() { + this.emitChange(); + }, + bmcTime() { + this.form.manual.date = this.$options.filters.formatDate( + this.$store.getters['global/bmcTime'] + ); + this.form.manual.time = this.$options.filters + .formatTime(this.$store.getters['global/bmcTime']) + .slice(0, 5); + }, + }, + created() { + this.startLoader(); + this.setNtpValues(); + Promise.all([ + this.$store.dispatch('global/getBmcTime'), + this.$store.dispatch('dateTime/getNtpData'), + ]).finally(() => this.endLoader()); + }, + methods: { + emitChange() { + if (this.$v.$invalid) return; + this.$v.$reset(); //reset to re-validate on blur + this.$emit('change', { + manualDate: this.manualDate ? new Date(this.manualDate) : null, + }); + }, + setNtpValues() { + this.form.configurationSelected = this.isNtpProtocolEnabled + ? 'ntp' + : 'manual'; + [ + this.form.ntp.firstAddress = '', + this.form.ntp.secondAddress = '', + this.form.ntp.thirdAddress = '', + ] = [this.ntpServers[0], this.ntpServers[1], this.ntpServers[2]]; + }, + submitForm() { + this.$v.$touch(); + if (this.$v.$invalid) return; + this.startLoader(); + + let dateTimeForm = {}; + let isNTPEnabled = this.form.configurationSelected === 'ntp'; + + if (!isNTPEnabled) { + const isUtcDisplay = this.$store.getters['global/isUtcDisplay']; + let date; + + dateTimeForm.ntpProtocolEnabled = false; + + if (isUtcDisplay) { + // Create UTC Date + date = this.getUtcDate(this.form.manual.date, this.form.manual.time); + } else { + // Create local Date + date = new Date(`${this.form.manual.date} ${this.form.manual.time}`); + } + + dateTimeForm.updatedDateTime = date.toISOString(); + } else { + dateTimeForm.ntpProtocolEnabled = true; + + const ntpArray = [ + this.form.ntp.firstAddress, + this.form.ntp.secondAddress, + this.form.ntp.thirdAddress, + ]; + + // Filter the ntpArray to remove empty strings, + // per Redfish spec there should be no empty strings or null on the ntp array. + const ntpArrayFiltered = ntpArray.filter((x) => x); + + dateTimeForm.ntpServersArray = [...ntpArrayFiltered]; + + [this.ntpServers[0], this.ntpServers[1], this.ntpServers[2]] = [ + ...dateTimeForm.ntpServersArray, + ]; + + this.setNtpValues(); + } + + this.$store + .dispatch('dateTime/updateDateTime', dateTimeForm) + .then((success) => { + this.successToast(success); + if (!isNTPEnabled) return; + // Shift address up if second address is empty + // to avoid refreshing after delay when updating NTP + if (!this.form.ntp.secondAddress && this.form.ntp.thirdAddres) { + this.form.ntp.secondAddress = this.form.ntp.thirdAddres; + this.form.ntp.thirdAddress = ''; + } + }) + .then(() => { + this.$store.dispatch('global/getBmcTime'); + }) + .catch(({ message }) => this.errorToast(message)) + .finally(() => { + this.$v.form.$reset(); + this.endLoader(); + }); + }, + getUtcDate(date, time) { + // Split user input string values to create + // a UTC Date object + const datesArray = date.split('-'); + const timeArray = time.split(':'); + let utcDate = Date.UTC( + datesArray[0], // User input year + //UTC expects zero-index month value 0-11 (January-December) + //for reference https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/UTC#Parameters + parseInt(datesArray[1]) - 1, // User input month + datesArray[2], // User input day + timeArray[0], // User input hour + timeArray[1] // User input minute + ); + return new Date(utcDate); + }, + }, +}; +</script> diff --git a/src/views/_ibs/Settings/DateTime/index.js b/src/views/_ibs/Settings/DateTime/index.js new file mode 100644 index 00000000..2df21eae --- /dev/null +++ b/src/views/_ibs/Settings/DateTime/index.js @@ -0,0 +1,2 @@ +import DateTime from './DateTime.vue'; +export default DateTime; diff --git a/src/views/_ibs/Settings/Network/ModalDns.vue b/src/views/_ibs/Settings/Network/ModalDns.vue new file mode 100644 index 00000000..7f127173 --- /dev/null +++ b/src/views/_ibs/Settings/Network/ModalDns.vue @@ -0,0 +1,92 @@ +<template> + <b-modal + id="modal-dns" + ref="modal" + :title="$t('pageNetwork.table.addDnsAddress')" + @hidden="resetForm" + > + <b-form id="form-dns" @submit.prevent="handleSubmit"> + <b-row> + <b-col sm="6"> + <b-form-group + :label="$t('pageNetwork.modal.staticDns')" + label-for="staticDns" + > + <b-form-input + id="staticDns" + v-model="form.staticDns" + type="text" + :state="getValidationState($v.form.staticDns)" + @input="$v.form.staticDns.$touch()" + /> + <b-form-invalid-feedback role="alert"> + <template v-if="!$v.form.staticDns.required"> + {{ $t('global.form.fieldRequired') }} + </template> + <template v-if="!$v.form.staticDns.ipAddress"> + {{ $t('global.form.invalidFormat') }} + </template> + </b-form-invalid-feedback> + </b-form-group> + </b-col> + </b-row> + </b-form> + <template #modal-footer="{ cancel }"> + <b-button variant="secondary" @click="cancel()"> + {{ $t('global.action.cancel') }} + </b-button> + <b-button form="form-dns" type="submit" variant="primary" @click="onOk"> + {{ $t('global.action.add') }} + </b-button> + </template> + </b-modal> +</template> + +<script> +import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; +import { ipAddress, required } from 'vuelidate/lib/validators'; + +export default { + mixins: [VuelidateMixin], + data() { + return { + form: { + staticDns: null, + }, + }; + }, + validations() { + return { + form: { + staticDns: { + required, + ipAddress, + }, + }, + }; + }, + methods: { + handleSubmit() { + this.$v.$touch(); + if (this.$v.$invalid) return; + this.$emit('ok', [this.form.staticDns]); + this.closeModal(); + }, + closeModal() { + this.$nextTick(() => { + this.$refs.modal.hide(); + }); + }, + resetForm() { + this.form.staticDns = null; + this.$v.$reset(); + this.$emit('hidden'); + }, + onOk(bvModalEvt) { + // prevent modal close + bvModalEvt.preventDefault(); + this.handleSubmit(); + }, + }, +}; +</script> diff --git a/src/views/_ibs/Settings/Network/ModalHostname.vue b/src/views/_ibs/Settings/Network/ModalHostname.vue new file mode 100644 index 00000000..f3221ec7 --- /dev/null +++ b/src/views/_ibs/Settings/Network/ModalHostname.vue @@ -0,0 +1,110 @@ +<template> + <b-modal + id="modal-hostname" + ref="modal" + :title="$t('pageNetwork.modal.editHostnameTitle')" + @hidden="resetForm" + > + <b-form id="hostname-settings" @submit.prevent="handleSubmit"> + <b-row> + <b-col sm="6"> + <b-form-group + :label="$t('pageNetwork.hostname')" + label-for="hostname" + > + <b-form-input + id="hostname" + v-model="form.hostname" + type="text" + :state="getValidationState($v.form.hostname)" + @input="$v.form.hostname.$touch()" + /> + <b-form-invalid-feedback role="alert"> + <template v-if="!$v.form.hostname.required"> + {{ $t('global.form.fieldRequired') }} + </template> + <template v-if="!$v.form.hostname.validateHostname"> + {{ $t('global.form.lengthMustBeBetween', { min: 1, max: 64 }) }} + </template> + </b-form-invalid-feedback> + </b-form-group> + </b-col> + </b-row> + </b-form> + <template #modal-footer="{ cancel }"> + <b-button variant="secondary" @click="cancel()"> + {{ $t('global.action.cancel') }} + </b-button> + <b-button + form="hostname-settings" + type="submit" + variant="primary" + @click="onOk" + > + {{ $t('global.action.add') }} + </b-button> + </template> + </b-modal> +</template> + +<script> +import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; +import { required, helpers } from 'vuelidate/lib/validators'; + +const validateHostname = helpers.regex('validateHostname', /^\S{0,64}$/); + +export default { + mixins: [VuelidateMixin], + props: { + hostname: { + type: String, + default: '', + }, + }, + data() { + return { + form: { + hostname: '', + }, + }; + }, + watch: { + hostname() { + this.form.hostname = this.hostname; + }, + }, + validations() { + return { + form: { + hostname: { + required, + validateHostname, + }, + }, + }; + }, + methods: { + handleSubmit() { + this.$v.$touch(); + if (this.$v.$invalid) return; + this.$emit('ok', { HostName: this.form.hostname }); + this.closeModal(); + }, + closeModal() { + this.$nextTick(() => { + this.$refs.modal.hide(); + }); + }, + resetForm() { + this.form.hostname = this.hostname; + this.$v.$reset(); + this.$emit('hidden'); + }, + onOk(bvModalEvt) { + // prevent modal close + bvModalEvt.preventDefault(); + this.handleSubmit(); + }, + }, +}; +</script> diff --git a/src/views/_ibs/Settings/Network/ModalIpv4.vue b/src/views/_ibs/Settings/Network/ModalIpv4.vue new file mode 100644 index 00000000..dcf4a579 --- /dev/null +++ b/src/views/_ibs/Settings/Network/ModalIpv4.vue @@ -0,0 +1,165 @@ +<template> + <b-modal + id="modal-add-ipv4" + ref="modal" + :title="$t('pageNetwork.table.addIpv4Address')" + @hidden="resetForm" + > + <b-form id="form-ipv4" @submit.prevent="handleSubmit"> + <b-row> + <b-col sm="6"> + <b-form-group + :label="$t('pageNetwork.modal.ipAddress')" + label-for="ipAddress" + > + <b-form-input + id="ipAddress" + v-model="form.ipAddress" + type="text" + :state="getValidationState($v.form.ipAddress)" + @input="$v.form.ipAddress.$touch()" + /> + <b-form-invalid-feedback role="alert"> + <template v-if="!$v.form.ipAddress.required"> + {{ $t('global.form.fieldRequired') }} + </template> + <template v-if="!$v.form.ipAddress.ipAddress"> + {{ $t('global.form.invalidFormat') }} + </template> + </b-form-invalid-feedback> + </b-form-group> + </b-col> + <b-col sm="6"> + <b-form-group + :label="$t('pageNetwork.modal.gateway')" + label-for="gateway" + > + <b-form-input + id="gateway" + v-model="form.gateway" + type="text" + :state="getValidationState($v.form.gateway)" + @input="$v.form.gateway.$touch()" + /> + <b-form-invalid-feedback role="alert"> + <template v-if="!$v.form.gateway.required"> + {{ $t('global.form.fieldRequired') }} + </template> + <template v-if="!$v.form.gateway.ipAddress"> + {{ $t('global.form.invalidFormat') }} + </template> + </b-form-invalid-feedback> + </b-form-group> + </b-col> + </b-row> + <b-row> + <b-col sm="6"> + <b-form-group + :label="$t('pageNetwork.modal.subnetMask')" + label-for="subnetMask" + > + <b-form-input + id="subnetMask" + v-model="form.subnetMask" + type="text" + :state="getValidationState($v.form.subnetMask)" + @input="$v.form.subnetMask.$touch()" + /> + <b-form-invalid-feedback role="alert"> + <template v-if="!$v.form.subnetMask.required"> + {{ $t('global.form.fieldRequired') }} + </template> + <template v-if="!$v.form.subnetMask.ipAddress"> + {{ $t('global.form.invalidFormat') }} + </template> + </b-form-invalid-feedback> + </b-form-group> + </b-col> + </b-row> + </b-form> + <template #modal-footer="{ cancel }"> + <b-button variant="secondary" @click="cancel()"> + {{ $t('global.action.cancel') }} + </b-button> + <b-button form="form-ipv4" type="submit" variant="primary" @click="onOk"> + {{ $t('global.action.add') }} + </b-button> + </template> + </b-modal> +</template> + +<script> +import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; +import { ipAddress, required } from 'vuelidate/lib/validators'; + +export default { + mixins: [VuelidateMixin], + props: { + defaultGateway: { + type: String, + default: '', + }, + }, + data() { + return { + form: { + ipAddress: '', + gateway: '', + subnetMask: '', + }, + }; + }, + watch: { + defaultGateway() { + this.form.gateway = this.defaultGateway; + }, + }, + validations() { + return { + form: { + ipAddress: { + required, + ipAddress, + }, + gateway: { + required, + ipAddress, + }, + subnetMask: { + required, + ipAddress, + }, + }, + }; + }, + methods: { + handleSubmit() { + this.$v.$touch(); + if (this.$v.$invalid) return; + this.$emit('ok', { + Address: this.form.ipAddress, + Gateway: this.form.gateway, + SubnetMask: this.form.subnetMask, + }); + this.closeModal(); + }, + closeModal() { + this.$nextTick(() => { + this.$refs.modal.hide(); + }); + }, + resetForm() { + this.form.ipAddress = null; + this.form.gateway = this.defaultGateway; + this.form.subnetMask = null; + this.$v.$reset(); + this.$emit('hidden'); + }, + onOk(bvModalEvt) { + // prevent modal close + bvModalEvt.preventDefault(); + this.handleSubmit(); + }, + }, +}; +</script> diff --git a/src/views/_ibs/Settings/Network/ModalMacAddress.vue b/src/views/_ibs/Settings/Network/ModalMacAddress.vue new file mode 100644 index 00000000..d563f4ce --- /dev/null +++ b/src/views/_ibs/Settings/Network/ModalMacAddress.vue @@ -0,0 +1,109 @@ +<template> + <b-modal + id="modal-mac-address" + ref="modal" + :title="$t('pageNetwork.modal.editMacAddressTitle')" + @hidden="resetForm" + > + <b-form id="mac-settings" @submit.prevent="handleSubmit"> + <b-row> + <b-col sm="6"> + <b-form-group + :label="$t('pageNetwork.macAddress')" + label-for="macAddress" + > + <b-form-input + id="mac-address" + v-model.trim="form.macAddress" + data-test-id="network-input-macAddress" + type="text" + :state="getValidationState($v.form.macAddress)" + @change="$v.form.macAddress.$touch()" + /> + <b-form-invalid-feedback role="alert"> + <div v-if="!$v.form.macAddress.required"> + {{ $t('global.form.fieldRequired') }} + </div> + <div v-if="!$v.form.macAddress.macAddress"> + {{ $t('global.form.invalidFormat') }} + </div> + </b-form-invalid-feedback> + </b-form-group> + </b-col> + </b-row> + </b-form> + <template #modal-footer="{ cancel }"> + <b-button variant="secondary" @click="cancel()"> + {{ $t('global.action.cancel') }} + </b-button> + <b-button + form="mac-settings" + type="submit" + variant="primary" + @click="onOk" + > + {{ $t('global.action.add') }} + </b-button> + </template> + </b-modal> +</template> + +<script> +import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; +import { macAddress, required } from 'vuelidate/lib/validators'; + +export default { + mixins: [VuelidateMixin], + props: { + macAddress: { + type: String, + default: '', + }, + }, + data() { + return { + form: { + macAddress: '', + }, + }; + }, + watch: { + macAddress() { + this.form.macAddress = this.macAddress; + }, + }, + validations() { + return { + form: { + macAddress: { + required, + macAddress: macAddress(), + }, + }, + }; + }, + methods: { + handleSubmit() { + this.$v.$touch(); + if (this.$v.$invalid) return; + this.$emit('ok', { MACAddress: this.form.macAddress }); + this.closeModal(); + }, + closeModal() { + this.$nextTick(() => { + this.$refs.modal.hide(); + }); + }, + resetForm() { + this.form.macAddress = this.macAddress; + this.$v.$reset(); + this.$emit('hidden'); + }, + onOk(bvModalEvt) { + // prevent modal close + bvModalEvt.preventDefault(); + this.handleSubmit(); + }, + }, +}; +</script> diff --git a/src/views/_ibs/Settings/Network/Network.vue b/src/views/_ibs/Settings/Network/Network.vue new file mode 100644 index 00000000..2abbcd7a --- /dev/null +++ b/src/views/_ibs/Settings/Network/Network.vue @@ -0,0 +1,167 @@ +<template> + <b-container fluid="xl"> + <page-title :description="$t('pageNetwork.pageDescription')" /> + <!-- Global settings for all interfaces --> + <network-global-settings /> + <!-- Interface tabs --> + <page-section v-show="ethernetData"> + <b-row> + <b-col> + <b-card no-body> + <b-tabs + active-nav-item-class="font-weight-bold" + card + content-class="mt-3" + > + <b-tab + v-for="(data, index) in ethernetData" + :key="data.Id" + :title="data.Id" + @click="getTabIndex(index)" + > + <!-- Interface settings --> + <network-interface-settings :tab-index="tabIndex" /> + <!-- IPV4 table --> + <table-ipv-4 :tab-index="tabIndex" /> + <!-- Static DNS table --> + <table-dns :tab-index="tabIndex" /> + </b-tab> + </b-tabs> + </b-card> + </b-col> + </b-row> + </page-section> + <!-- Modals --> + <modal-ipv4 :default-gateway="defaultGateway" @ok="saveIpv4Address" /> + <modal-dns @ok="saveDnsAddress" /> + <modal-hostname :hostname="currentHostname" @ok="saveSettings" /> + <modal-mac-address :mac-address="currentMacAddress" @ok="saveSettings" /> + </b-container> +</template> + +<script> +import BVToastMixin from '@/components/Mixins/BVToastMixin'; +import DataFormatterMixin from '@/components/Mixins/DataFormatterMixin'; +import LoadingBarMixin, { loading } from '@/components/Mixins/LoadingBarMixin'; +import ModalMacAddress from './ModalMacAddress.vue'; +import ModalHostname from './ModalHostname.vue'; +import ModalIpv4 from './ModalIpv4.vue'; +import ModalDns from './ModalDns.vue'; +import NetworkGlobalSettings from './NetworkGlobalSettings.vue'; +import NetworkInterfaceSettings from './NetworkInterfaceSettings.vue'; +import PageSection from '@/components/Global/PageSection'; +import PageTitle from '@/components/Global/PageTitle'; +import TableIpv4 from './TableIpv4.vue'; +import TableDns from './TableDns.vue'; +import { mapState } from 'vuex'; + +export default { + name: 'Network', + components: { + ModalHostname, + ModalMacAddress, + ModalIpv4, + ModalDns, + NetworkGlobalSettings, + NetworkInterfaceSettings, + PageSection, + PageTitle, + TableDns, + TableIpv4, + }, + mixins: [BVToastMixin, DataFormatterMixin, LoadingBarMixin], + beforeRouteLeave(to, from, next) { + this.hideLoader(); + next(); + }, + data() { + return { + currentHostname: '', + currentMacAddress: '', + defaultGateway: '', + loading, + tabIndex: 0, + }; + }, + computed: { + ...mapState('network', ['ethernetData']), + }, + watch: { + ethernetData() { + this.getModalInfo(); + }, + }, + created() { + this.startLoader(); + const globalSettings = new Promise((resolve) => { + this.$root.$on('network-global-settings-complete', () => resolve()); + }); + const interfaceSettings = new Promise((resolve) => { + this.$root.$on('network-interface-settings-complete', () => resolve()); + }); + const networkTableDns = new Promise((resolve) => { + this.$root.$on('network-table-dns-complete', () => resolve()); + }); + const networkTableIpv4 = new Promise((resolve) => { + this.$root.$on('network-table-ipv4-complete', () => resolve()); + }); + // Combine all child component Promises to indicate + // when page data load complete + Promise.all([ + this.$store.dispatch('network/getEthernetData'), + globalSettings, + interfaceSettings, + networkTableDns, + networkTableIpv4, + ]).finally(() => this.endLoader()); + }, + methods: { + getModalInfo() { + this.defaultGateway = this.$store.getters[ + 'network/globalNetworkSettings' + ][this.tabIndex].defaultGateway; + + this.currentHostname = this.$store.getters[ + 'network/globalNetworkSettings' + ][this.tabIndex].hostname; + + this.currentMacAddress = this.$store.getters[ + 'network/globalNetworkSettings' + ][this.tabIndex].macAddress; + }, + getTabIndex(selectedIndex) { + this.tabIndex = selectedIndex; + this.$store.dispatch('network/setSelectedTabIndex', this.tabIndex); + this.$store.dispatch( + 'network/setSelectedTabId', + this.ethernetData[selectedIndex].Id + ); + this.getModalInfo(); + }, + saveIpv4Address(modalFormData) { + this.startLoader(); + this.$store + .dispatch('network/saveIpv4Address', modalFormData) + .then((message) => this.successToast(message)) + .catch(({ message }) => this.errorToast(message)) + .finally(() => this.endLoader()); + }, + saveDnsAddress(modalFormData) { + this.startLoader(); + this.$store + .dispatch('network/saveDnsAddress', modalFormData) + .then((message) => this.successToast(message)) + .catch(({ message }) => this.errorToast(message)) + .finally(() => this.endLoader()); + }, + saveSettings(modalFormData) { + this.startLoader(); + this.$store + .dispatch('network/saveSettings', modalFormData) + .then((message) => this.successToast(message)) + .catch(({ message }) => this.errorToast(message)) + .finally(() => this.endLoader()); + }, + }, +}; +</script> diff --git a/src/views/_ibs/Settings/Network/NetworkGlobalSettings.vue b/src/views/_ibs/Settings/Network/NetworkGlobalSettings.vue new file mode 100644 index 00000000..30287673 --- /dev/null +++ b/src/views/_ibs/Settings/Network/NetworkGlobalSettings.vue @@ -0,0 +1,161 @@ +<template> + <page-section + v-if="firstInterface" + :section-title="$t('pageNetwork.networkSettings')" + > + <b-row> + <b-col md="3"> + <dl> + <dt> + {{ $t('pageNetwork.hostname') }} + <b-button variant="link" class="p-1" @click="initSettingsModal()"> + <icon-edit :title="$t('pageNetwork.modal.editHostnameTitle')" /> + </b-button> + </dt> + <dd>{{ dataFormatter(firstInterface.hostname) }}</dd> + </dl> + </b-col> + <b-col md="3"> + <dl> + <dt>{{ $t('pageNetwork.useDomainName') }}</dt> + <dd> + <b-form-checkbox + id="useDomainNameSwitch" + v-model="useDomainNameState" + data-test-id="networkSettings-switch-useDomainName" + switch + @change="changeDomainNameState" + > + <span v-if="useDomainNameState"> + {{ $t('global.status.enabled') }} + </span> + <span v-else>{{ $t('global.status.disabled') }}</span> + </b-form-checkbox> + </dd> + </dl> + </b-col> + <b-col md="3"> + <dl> + <dt>{{ $t('pageNetwork.useDns') }}</dt> + <dd> + <b-form-checkbox + id="useDnsSwitch" + v-model="useDnsState" + data-test-id="networkSettings-switch-useDns" + switch + @change="changeDnsState" + > + <span v-if="useDnsState"> + {{ $t('global.status.enabled') }} + </span> + <span v-else>{{ $t('global.status.disabled') }}</span> + </b-form-checkbox> + </dd> + </dl> + </b-col> + <b-col md="3"> + <dl> + <dt>{{ $t('pageNetwork.useNtp') }}</dt> + <dd> + <b-form-checkbox + id="useNtpSwitch" + v-model="useNtpState" + data-test-id="networkSettings-switch-useNtp" + switch + @change="changeNtpState" + > + <span v-if="useNtpState"> + {{ $t('global.status.enabled') }} + </span> + <span v-else>{{ $t('global.status.disabled') }}</span> + </b-form-checkbox> + </dd> + </dl> + </b-col> + </b-row> + </page-section> +</template> + +<script> +import BVToastMixin from '@/components/Mixins/BVToastMixin'; +import IconEdit from '@carbon/icons-vue/es/edit/16'; +import DataFormatterMixin from '@/components/Mixins/DataFormatterMixin'; +import PageSection from '@/components/Global/PageSection'; +import { mapState } from 'vuex'; + +export default { + name: 'GlobalNetworkSettings', + components: { IconEdit, PageSection }, + mixins: [BVToastMixin, DataFormatterMixin], + + data() { + return { + hostname: '', + }; + }, + computed: { + ...mapState('network', ['ethernetData']), + firstInterface() { + return this.$store.getters['network/globalNetworkSettings'][0]; + }, + useDomainNameState: { + get() { + return this.$store.getters['network/globalNetworkSettings'][0] + .useDomainNameEnabled; + }, + set(newValue) { + return newValue; + }, + }, + useDnsState: { + get() { + return this.$store.getters['network/globalNetworkSettings'][0] + .useDnsEnabled; + }, + set(newValue) { + return newValue; + }, + }, + useNtpState: { + get() { + return this.$store.getters['network/globalNetworkSettings'][0] + .useNtpEnabled; + }, + set(newValue) { + return newValue; + }, + }, + }, + created() { + this.$store.dispatch('network/getEthernetData').finally(() => { + // Emit initial data fetch complete to parent component + this.$root.$emit('network-global-settings-complete'); + }); + }, + methods: { + changeDomainNameState(state) { + this.$store + .dispatch('network/saveDomainNameState', state) + .then((success) => { + this.successToast(success); + }) + .catch(({ message }) => this.errorToast(message)); + }, + changeDnsState(state) { + this.$store + .dispatch('network/saveDnsState', state) + .then((message) => this.successToast(message)) + .catch(({ message }) => this.errorToast(message)); + }, + changeNtpState(state) { + this.$store + .dispatch('network/saveNtpState', state) + .then((message) => this.successToast(message)) + .catch(({ message }) => this.errorToast(message)); + }, + initSettingsModal() { + this.$bvModal.show('modal-hostname'); + }, + }, +}; +</script> diff --git a/src/views/_ibs/Settings/Network/NetworkInterfaceSettings.vue b/src/views/_ibs/Settings/Network/NetworkInterfaceSettings.vue new file mode 100644 index 00000000..023d29bc --- /dev/null +++ b/src/views/_ibs/Settings/Network/NetworkInterfaceSettings.vue @@ -0,0 +1,117 @@ +<template> + <div> + <page-section> + <b-row> + <b-col md="3"> + <dl> + <dt>{{ $t('pageNetwork.linkStatus') }}</dt> + <dd> + {{ dataFormatter(linkStatus) }} + </dd> + </dl> + </b-col> + <b-col md="3"> + <dl> + <dt>{{ $t('pageNetwork.speed') }}</dt> + <dd> + {{ dataFormatter(linkSpeed) }} + </dd> + </dl> + </b-col> + </b-row> + </page-section> + <page-section :section-title="$t('pageNetwork.interfaceSection')"> + <b-row> + <b-col md="3"> + <dl> + <dt> + {{ $t('pageNetwork.fqdn') }} + </dt> + <dd> + {{ dataFormatter(fqdn) }} + </dd> + </dl> + </b-col> + <b-col md="3"> + <dl class="text-nowrap"> + <dt> + {{ $t('pageNetwork.macAddress') }} + <b-button + variant="link" + class="p-1" + @click="initMacAddressModal()" + > + <icon-edit + :title="$t('pageNetwork.modal.editMacAddressTitle')" + /> + </b-button> + </dt> + <dd> + {{ dataFormatter(macAddress) }} + </dd> + </dl> + </b-col> + </b-row> + </page-section> + </div> +</template> + +<script> +import BVToastMixin from '@/components/Mixins/BVToastMixin'; +import IconEdit from '@carbon/icons-vue/es/edit/16'; +import PageSection from '@/components/Global/PageSection'; +import DataFormatterMixin from '@/components/Mixins/DataFormatterMixin'; +import { mapState } from 'vuex'; + +export default { + name: 'Ipv4Table', + components: { + IconEdit, + PageSection, + }, + mixins: [BVToastMixin, DataFormatterMixin], + props: { + tabIndex: { + type: Number, + default: 0, + }, + }, + data() { + return { + selectedInterface: '', + linkStatus: '', + linkSpeed: '', + fqdn: '', + macAddress: '', + }; + }, + computed: { + ...mapState('network', ['ethernetData']), + }, + watch: { + // Watch for change in tab index + tabIndex() { + this.getSettings(); + }, + }, + created() { + this.getSettings(); + this.$store.dispatch('network/getEthernetData').finally(() => { + // Emit initial data fetch complete to parent component + this.$root.$emit('network-interface-settings-complete'); + }); + }, + methods: { + getSettings() { + this.selectedInterface = this.tabIndex; + this.linkStatus = this.ethernetData[this.selectedInterface].LinkStatus; + this.linkSpeed = this.ethernetData[this.selectedInterface].SpeedMbps; + this.fqdn = this.ethernetData[this.selectedInterface].FQDN; + this.macAddress = this.ethernetData[this.selectedInterface].MACAddress; + }, + initMacAddressModal() { + this.$bvModal.show('modal-mac-address'); + }, + }, +}; +</script> diff --git a/src/views/_ibs/Settings/Network/TableDns.vue b/src/views/_ibs/Settings/Network/TableDns.vue new file mode 100644 index 00000000..569109f1 --- /dev/null +++ b/src/views/_ibs/Settings/Network/TableDns.vue @@ -0,0 +1,145 @@ +<template> + <page-section :section-title="$t('pageNetwork.staticDns')"> + <b-row> + <b-col lg="6"> + <div class="text-right"> + <b-button variant="primary" @click="initDnsModal()"> + <icon-add /> + {{ $t('pageNetwork.table.addDnsAddress') }} + </b-button> + </div> + <b-table + responsive="md" + hover + :fields="dnsTableFields" + :items="form.dnsStaticTableItems" + :empty-text="$t('global.table.emptyMessage')" + class="mb-0" + show-empty + > + <template #cell(actions)="{ item, index }"> + <table-row-action + v-for="(action, actionIndex) in item.actions" + :key="actionIndex" + :value="action.value" + :title="action.title" + :enabled="action.enabled" + @click-table-action="onDnsTableAction(action, $event, index)" + > + <template #icon> + <icon-edit v-if="action.value === 'edit'" /> + <icon-trashcan v-if="action.value === 'delete'" /> + </template> + </table-row-action> + </template> + </b-table> + </b-col> + </b-row> + </page-section> +</template> + +<script> +import BVToastMixin from '@/components/Mixins/BVToastMixin'; +import IconAdd from '@carbon/icons-vue/es/add--alt/20'; +import IconEdit from '@carbon/icons-vue/es/edit/20'; +import IconTrashcan from '@carbon/icons-vue/es/trash-can/20'; +import PageSection from '@/components/Global/PageSection'; +import TableRowAction from '@/components/Global/TableRowAction'; +import { mapState } from 'vuex'; + +export default { + name: 'DNSTable', + components: { + IconAdd, + IconEdit, + IconTrashcan, + PageSection, + TableRowAction, + }, + mixins: [BVToastMixin], + props: { + tabIndex: { + type: Number, + default: 0, + }, + }, + data() { + return { + form: { + dnsStaticTableItems: [], + }, + actions: [ + { + value: 'edit', + title: this.$t('global.action.edit'), + }, + { + value: 'delete', + title: this.$t('global.action.delete'), + }, + ], + dnsTableFields: [ + { + key: 'address', + label: this.$t('pageNetwork.table.ipAddress'), + }, + { key: 'actions', label: '', tdClass: 'text-right' }, + ], + }; + }, + computed: { + ...mapState('network', ['ethernetData']), + }, + watch: { + // Watch for change in tab index + tabIndex() { + this.getStaticDnsItems(); + }, + ethernetData() { + this.getStaticDnsItems(); + }, + }, + created() { + this.getStaticDnsItems(); + this.$store.dispatch('network/getEthernetData').finally(() => { + // Emit initial data fetch complete to parent component + this.$root.$emit('network-table-dns-complete'); + }); + }, + methods: { + getStaticDnsItems() { + const index = this.tabIndex; + const dns = this.ethernetData[index].StaticNameServers || []; + this.form.dnsStaticTableItems = dns.map((server) => { + return { + address: server, + actions: [ + { + value: 'delete', + title: this.$t('pageNetwork.table.deleteDns'), + }, + ], + }; + }); + }, + onDnsTableAction(action, $event, index) { + if ($event === 'delete') { + this.deleteDnsTableRow(index); + } + }, + deleteDnsTableRow(index) { + this.form.dnsStaticTableItems.splice(index, 1); + const newDnsArray = this.form.dnsStaticTableItems.map((dns) => { + return dns.address; + }); + this.$store + .dispatch('network/editDnsAddress', newDnsArray) + .then((message) => this.successToast(message)) + .catch(({ message }) => this.errorToast(message)); + }, + initDnsModal() { + this.$bvModal.show('modal-dns'); + }, + }, +}; +</script> diff --git a/src/views/_ibs/Settings/Network/TableIpv4.vue b/src/views/_ibs/Settings/Network/TableIpv4.vue new file mode 100644 index 00000000..75870031 --- /dev/null +++ b/src/views/_ibs/Settings/Network/TableIpv4.vue @@ -0,0 +1,169 @@ +<template> + <page-section :section-title="$t('pageNetwork.ipv4')"> + <b-row> + <b-col> + <h3 class="h5"> + {{ $t('pageNetwork.ipv4Addresses') }} + </h3> + </b-col> + <b-col class="text-right"> + <b-button variant="primary" @click="initAddIpv4Address()"> + <icon-add /> + {{ $t('pageNetwork.table.addIpv4Address') }} + </b-button> + </b-col> + </b-row> + <b-table + responsive="md" + hover + :fields="ipv4TableFields" + :items="form.ipv4TableItems" + :empty-text="$t('global.table.emptyMessage')" + class="mb-0" + show-empty + > + <template #cell(actions)="{ item, index }"> + <table-row-action + v-for="(action, actionIndex) in item.actions" + :key="actionIndex" + :value="action.value" + :title="action.title" + :enabled="action.enabled" + @click-table-action="onIpv4TableAction(action, $event, index)" + > + <template #icon> + <icon-edit v-if="action.value === 'edit'" /> + <icon-trashcan v-if="action.value === 'delete'" /> + </template> + </table-row-action> + </template> + </b-table> + </page-section> +</template> + +<script> +import BVToastMixin from '@/components/Mixins/BVToastMixin'; +import IconAdd from '@carbon/icons-vue/es/add--alt/20'; +import IconEdit from '@carbon/icons-vue/es/edit/20'; +import IconTrashcan from '@carbon/icons-vue/es/trash-can/20'; +import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin'; +import PageSection from '@/components/Global/PageSection'; +import TableRowAction from '@/components/Global/TableRowAction'; +import { mapState } from 'vuex'; + +export default { + name: 'Ipv4Table', + components: { + IconAdd, + IconEdit, + IconTrashcan, + PageSection, + TableRowAction, + }, + mixins: [BVToastMixin, LoadingBarMixin], + props: { + tabIndex: { + type: Number, + default: 0, + }, + }, + data() { + return { + form: { + ipv4TableItems: [], + }, + actions: [ + { + value: 'edit', + title: this.$t('global.action.edit'), + }, + { + value: 'delete', + title: this.$t('global.action.delete'), + }, + ], + ipv4TableFields: [ + { + key: 'Address', + label: this.$t('pageNetwork.table.ipAddress'), + }, + { + key: 'Gateway', + label: this.$t('pageNetwork.table.gateway'), + }, + { + key: 'SubnetMask', + label: this.$t('pageNetwork.table.subnet'), + }, + { + key: 'AddressOrigin', + label: this.$t('pageNetwork.table.addressOrigin'), + }, + { key: 'actions', label: '', tdClass: 'text-right' }, + ], + }; + }, + computed: { + ...mapState('network', ['ethernetData']), + }, + watch: { + // Watch for change in tab index + tabIndex() { + this.getIpv4TableItems(); + }, + ethernetData() { + this.getIpv4TableItems(); + }, + }, + created() { + this.getIpv4TableItems(); + this.$store.dispatch('network/getEthernetData').finally(() => { + // Emit initial data fetch complete to parent component + this.$root.$emit('network-table-ipv4-complete'); + }); + }, + methods: { + getIpv4TableItems() { + const index = this.tabIndex; + const addresses = this.ethernetData[index].IPv4Addresses || []; + this.form.ipv4TableItems = addresses.map((ipv4) => { + return { + Address: ipv4.Address, + SubnetMask: ipv4.SubnetMask, + Gateway: ipv4.Gateway, + AddressOrigin: ipv4.AddressOrigin, + actions: [ + { + value: 'delete', + title: this.$t('pageNetwork.table.deleteIpv4'), + }, + ], + }; + }); + }, + onIpv4TableAction(action, $event, index) { + if ($event === 'delete') { + this.deleteIpv4TableRow(index); + } + }, + deleteIpv4TableRow(index) { + this.form.ipv4TableItems.splice(index, 1); + const newIpv4Array = this.form.ipv4TableItems.map((ipv4) => { + const { Address, SubnetMask, Gateway } = ipv4; + return { + Address, + SubnetMask, + Gateway, + }; + }); + this.$store + .dispatch('network/editIpv4Address', newIpv4Array) + .then((message) => this.successToast(message)) + .catch(({ message }) => this.errorToast(message)); + }, + initAddIpv4Address() { + this.$bvModal.show('modal-add-ipv4'); + }, + }, +}; +</script> diff --git a/src/views/_ibs/Settings/Network/index.js b/src/views/_ibs/Settings/Network/index.js new file mode 100644 index 00000000..97bf0397 --- /dev/null +++ b/src/views/_ibs/Settings/Network/index.js @@ -0,0 +1,2 @@ +import Network from './Network.vue'; +export default Network; diff --git a/src/views/_ibs/Settings/PowerRestorePolicy/PowerRestorePolicy.vue b/src/views/_ibs/Settings/PowerRestorePolicy/PowerRestorePolicy.vue new file mode 100644 index 00000000..06e30f3e --- /dev/null +++ b/src/views/_ibs/Settings/PowerRestorePolicy/PowerRestorePolicy.vue @@ -0,0 +1,91 @@ +<template> + <b-container fluid="xl"> + <page-title :description="$t('pagePowerRestorePolicy.description')" /> + + <b-row> + <b-col sm="8" md="6" xl="12"> + <b-form-group :label="$t('pagePowerRestorePolicy.powerPoliciesLabel')"> + <b-form-radio-group + v-model="currentPowerRestorePolicy" + :options="options" + name="power-restore-policy" + ></b-form-radio-group> + </b-form-group> + </b-col> + </b-row> + + <b-button variant="primary" type="submit" @click="submitForm"> + {{ $t('global.action.saveSettings') }} + </b-button> + </b-container> +</template> + +<script> +import PageTitle from '@/components/Global/PageTitle'; +import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin'; +import VuelidateMixin from '@/components/Mixins/VuelidateMixin.js'; +import BVToastMixin from '@/components/Mixins/BVToastMixin'; + +export default { + name: 'PowerRestorePolicy', + components: { PageTitle }, + mixins: [VuelidateMixin, BVToastMixin, LoadingBarMixin], + beforeRouteLeave(to, from, next) { + this.hideLoader(); + next(); + }, + data() { + return { + policyValue: null, + options: [], + }; + }, + computed: { + powerRestorePolicies() { + return this.$store.getters['powerPolicy/powerRestorePolicies']; + }, + currentPowerRestorePolicy: { + get() { + return this.$store.getters['powerPolicy/powerRestoreCurrentPolicy']; + }, + set(policy) { + this.policyValue = policy; + }, + }, + }, + created() { + this.startLoader(); + this.renderPowerRestoreSettings(); + }, + methods: { + renderPowerRestoreSettings() { + Promise.all([ + this.$store.dispatch('powerPolicy/getPowerRestorePolicies'), + this.$store.dispatch('powerPolicy/getPowerRestoreCurrentPolicy'), + ]).finally(() => { + this.options.length = 0; + this.powerRestorePolicies.map((item) => { + this.options.push({ + text: this.$t(`pagePowerRestorePolicy.policiesDesc.${item.state}`), + value: `${item.state}`, + }); + }); + this.endLoader(); + }); + }, + submitForm() { + this.startLoader(); + this.$store + .dispatch( + 'powerPolicy/setPowerRestorePolicy', + this.policyValue || this.currentPowerRestorePolicy + ) + .then((message) => this.successToast(message)) + .catch(({ message }) => this.errorToast(message)) + .finally(() => { + this.renderPowerRestoreSettings(); + }); + }, + }, +}; +</script> diff --git a/src/views/_ibs/Settings/PowerRestorePolicy/index.js b/src/views/_ibs/Settings/PowerRestorePolicy/index.js new file mode 100644 index 00000000..fab0d477 --- /dev/null +++ b/src/views/_ibs/Settings/PowerRestorePolicy/index.js @@ -0,0 +1,2 @@ +import PowerRestorePolicy from './PowerRestorePolicy.vue'; +export default PowerRestorePolicy; |