diff options
author | Dixsie Wolmers <dixsie@ibm.com> | 2021-10-08 00:15:50 +0300 |
---|---|---|
committer | Dixsie Wolmers <dixsiew@gmail.com> | 2021-12-03 23:45:37 +0300 |
commit | c4b8757ed88ecea369e6044548d2fbe072d5bd4a (patch) | |
tree | 6999c7a29a7a3eea03f4a096ee827c8b18acc124 /src/views/Settings | |
parent | cc79a53192de73457cb4c8c3350d896d952bb106 (diff) | |
download | webui-vue-c4b8757ed88ecea369e6044548d2fbe072d5bd4a.tar.xz |
Network settings redesign - interface settings
First commit of the network settings redesign:
- Adds the global network settings section for DHCP settings
- Adds read only hostname, FQDN and MAC address,
modal to edit each will be done seperately
- Removes interface specific sections to refactor in next commit
- Adds tab component to display ethernet data by interface
- Ability to edit, delete and add ipv4 addresses and DNS will
be done in separate commit
Signed-off-by: Dixsie Wolmers <dixsie@ibm.com>
Change-Id: Ibb1db6894ee697fec9e6ea1b8312d041c61faaad
Diffstat (limited to 'src/views/Settings')
-rw-r--r-- | src/views/Settings/Network/Network.vue | 683 | ||||
-rw-r--r-- | src/views/Settings/Network/NetworkGlobalSettings.vue | 152 | ||||
-rw-r--r-- | src/views/Settings/Network/NetworkInterfaceSettings.vue | 99 | ||||
-rw-r--r-- | src/views/Settings/Network/TableDns.vue | 126 | ||||
-rw-r--r-- | src/views/Settings/Network/TableIpv4.vue | 146 |
5 files changed, 584 insertions, 622 deletions
diff --git a/src/views/Settings/Network/Network.vue b/src/views/Settings/Network/Network.vue index ab5003f8..918c8e98 100644 --- a/src/views/Settings/Network/Network.vue +++ b/src/views/Settings/Network/Network.vue @@ -1,663 +1,102 @@ <template> <b-container fluid="xl"> <page-title :description="$t('pageNetwork.pageDescription')" /> - <page-section :section-title="$t('pageNetwork.interface')"> + <!-- Global settings for all interfaces --> + <network-global-settings /> + <!-- Interface tabs --> + <page-section> <b-row> - <b-col lg="3"> - <b-form-group - label-for="interface-select" - :label="$t('pageNetwork.form.networkInterface')" - > - <b-form-select - id="interface-select" - v-model="selectedInterfaceIndex" - :disabled="loading" - data-test-id="network-select-interface" - :options="interfaceSelectOptions" - @change="selectInterface" + <b-col> + <b-card no-body> + <b-tabs + active-nav-item-class="font-weight-bold" + card + content-class="mt-3" > - </b-form-select> - </b-form-group> + <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> - <b-form novalidate @submit.prevent="submitForm"> - <b-form-group :disabled="loading"> - <page-section :section-title="$t('pageNetwork.system')"> - <b-row> - <b-col lg="3"> - <b-form-group - :label="$t('pageNetwork.form.defaultGateway')" - label-for="default-gateway" - > - <b-form-input - id="default-gateway" - v-model.trim="form.gateway" - data-test-id="network-input-gateway" - type="text" - :state="getValidationState($v.form.gateway)" - @change="$v.form.gateway.$touch()" - /> - <b-form-invalid-feedback role="alert"> - <div v-if="!$v.form.gateway.required"> - {{ $t('global.form.fieldRequired') }} - </div> - <div v-if="!$v.form.gateway.ipAddress"> - {{ $t('global.form.invalidFormat') }} - </div> - </b-form-invalid-feedback> - </b-form-group> - </b-col> - <b-col lg="3"> - <b-form-group - :label="$t('pageNetwork.form.hostname')" - label-for="hostname-field" - > - <b-form-input - id="hostname-field" - v-model.trim="form.hostname" - data-test-id="network-input-hostname" - type="text" - :state="getValidationState($v.form.hostname)" - @change="$v.form.hostname.$touch()" - /> - <b-form-invalid-feedback role="alert"> - <div v-if="!$v.form.hostname.required"> - {{ $t('global.form.fieldRequired') }} - </div> - <div v-if="!$v.form.hostname.validateHostname"> - {{ - $t('global.form.lengthMustBeBetween', { min: 1, max: 64 }) - }} - </div> - </b-form-invalid-feedback> - </b-form-group> - </b-col> - <b-col lg="3"> - <b-form-group - :label="$t('pageNetwork.form.macAddress')" - label-for="mac-address" - > - <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> - </page-section> - <page-section :section-title="$t('pageNetwork.ipv4')"> - <b-form-group :label="$t('pageNetwork.ipv4Configuration')"> - <b-form-text id="enable-secure-help-block"> - {{ $t('pageNetwork.ipv4Helper') }} - </b-form-text> - <b-form-radio - v-model="form.dhcpEnabled" - name="dhcp-radio" - :value="true" - @change="onChangeIpv4Config" - > - {{ $t('pageNetwork.dhcp') }} - </b-form-radio> - <b-form-radio - v-model="form.dhcpEnabled" - name="static-radio" - :value="false" - @change="onChangeIpv4Config" - > - {{ $t('pageNetwork.static') }} - </b-form-radio> - </b-form-group> - <b-row> - <b-col lg="9" class="mb-3"> - <h3 class="h4"> - {{ $t('pageNetwork.dhcp') }} - </h3> - <b-table - responsive="md" - hover - :fields="ipv4DhcpTableFields" - :items="form.ipv4DhcpTableItems" - :empty-text="$t('global.table.emptyMessage')" - class="mb-0" - show-empty - > - <template #cell(Address)="{ item, index }"> - <b-form-input - v-model.trim="item.Address" - :data-test-id="`network-input-dhcpIpv4-${index}`" - :aria-label=" - $t('pageNetwork.table.dhcpIpv4AddressRow') + - ' ' + - (index + 1) - " - readonly - /> - </template> - <template #cell(SubnetMask)="{ item, index }"> - <b-form-input - v-model.trim="item.SubnetMask" - :data-test-id="`network-input-subnetMask-${index}`" - :aria-label=" - $t('pageNetwork.table.dhcpIpv4SubnetRow') + - ' ' + - (index + 1) - " - readonly - /> - </template> - <template #cell(actions)="{ item, index }"> - <table-row-action - v-for="(action, actionIndex) in item.actions" - :key="actionIndex" - :value="action.value" - :title="action.title" - :enabled="false" - @click-table-action=" - onDeleteIpv4StaticTableRow($event, index) - " - > - <template #icon> - <icon-trashcan v-if="action.value === 'delete'" /> - </template> - </table-row-action> - </template> - </b-table> - </b-col> - <b-col lg="9" class="mb-3"> - <h3 class="h4"> - {{ $t('pageNetwork.static') }} - </h3> - <b-table - responsive="md" - hover - :fields="ipv4StaticTableFields" - :items="form.ipv4StaticTableItems" - :empty-text="$t('global.table.emptyMessage')" - class="mb-0" - show-empty - > - <template #cell(Address)="{ item, index }"> - <b-form-input - v-model.trim="item.Address" - :data-test-id="`network-input-staticIpv4-${index}`" - :aria-label=" - $t('pageNetwork.table.staticIpv4AddressRow') + - ' ' + - (index + 1) - " - :state=" - getValidationState( - $v.form.ipv4StaticTableItems.$each.$iter[index].Address - ) - " - @change=" - $v.form.ipv4StaticTableItems.$each.$iter[ - index - ].Address.$touch() - " - /> - <b-form-invalid-feedback role="alert"> - <div - v-if=" - !$v.form.ipv4StaticTableItems.$each.$iter[index].Address - .required - " - > - {{ $t('global.form.fieldRequired') }} - </div> - <div - v-if=" - !$v.form.ipv4StaticTableItems.$each.$iter[index].Address - .ipAddress - " - > - {{ $t('global.form.invalidFormat') }} - </div> - </b-form-invalid-feedback> - </template> - <template #cell(SubnetMask)="{ item, index }"> - <b-form-input - v-model.trim="item.SubnetMask" - :data-test-id="`network-input-subnetMask-${index}`" - :aria-label=" - $t('pageNetwork.table.staticIpv4SubnetRow') + - ' ' + - (index + 1) - " - :state=" - getValidationState( - $v.form.ipv4StaticTableItems.$each.$iter[index] - .SubnetMask - ) - " - @change=" - $v.form.ipv4StaticTableItems.$each.$iter[ - index - ].SubnetMask.$touch() - " - /> - <b-form-invalid-feedback role="alert"> - <div - v-if=" - !$v.form.ipv4StaticTableItems.$each.$iter[index] - .SubnetMask.required - " - > - {{ $t('global.form.fieldRequired') }} - </div> - <div - v-if=" - !$v.form.ipv4StaticTableItems.$each.$iter[index] - .SubnetMask.ipAddress - " - > - {{ $t('global.form.invalidFormat') }} - </div> - </b-form-invalid-feedback> - </template> - <template #cell(actions)="{ item, index }"> - <table-row-action - v-for="(action, actionIndex) in item.actions" - :key="actionIndex" - :value="action.value" - :title="action.title" - @click-table-action=" - onDeleteIpv4StaticTableRow($event, index) - " - > - <template #icon> - <icon-trashcan v-if="action.value === 'delete'" /> - </template> - </table-row-action> - </template> - </b-table> - <b-button variant="link" @click="addIpv4StaticTableRow"> - <icon-add /> - {{ $t('pageNetwork.table.addStaticIpv4Address') }} - </b-button> - </b-col> - </b-row> - </page-section> - <page-section :section-title="$t('pageNetwork.staticDns')"> - <b-row> - <b-col lg="4" class="mb-3"> - <b-table - responsive - hover - :fields="dnsTableFields" - :items="form.dnsStaticTableItems" - :empty-text="$t('global.table.emptyMessage')" - class="mb-0" - show-empty - > - <template #cell(address)="{ item, index }"> - <b-form-input - v-model.trim="item.address" - :data-test-id="`network-input-dnsAddress-${index}`" - :aria-label=" - $t('pageNetwork.table.staticDnsRow') + ' ' + (index + 1) - " - :state=" - getValidationState( - $v.form.dnsStaticTableItems.$each.$iter[index].address - ) - " - @change=" - $v.form.dnsStaticTableItems.$each.$iter[ - index - ].address.$touch() - " - /> - <b-form-invalid-feedback role="alert"> - <div - v-if=" - !$v.form.dnsStaticTableItems.$each.$iter[index].address - .required - " - > - {{ $t('global.form.fieldRequired') }} - </div> - <div - v-if=" - !$v.form.dnsStaticTableItems.$each.$iter[index].address - .ipAddress - " - > - {{ $t('global.form.invalidFormat') }} - </div> - </b-form-invalid-feedback> - </template> - <template #cell(actions)="{ item, index }"> - <table-row-action - v-for="(action, actionIndex) in item.actions" - :key="actionIndex" - :value="action.value" - :title="action.title" - @click-table-action="onDeleteDnsTableRow($event, index)" - > - <template #icon> - <icon-trashcan v-if="action.value === 'delete'" /> - </template> - </table-row-action> - </template> - </b-table> - <b-button variant="link" @click="addDnsTableRow"> - <icon-add /> {{ $t('pageNetwork.table.addDns') }} - </b-button> - </b-col> - </b-row> - </page-section> - <b-button - variant="primary" - type="submit" - data-test-id="network-button-saveNetworkSettings" - > - {{ $t('global.action.saveSettings') }} - </b-button> - </b-form-group> - </b-form> </b-container> </template> <script> -import IconTrashcan from '@carbon/icons-vue/es/trash-can/20'; -import IconAdd from '@carbon/icons-vue/es/add--alt/20'; import BVToastMixin from '@/components/Mixins/BVToastMixin'; +import DataFormatterMixin from '@/components/Mixins/DataFormatterMixin'; import LoadingBarMixin, { loading } from '@/components/Mixins/LoadingBarMixin'; +import NetworkGlobalSettings from './NetworkGlobalSettings.vue'; +import NetworkInterfaceSettings from './NetworkInterfaceSettings.vue'; import PageSection from '@/components/Global/PageSection'; import PageTitle from '@/components/Global/PageTitle'; -import TableRowAction from '@/components/Global/TableRowAction'; -import VuelidateMixin from '@/components/Mixins/VuelidateMixin'; +import TableIpv4 from './TableIpv4.vue'; +import TableDns from './TableDns.vue'; import { mapState } from 'vuex'; -import { - required, - helpers, - ipAddress, - macAddress, -} from 'vuelidate/lib/validators'; - -// Hostname pattern -const validateHostname = helpers.regex('validateHostname', /^\S{0,64}$/); export default { name: 'Network', components: { - PageTitle, + NetworkGlobalSettings, + NetworkInterfaceSettings, PageSection, - TableRowAction, - IconTrashcan, - IconAdd, + PageTitle, + TableDns, + TableIpv4, }, - mixins: [BVToastMixin, VuelidateMixin, LoadingBarMixin], + mixins: [BVToastMixin, DataFormatterMixin, LoadingBarMixin], beforeRouteLeave(to, from, next) { this.hideLoader(); next(); }, data() { return { - ipv4DhcpTableFields: [ - { - key: 'Address', - label: this.$t('pageNetwork.table.ipAddress'), - }, - { - key: 'SubnetMask', - label: this.$t('pageNetwork.table.subnet'), - }, - { key: 'actions', label: '', tdClass: 'text-right' }, - ], - ipv4StaticTableFields: [ - { - key: 'Address', - label: this.$t('pageNetwork.table.ipAddress'), - }, - { - key: 'SubnetMask', - label: this.$t('pageNetwork.table.subnet'), - }, - { key: 'actions', label: '', tdClass: 'text-right' }, - ], - dnsTableFields: [ - { - key: 'address', - label: this.$t('pageNetwork.table.ipAddress'), - }, - { key: 'actions', label: '', tdClass: 'text-right' }, - ], - selectedInterfaceIndex: 0, - selectedInterface: {}, - form: { - dhcpEnabled: null, - gateway: '', - hostname: '', - macAddress: '', - ipv4StaticTableItems: [], - ipv4DhcpTableItems: [], - dnsStaticTableItems: [], - }, loading, - }; - }, - validations() { - return { - form: { - gateway: { required, ipAddress }, - hostname: { required, validateHostname }, - ipv4StaticTableItems: { - $each: { - Address: { - required, - ipAddress, - }, - SubnetMask: { - required, - ipAddress, - }, - }, - }, - macAddress: { required, macAddress: macAddress() }, - dnsStaticTableItems: { - $each: { - address: { - required, - ipAddress, - }, - }, - }, - }, + tabIndex: 0, }; }, computed: { - ...mapState('network', [ - 'ethernetData', - 'interfaceOptions', - 'defaultGateway', - ]), - interfaceSelectOptions() { - return this.interfaceOptions.map((option, index) => { - return { - text: option, - value: index, - }; - }); - }, - }, - watch: { - ethernetData: function () { - this.selectInterface(); - }, + ...mapState('network', ['ethernetData']), }, created() { this.startLoader(); - this.$store - .dispatch('network/getEthernetData') - .finally(() => this.endLoader()); + 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: { - selectInterface() { - this.selectedInterface = this.ethernetData[this.selectedInterfaceIndex]; - this.getIpv4DhcpTableItems(); - this.getIpv4StaticTableItems(); - this.getDnsStaticTableItems(); - this.getInterfaceSettings(); - }, - getInterfaceSettings() { - this.form.gateway = this.defaultGateway; - this.form.hostname = this.selectedInterface.HostName; - this.form.macAddress = this.selectedInterface.MACAddress; - this.form.dhcpEnabled = this.selectedInterface.DHCPv4.DHCPEnabled; - }, - onChangeIpv4Config(value) { - this.form.dhcpEnabled = value; - }, - getDnsStaticTableItems() { - const dns = this.selectedInterface.StaticNameServers || []; - this.form.dnsStaticTableItems = dns.map((server) => { - return { - address: server, - actions: [ - { - value: 'delete', - enabled: this.form.dhcpEnabled, - title: this.$t('pageNetwork.table.deleteDns'), - }, - ], - }; - }); - }, - addDnsTableRow() { - this.$v.form.dnsStaticTableItems.$touch(); - this.form.dnsStaticTableItems.push({ - address: '', - actions: [ - { - value: 'delete', - enabled: this.form.dhcpEnabled, - title: this.$t('pageNetwork.table.deleteDns'), - }, - ], - }); - }, - deleteDnsTableRow(index) { - this.$v.form.dnsStaticTableItems.$touch(); - this.form.dnsStaticTableItems.splice(index, 1); - }, - onDeleteDnsTableRow(action, row) { - this.deleteDnsTableRow(row); - }, - getIpv4DhcpTableItems() { - const addresses = this.selectedInterface.IPv4Addresses || []; - this.form.ipv4DhcpTableItems = addresses - .filter((ipv4) => ipv4.AddressOrigin === 'DHCP') - .map((ipv4) => { - return { - Address: ipv4.Address, - SubnetMask: ipv4.SubnetMask, - actions: [ - { - value: 'delete', - enabled: false, - title: this.$t('pageNetwork.table.deleteDhcpIpv4'), - }, - ], - }; - }); - }, - getIpv4StaticTableItems() { - const addresses = this.selectedInterface.IPv4StaticAddresses || []; - this.form.ipv4StaticTableItems = addresses.map((ipv4) => { - return { - Address: ipv4.Address, - SubnetMask: ipv4.SubnetMask, - actions: [ - { - value: 'delete', - enabled: this.form.dhcpEnabled, - title: this.$t('pageNetwork.table.deleteStaticIpv4'), - }, - ], - }; - }); - }, - addIpv4StaticTableRow() { - this.$v.form.ipv4StaticTableItems.$touch(); - this.form.ipv4StaticTableItems.push({ - Address: '', - SubnetMask: '', - actions: [ - { - value: 'delete', - enabled: this.form.dhcpEnabled, - title: this.$t('pageNetwork.table.deleteStaticIpv4'), - }, - ], - }); - }, - deleteIpv4StaticTableRow(index) { - this.$v.form.ipv4StaticTableItems.$touch(); - this.form.ipv4StaticTableItems.splice(index, 1); - }, - onDeleteIpv4StaticTableRow(action, row) { - this.deleteIpv4StaticTableRow(row); - }, - submitForm() { - this.$v.$touch(); - if (this.$v.$invalid) return; - this.startLoader(); - let networkInterfaceSelected = this.selectedInterface; - let selectedInterfaceIndex = this.selectedInterfaceIndex; - let interfaceId = networkInterfaceSelected.Id; - let isDhcpEnabled = this.form.dhcpEnabled; - let macAddress = this.form.macAddress; - let hostname = this.form.hostname; - let networkSettingsForm = { - interfaceId, - hostname, - macAddress, - selectedInterfaceIndex, - }; - // Enabling DHCP without any available IP addresses will bring network down - if (this.form.ipv4DhcpTableItems.length) { - networkSettingsForm.isDhcpEnabled = isDhcpEnabled; - } else { - networkSettingsForm.isDhcpEnabled = false; - this.errorToast(this.$t('pageNetwork.toast.errorSaveDhcpSettings')); - } - networkSettingsForm.staticIpv4 = this.form.ipv4StaticTableItems.map( - (updateIpv4) => { - delete updateIpv4.actions; - updateIpv4.Gateway = this.form.gateway; - return updateIpv4; - } - ); - networkSettingsForm.staticNameServers = this.form.dnsStaticTableItems.map( - (updateDns) => { - return updateDns.address; - } - ); - this.$store - .dispatch('network/updateInterfaceSettings', networkSettingsForm) - .then((success) => { - this.successToast(success); - }) - .catch(({ message }) => this.errorToast(message)) - .finally(() => { - this.$v.form.$reset(); - this.endLoader(); - }); + getTabIndex(selectedIndex) { + this.tabIndex = selectedIndex; }, }, }; diff --git a/src/views/Settings/Network/NetworkGlobalSettings.vue b/src/views/Settings/Network/NetworkGlobalSettings.vue new file mode 100644 index 00000000..fc82c86d --- /dev/null +++ b/src/views/Settings/Network/NetworkGlobalSettings.vue @@ -0,0 +1,152 @@ +<template> + <page-section + v-if="firstInterface" + :section-title="$t('pageNetwork.networkSettings')" + > + <b-row> + <b-col md="3"> + <dl> + <dt>{{ $t('pageNetwork.hostname') }}</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 DataFormatterMixin from '@/components/Mixins/DataFormatterMixin'; +import PageSection from '@/components/Global/PageSection'; +import { mapState } from 'vuex'; + +export default { + name: 'GlobalNetworkSettings', + components: { 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)); + }, + }, +}; +</script> diff --git a/src/views/Settings/Network/NetworkInterfaceSettings.vue b/src/views/Settings/Network/NetworkInterfaceSettings.vue new file mode 100644 index 00000000..bdcba4d8 --- /dev/null +++ b/src/views/Settings/Network/NetworkInterfaceSettings.vue @@ -0,0 +1,99 @@ +<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') }}</dt> + <dd> + {{ dataFormatter(macAddress) }} + </dd> + </dl> + </b-col> + </b-row> + </page-section> + </div> +</template> + +<script> +import BVToastMixin from '@/components/Mixins/BVToastMixin'; +import PageSection from '@/components/Global/PageSection'; +import DataFormatterMixin from '@/components/Mixins/DataFormatterMixin'; +import { mapState } from 'vuex'; + +export default { + name: 'Ipv4Table', + components: { + 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; + }, + }, +}; +</script> diff --git a/src/views/Settings/Network/TableDns.vue b/src/views/Settings/Network/TableDns.vue new file mode 100644 index 00000000..2578ba36 --- /dev/null +++ b/src/views/Settings/Network/TableDns.vue @@ -0,0 +1,126 @@ +<template> + <page-section :section-title="$t('pageNetwork.staticDns')"> + <b-row> + <b-col lg="6"> + <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 }"> + <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 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: { + 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(); + }, + }, + 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: 'edit', + title: this.$t('pageNetwork.table.editDns'), + }, + { + value: 'delete', + title: this.$t('pageNetwork.table.deleteDns'), + }, + ], + }; + }); + }, + onDnsTableAction(action, row) { + if (action === 'delete') { + this.form.dnsStaticTableItems.splice(row, 1); + // TODO: delete row in store + } + }, + }, +}; +</script> diff --git a/src/views/Settings/Network/TableIpv4.vue b/src/views/Settings/Network/TableIpv4.vue new file mode 100644 index 00000000..5e4bb7b5 --- /dev/null +++ b/src/views/Settings/Network/TableIpv4.vue @@ -0,0 +1,146 @@ +<template> + <page-section :section-title="$t('pageNetwork.ipv4')"> + <b-row> + <b-col> + <h3 class="h5"> + {{ $t('pageNetwork.ipv4Addresses') }} + </h3> + </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 }"> + <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 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: 'Ipv4Table', + components: { + IconEdit, + IconTrashcan, + PageSection, + TableRowAction, + }, + mixins: [BVToastMixin], + 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(); + }, + }, + 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: 'edit', + title: this.$t('pageNetwork.table.editIpv4'), + enabled: false, + }, + { + value: 'delete', + title: this.$t('pageNetwork.table.deleteIpv4'), + enabled: false, + }, + ], + }; + }); + }, + onIpv4TableAction(action, row) { + if (action === 'delete') { + this.form.ipv4TableItems.splice(row, 1); + // TODO: delete row in store + } + }, + }, +}; +</script> |