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