1<template> 2 <page-section :section-title="$t('pageNetwork.ipv4')"> 3 <b-row class="mb-4"> 4 <b-col lg="2" md="6"> 5 <dl> 6 <dt>{{ $t('pageNetwork.dhcp') }}</dt> 7 <dd> 8 <b-form-checkbox 9 id="dhcpSwitch" 10 v-model="dhcpEnabledState" 11 data-test-id="networkSettings-switch-dhcpEnabled" 12 switch 13 @change="changeDhcpEnabledState" 14 > 15 <span v-if="dhcpEnabledState"> 16 {{ $t('global.status.enabled') }} 17 </span> 18 <span v-else>{{ $t('global.status.disabled') }}</span> 19 </b-form-checkbox> 20 </dd> 21 </dl> 22 </b-col> 23 </b-row> 24 <b-row> 25 <b-col> 26 <h3 class="h5"> 27 {{ $t('pageNetwork.ipv4Addresses') }} 28 </h3> 29 </b-col> 30 <b-col class="text-end"> 31 <b-button variant="primary" @click="initAddIpv4Address()"> 32 <icon-add /> 33 {{ $t('pageNetwork.table.addIpv4Address') }} 34 </b-button> 35 </b-col> 36 </b-row> 37 <b-table 38 responsive="md" 39 hover 40 thead-class="table-light" 41 :fields="ipv4TableFields" 42 :items="form.ipv4TableItems" 43 :empty-text="$t('global.table.emptyMessage')" 44 class="mb-0" 45 show-empty 46 > 47 <template #cell(actions)="{ item, index }"> 48 <table-row-action 49 v-for="(action, actionIndex) in filteredActions(item)" 50 :key="actionIndex" 51 :value="action.value" 52 :title="action.title" 53 :enabled="action.enabled" 54 @click-table-action="onIpv4TableAction(action, $event, index)" 55 > 56 <template #icon> 57 <icon-edit v-if="action.value === 'edit'" /> 58 <icon-trashcan v-if="action.value === 'delete'" /> 59 </template> 60 </table-row-action> 61 </template> 62 </b-table> 63 <modal-ipv4 v-model="showAddIpv4" /> 64 </page-section> 65</template> 66 67<script> 68import BVToastMixin from '@/components/Mixins/BVToastMixin'; 69import IconAdd from '@carbon/icons-vue/es/add--alt/20'; 70import IconEdit from '@carbon/icons-vue/es/edit/20'; 71import IconTrashcan from '@carbon/icons-vue/es/trash-can/20'; 72import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin'; 73import PageSection from '@/components/Global/PageSection'; 74import TableRowAction from '@/components/Global/TableRowAction'; 75import ModalIpv4 from './ModalIpv4.vue'; 76import { mapState } from 'vuex'; 77import { useI18n } from 'vue-i18n'; 78import i18n from '@/i18n'; 79import { useModal } from 'bootstrap-vue-next'; 80 81export default { 82 name: 'Ipv4Table', 83 components: { 84 IconAdd, 85 IconEdit, 86 IconTrashcan, 87 PageSection, 88 TableRowAction, 89 ModalIpv4, 90 }, 91 mixins: [BVToastMixin, LoadingBarMixin], 92 props: { 93 tabIndex: { 94 type: Number, 95 default: 0, 96 }, 97 }, 98 setup() { 99 const bvModal = useModal(); 100 return { bvModal }; 101 }, 102 data() { 103 return { 104 $t: useI18n().t, 105 showAddIpv4: false, 106 form: { 107 ipv4TableItems: [], 108 }, 109 actions: [ 110 { 111 value: 'edit', 112 title: i18n.global.t('global.action.edit'), 113 }, 114 { 115 value: 'delete', 116 title: i18n.global.t('global.action.delete'), 117 }, 118 ], 119 ipv4TableFields: [ 120 { 121 key: 'Address', 122 label: i18n.global.t('pageNetwork.table.ipAddress'), 123 }, 124 { 125 key: 'Gateway', 126 label: i18n.global.t('pageNetwork.table.gateway'), 127 }, 128 { 129 key: 'SubnetMask', 130 label: i18n.global.t('pageNetwork.table.subnet'), 131 }, 132 { 133 key: 'AddressOrigin', 134 label: i18n.global.t('pageNetwork.table.addressOrigin'), 135 }, 136 { key: 'actions', label: '', tdClass: 'text-end' }, 137 ], 138 }; 139 }, 140 computed: { 141 ...mapState('network', ['ethernetData']), 142 selectedInterface() { 143 return this.$store.getters['network/selectedInterfaceIndex']; 144 }, 145 dhcpEnabledState: { 146 get() { 147 return this.$store.getters['network/globalNetworkSettings'][ 148 this.selectedInterface 149 ].dhcpEnabled; 150 }, 151 set(newValue) { 152 return newValue; 153 }, 154 }, 155 filteredActions() { 156 return (item) => { 157 if (item.AddressOrigin === 'DHCP') { 158 return item.actions.filter((action) => action.value !== 'delete'); 159 } else { 160 return item.actions; 161 } 162 }; 163 }, 164 }, 165 watch: { 166 // Watch for change in tab index 167 tabIndex() { 168 this.getIpv4TableItems(); 169 }, 170 ethernetData() { 171 this.getIpv4TableItems(); 172 }, 173 }, 174 created() { 175 this.getIpv4TableItems(); 176 this.$store.dispatch('network/getEthernetData').finally(() => { 177 // Emit initial data fetch complete to parent component 178 require('@/eventBus').default.$emit('network-table-ipv4-complete'); 179 }); 180 }, 181 methods: { 182 getIpv4TableItems() { 183 const index = this.tabIndex; 184 const addresses = this.ethernetData[index].IPv4Addresses || []; 185 this.form.ipv4TableItems = addresses.map((ipv4) => { 186 return { 187 Address: ipv4.Address, 188 SubnetMask: ipv4.SubnetMask, 189 Gateway: ipv4.Gateway, 190 AddressOrigin: ipv4.AddressOrigin, 191 actions: [ 192 { 193 value: 'delete', 194 title: i18n.global.t('pageNetwork.table.deleteIpv4'), 195 }, 196 ], 197 }; 198 }); 199 }, 200 onIpv4TableAction(action, $event, index) { 201 if ($event === 'delete') { 202 this.deleteIpv4TableRow(index); 203 } 204 }, 205 deleteIpv4TableRow(index) { 206 this.form.ipv4TableItems.splice(index, 1); 207 const newIpv4Array = this.form.ipv4TableItems.map((ipv4) => { 208 const { Address, SubnetMask, Gateway } = ipv4; 209 return { 210 Address, 211 SubnetMask, 212 Gateway, 213 }; 214 }); 215 this.$store 216 .dispatch('network/editIpv4Address', newIpv4Array) 217 .then((message) => this.successToast(message)) 218 .catch(({ message }) => this.errorToast(message)); 219 }, 220 initAddIpv4Address() { 221 this.showAddIpv4 = true; 222 }, 223 changeDhcpEnabledState(state) { 224 const dhcpState = state 225 ? i18n.global.t('global.action.enable') 226 : i18n.global.t('global.action.disable'); 227 this.confirmDialog( 228 state 229 ? i18n.global.t('pageNetwork.modal.confirmEnableDhcp') 230 : i18n.global.t('pageNetwork.modal.confirmDisableDhcp'), 231 { 232 title: i18n.global.t('pageNetwork.modal.dhcpConfirmTitle', { 233 dhcpState, 234 }), 235 okTitle: dhcpState, 236 okVariant: 'danger', 237 cancelTitle: i18n.global.t('global.action.cancel'), 238 autoFocusButton: 'cancel', 239 }, 240 ).then((dhcpEnableConfirmed) => { 241 if (dhcpEnableConfirmed) { 242 this.$store 243 .dispatch('network/saveDhcpEnabledState', state) 244 .then((message) => this.successToast(message)) 245 .catch(({ message }) => this.errorToast(message)); 246 } else { 247 let onDhcpCancel = document.getElementById('dhcpSwitch'); 248 onDhcpCancel.checked = !state; 249 } 250 }); 251 }, 252 confirmDialog(message, options = {}) { 253 return this.$confirm({ message, ...options }); 254 }, 255 }, 256}; 257</script> 258