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