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