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