1<template> 2 <page-section :section-title="$t('pageNetwork.ipv6')"> 3 <b-row class="mb-4"> 4 <b-col lg="2" md="6"> 5 <dl> 6 <dt>{{ $t('pageNetwork.dhcp6') }}</dt> 7 <dd> 8 <b-form-checkbox 9 id="dhcp6Switch" 10 v-model="dhcp6EnabledState" 11 data-test-id="networkSettings-switch-dhcp6Enabled" 12 switch 13 @change="changeDhcp6EnabledState" 14 > 15 <span v-if="dhcp6EnabledState"> 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-col lg="2" md="6"> 24 <dl class="text-nowrap"> 25 <dt> 26 {{ $t('pageNetwork.ipv6DefaultGateway') }} 27 <b-button 28 v-if="defaultGatewayEditable" 29 variant="link" 30 class="p-1" 31 @click="initDefaultGatewayModal()" 32 > 33 <icon-edit 34 :title="$t('pageNetwork.modal.editIPv6DefaultGatewayTitle')" 35 /> 36 </b-button> 37 </dt> 38 <dd> 39 {{ dataFormatter(defaultGateway) }} 40 </dd> 41 </dl> 42 </b-col> 43 </b-row> 44 <b-row> 45 <b-col> 46 <h3 class="h5"> 47 {{ $t('pageNetwork.ipv6Addresses') }} 48 </h3> 49 </b-col> 50 <b-col class="text-right"> 51 <b-button variant="primary" @click="initAddIpv6Address()"> 52 <icon-add /> 53 {{ $t('pageNetwork.table.addIpv6Address') }} 54 </b-button> 55 </b-col> 56 </b-row> 57 <b-table 58 responsive="md" 59 hover 60 :fields="ipv6TableFields" 61 :items="form.ipv6TableItems" 62 :empty-text="$t('global.table.emptyMessage')" 63 class="mb-0" 64 show-empty 65 > 66 <template #cell(actions)="{ item, index }"> 67 <table-row-action 68 v-for="(action, actionIndex) in filteredActions(item)" 69 :key="actionIndex" 70 :value="action.value" 71 :title="action.title" 72 :enabled="action.enabled" 73 @click-table-action="onIpv6TableAction(action, $event, index)" 74 > 75 <template #icon> 76 <icon-edit v-if="action.value === 'edit'" /> 77 <icon-trashcan v-if="action.value === 'delete'" /> 78 </template> 79 </table-row-action> 80 </template> 81 </b-table> 82 </page-section> 83</template> 84 85<script> 86import BVToastMixin from '@/components/Mixins/BVToastMixin'; 87import IconAdd from '@carbon/icons-vue/es/add--alt/20'; 88import IconEdit from '@carbon/icons-vue/es/edit/20'; 89import IconTrashcan from '@carbon/icons-vue/es/trash-can/20'; 90import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin'; 91import PageSection from '@/components/Global/PageSection'; 92import TableRowAction from '@/components/Global/TableRowAction'; 93import DataFormatterMixin from '@/components/Mixins/DataFormatterMixin'; 94import { mapState } from 'vuex'; 95 96export default { 97 name: 'Ipv6Table', 98 components: { 99 IconAdd, 100 IconEdit, 101 IconTrashcan, 102 PageSection, 103 TableRowAction, 104 }, 105 mixins: [BVToastMixin, LoadingBarMixin, DataFormatterMixin], 106 props: { 107 tabIndex: { 108 type: Number, 109 default: 0, 110 }, 111 }, 112 data() { 113 return { 114 form: { 115 ipv6TableItems: [], 116 }, 117 actions: [ 118 { 119 value: 'edit', 120 title: this.$t('global.action.edit'), 121 }, 122 { 123 value: 'delete', 124 title: this.$t('global.action.delete'), 125 }, 126 ], 127 ipv6TableFields: [ 128 { 129 key: 'Address', 130 label: this.$t('pageNetwork.table.ipAddress'), 131 }, 132 { 133 key: 'PrefixLength', 134 label: this.$t('pageNetwork.table.prefixLength'), 135 }, 136 { 137 key: 'AddressOrigin', 138 label: this.$t('pageNetwork.table.addressOrigin'), 139 }, 140 { key: 'actions', label: '', tdClass: 'text-right' }, 141 ], 142 defaultGateway: '', 143 defaultGatewayEditable: 144 process.env.VUE_APP_ENV_NAME !== 'nvidia-bluefield', 145 }; 146 }, 147 computed: { 148 ...mapState('network', ['ethernetData']), 149 selectedInterface() { 150 return this.$store.getters['network/selectedInterfaceIndex']; 151 }, 152 dhcp6EnabledState: { 153 get() { 154 return ( 155 this.$store.getters['network/globalNetworkSettings'][ 156 this.selectedInterface 157 ].dhcp6Enabled === 'Enabled' 158 ); 159 }, 160 set(newValue) { 161 return newValue; 162 }, 163 }, 164 filteredActions() { 165 return (item) => { 166 if (item.AddressOrigin === 'DHCPv6' || item.AddressOrigin === 'SLAAC') { 167 return item.actions.filter((action) => action.value !== 'delete'); 168 } else { 169 return item.actions; 170 } 171 }; 172 }, 173 }, 174 watch: { 175 // Watch for change in tab index 176 tabIndex() { 177 this.getIpv6TableItems(); 178 this.getDefaultGateway(); 179 }, 180 ethernetData() { 181 this.getIpv6TableItems(); 182 this.getDefaultGateway(); 183 }, 184 }, 185 created() { 186 this.getIpv6TableItems(); 187 this.getDefaultGateway(); 188 this.$store.dispatch('network/getEthernetData').finally(() => { 189 // Emit initial data fetch complete to parent component 190 this.$root.$emit('network-table-ipv6-complete'); 191 }); 192 }, 193 methods: { 194 getDefaultGateway() { 195 this.defaultGateway = this.ethernetData[this.tabIndex].IPv6DefaultGateway; 196 }, 197 getIpv6TableItems() { 198 const index = this.tabIndex; 199 const addresses = 200 this.ethernetData[index].IPv6Addresses.filter( 201 (ipv6) => 202 ipv6.AddressOrigin === 'LinkLocal' || 203 ipv6.AddressOrigin === 'Static' || 204 ipv6.AddressOrigin === 'SLAAC' || 205 ipv6.AddressOrigin === 'DHCPv6', 206 ) || []; 207 this.form.ipv6TableItems = addresses.map((ipv6) => { 208 return { 209 Address: ipv6.Address, 210 PrefixLength: ipv6.PrefixLength, 211 AddressOrigin: ipv6.AddressOrigin, 212 actions: [ 213 { 214 value: 'delete', 215 title: this.$t('pageNetwork.table.deleteIpv6'), 216 }, 217 ], 218 }; 219 }); 220 }, 221 onIpv6TableAction(action, $event, index) { 222 if ($event === 'delete') { 223 this.deleteIpv6TableRow(index); 224 } 225 }, 226 deleteIpv6TableRow(index) { 227 const AddressOrigin = this.form.ipv6TableItems[index].AddressOrigin; 228 this.form.ipv6TableItems.splice(index, 1); 229 const newIpv6Array = this.form.ipv6TableItems.map((ipv6) => { 230 const { Address, PrefixLength } = ipv6; 231 return { 232 Address, 233 PrefixLength, 234 }; 235 }); 236 if ( 237 newIpv6Array.length == 0 && 238 (AddressOrigin === 'Static' || AddressOrigin === 'LinkLocal') 239 ) { 240 this.$store 241 .dispatch('network/saveDhcp6EnabledState', true) 242 .then((message) => this.successToast(message)) 243 .catch(({ message }) => this.errorToast(message)); 244 } 245 this.$store 246 .dispatch('network/editIpv6Address', newIpv6Array) 247 .then((message) => this.successToast(message)) 248 .catch(({ message }) => this.errorToast(message)); 249 }, 250 initAddIpv6Address() { 251 this.$bvModal.show('modal-add-ipv6'); 252 }, 253 changeDhcp6EnabledState(state) { 254 this.$bvModal 255 .msgBoxConfirm( 256 state 257 ? this.$t('pageNetwork.modal.confirmEnableDhcp') 258 : this.$t('pageNetwork.modal.confirmDisableDhcp'), 259 { 260 title: this.$t('pageNetwork.modal.dhcpConfirmTitle', { 261 dhcpState: state 262 ? this.$t('global.action.enable') 263 : this.$t('global.action.disable'), 264 }), 265 okTitle: state 266 ? this.$t('global.action.enable') 267 : this.$t('global.action.disable'), 268 okVariant: 'danger', 269 cancelTitle: this.$t('global.action.cancel'), 270 }, 271 ) 272 .then((dhcpEnableConfirmed) => { 273 if (dhcpEnableConfirmed) { 274 this.$store 275 .dispatch('network/saveDhcp6EnabledState', state) 276 .then((message) => this.successToast(message)) 277 .catch(({ message }) => this.errorToast(message)); 278 } else { 279 let onDhcpCancel = document.getElementById('dhcp6Switch'); 280 onDhcpCancel.checked = !state; 281 } 282 }); 283 }, 284 initDefaultGatewayModal() { 285 this.$bvModal.show('modal-default-gateway'); 286 }, 287 }, 288}; 289</script> 290