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'; 95import i18n from '@/i18n'; 96import { useI18n } from 'vue-i18n'; 97 98export default { 99 name: 'Ipv6Table', 100 components: { 101 IconAdd, 102 IconEdit, 103 IconTrashcan, 104 PageSection, 105 TableRowAction, 106 }, 107 mixins: [BVToastMixin, LoadingBarMixin, DataFormatterMixin], 108 props: { 109 tabIndex: { 110 type: Number, 111 default: 0, 112 }, 113 }, 114 data() { 115 return { 116 $t: useI18n().t, 117 form: { 118 ipv6TableItems: [], 119 }, 120 actions: [ 121 { 122 value: 'edit', 123 title: i18n.global.t('global.action.edit'), 124 }, 125 { 126 value: 'delete', 127 title: i18n.global.t('global.action.delete'), 128 }, 129 ], 130 ipv6TableFields: [ 131 { 132 key: 'Address', 133 label: i18n.global.t('pageNetwork.table.ipAddress'), 134 }, 135 { 136 key: 'PrefixLength', 137 label: i18n.global.t('pageNetwork.table.prefixLength'), 138 }, 139 { 140 key: 'AddressOrigin', 141 label: i18n.global.t('pageNetwork.table.addressOrigin'), 142 }, 143 { key: 'actions', label: '', tdClass: 'text-right' }, 144 ], 145 defaultGateway: '', 146 defaultGatewayEditable: 147 process.env.VUE_APP_ENV_NAME !== 'nvidia-bluefield', 148 }; 149 }, 150 computed: { 151 ...mapState('network', ['ethernetData']), 152 selectedInterface() { 153 return this.$store.getters['network/selectedInterfaceIndex']; 154 }, 155 dhcp6EnabledState: { 156 get() { 157 return ( 158 this.$store.getters['network/globalNetworkSettings'][ 159 this.selectedInterface 160 ].dhcp6Enabled === 'Enabled' 161 ); 162 }, 163 set(newValue) { 164 return newValue; 165 }, 166 }, 167 filteredActions() { 168 return (item) => { 169 if (item.AddressOrigin === 'DHCPv6' || item.AddressOrigin === 'SLAAC') { 170 return item.actions.filter((action) => action.value !== 'delete'); 171 } else { 172 return item.actions; 173 } 174 }; 175 }, 176 }, 177 watch: { 178 // Watch for change in tab index 179 tabIndex() { 180 this.getIpv6TableItems(); 181 this.getDefaultGateway(); 182 }, 183 ethernetData() { 184 this.getIpv6TableItems(); 185 this.getDefaultGateway(); 186 }, 187 }, 188 created() { 189 this.getIpv6TableItems(); 190 this.getDefaultGateway(); 191 this.$store.dispatch('network/getEthernetData').finally(() => { 192 // Emit initial data fetch complete to parent component 193 this.$root.$emit('network-table-ipv6-complete'); 194 }); 195 }, 196 methods: { 197 getDefaultGateway() { 198 this.defaultGateway = this.ethernetData[this.tabIndex].IPv6DefaultGateway; 199 }, 200 getIpv6TableItems() { 201 const index = this.tabIndex; 202 const addresses = 203 this.ethernetData[index].IPv6Addresses.filter( 204 (ipv6) => 205 ipv6.AddressOrigin === 'LinkLocal' || 206 ipv6.AddressOrigin === 'Static' || 207 ipv6.AddressOrigin === 'SLAAC' || 208 ipv6.AddressOrigin === 'DHCPv6', 209 ) || []; 210 this.form.ipv6TableItems = addresses.map((ipv6) => { 211 return { 212 Address: ipv6.Address, 213 PrefixLength: ipv6.PrefixLength, 214 AddressOrigin: ipv6.AddressOrigin, 215 actions: [ 216 { 217 value: 'delete', 218 title: i18n.global.t('pageNetwork.table.deleteIpv6'), 219 }, 220 ], 221 }; 222 }); 223 }, 224 onIpv6TableAction(action, $event, index) { 225 if ($event === 'delete') { 226 this.deleteIpv6TableRow(index); 227 } 228 }, 229 deleteIpv6TableRow(index) { 230 const AddressOrigin = this.form.ipv6TableItems[index].AddressOrigin; 231 this.form.ipv6TableItems.splice(index, 1); 232 const newIpv6Array = this.form.ipv6TableItems.map((ipv6) => { 233 const { Address, PrefixLength } = ipv6; 234 return { 235 Address, 236 PrefixLength, 237 }; 238 }); 239 if ( 240 newIpv6Array.length == 0 && 241 (AddressOrigin === 'Static' || AddressOrigin === 'LinkLocal') 242 ) { 243 this.$store 244 .dispatch('network/saveDhcp6EnabledState', true) 245 .then((message) => this.successToast(message)) 246 .catch(({ message }) => this.errorToast(message)); 247 } 248 this.$store 249 .dispatch('network/editIpv6Address', newIpv6Array) 250 .then((message) => this.successToast(message)) 251 .catch(({ message }) => this.errorToast(message)); 252 }, 253 initAddIpv6Address() { 254 this.$bvModal.show('modal-add-ipv6'); 255 }, 256 changeDhcp6EnabledState(state) { 257 this.$bvModal 258 .msgBoxConfirm( 259 state 260 ? i18n.global.t('pageNetwork.modal.confirmEnableDhcp') 261 : i18n.global.t('pageNetwork.modal.confirmDisableDhcp'), 262 { 263 title: i18n.global.t('pageNetwork.modal.dhcpConfirmTitle', { 264 dhcpState: state 265 ? i18n.global.t('global.action.enable') 266 : i18n.global.t('global.action.disable'), 267 }), 268 okTitle: state 269 ? i18n.global.t('global.action.enable') 270 : i18n.global.t('global.action.disable'), 271 okVariant: 'danger', 272 cancelTitle: i18n.global.t('global.action.cancel'), 273 }, 274 ) 275 .then((dhcpEnableConfirmed) => { 276 if (dhcpEnableConfirmed) { 277 this.$store 278 .dispatch('network/saveDhcp6EnabledState', state) 279 .then((message) => this.successToast(message)) 280 .catch(({ message }) => this.errorToast(message)); 281 } else { 282 let onDhcpCancel = document.getElementById('dhcp6Switch'); 283 onDhcpCancel.checked = !state; 284 } 285 }); 286 }, 287 initDefaultGatewayModal() { 288 this.$bvModal.show('modal-default-gateway'); 289 }, 290 }, 291}; 292</script> 293