xref: /openbmc/webui-vue/src/views/Settings/Network/Network.vue (revision d36ac8a8be8636ddd0e64ce005d507b21bcdeb00)
1<template>
2  <b-container fluid="xl">
3    <page-title :description="$t('pageNetwork.pageDescription')" />
4    <!-- Global settings for all interfaces -->
5    <network-global-settings />
6    <!-- Interface tabs -->
7    <page-section v-if="ethernetData && ethernetData.length">
8      <b-row>
9        <b-col>
10          <b-card no-body>
11            <b-tabs
12              :key="tabsRenderKey"
13              v-model:index="tabIndex"
14              active-nav-item-class="fw-bold"
15              card
16              content-class="mt-3"
17              :lazy="false"
18            >
19              <b-tab
20                v-for="data in ethernetData"
21                :key="data.Id"
22                :title="data.Id"
23              >
24                <!-- Interface settings -->
25                <network-interface-settings :tab-index="tabIndex" />
26                <!-- IPV4 table -->
27                <table-ipv-4 :tab-index="tabIndex" />
28                <!-- IPV6 table -->
29                <table-ipv-6 :tab-index="tabIndex" />
30                <!-- Static DNS table -->
31                <table-dns :tab-index="tabIndex" />
32              </b-tab>
33            </b-tabs>
34          </b-card>
35        </b-col>
36      </b-row>
37    </page-section>
38    <!-- Modals -->
39    <modal-ipv4 :default-gateway="defaultGateway" @ok="saveIpv4Address" />
40    <modal-ipv6 @ok="saveIpv6Address" />
41    <modal-dns @ok="saveDnsAddress" />
42    <modal-hostname
43      v-model="showHostnameModal"
44      :hostname="currentHostname"
45      @ok="saveSettings"
46    />
47    <modal-mac-address
48      v-model="showMacAddressModal"
49      :mac-address="currentMacAddress"
50      @ok="saveSettings"
51    />
52    <modal-default-gateway
53      v-model="showDefaultGatewayModal"
54      :default-gateway="ipv6DefaultGateway"
55      @ok="saveSettings"
56    />
57  </b-container>
58</template>
59
60<script>
61import BVToastMixin from '@/components/Mixins/BVToastMixin';
62import DataFormatterMixin from '@/components/Mixins/DataFormatterMixin';
63import LoadingBarMixin, { loading } from '@/components/Mixins/LoadingBarMixin';
64import ModalMacAddress from './ModalMacAddress.vue';
65import ModalDefaultGateway from './ModalDefaultGateway.vue';
66import ModalHostname from './ModalHostname.vue';
67import ModalIpv4 from './ModalIpv4.vue';
68import ModalIpv6 from './ModalIpv6.vue';
69import ModalDns from './ModalDns.vue';
70import NetworkGlobalSettings from './NetworkGlobalSettings.vue';
71import NetworkInterfaceSettings from './NetworkInterfaceSettings.vue';
72import PageSection from '@/components/Global/PageSection';
73import PageTitle from '@/components/Global/PageTitle';
74import TableIpv4 from './TableIpv4.vue';
75import TableIpv6 from './TableIpv6.vue';
76import TableDns from './TableDns.vue';
77import { mapState } from 'vuex';
78import { useI18n } from 'vue-i18n';
79
80export default {
81  name: 'Network',
82  components: {
83    ModalHostname,
84    ModalMacAddress,
85    ModalDefaultGateway,
86    ModalIpv4,
87    ModalIpv6,
88    ModalDns,
89    NetworkGlobalSettings,
90    NetworkInterfaceSettings,
91    PageSection,
92    PageTitle,
93    TableDns,
94    TableIpv4,
95    TableIpv6,
96  },
97  mixins: [BVToastMixin, DataFormatterMixin, LoadingBarMixin],
98  beforeRouteLeave(to, from, next) {
99    this.hideLoader();
100    next();
101  },
102  data() {
103    return {
104      $t: useI18n().t,
105      currentHostname: '',
106      currentMacAddress: '',
107      defaultGateway: '',
108      ipv6DefaultGateway: '',
109      loading,
110      tabIndex: 0,
111      tabsReady: false,
112      tabsRenderKey: 0,
113      showHostnameModal: false,
114      showDefaultGatewayModal: false,
115      showMacAddressModal: false,
116    };
117  },
118  computed: {
119    ...mapState('network', ['ethernetData']),
120  },
121  watch: {
122    ethernetData() {
123      this.getModalInfo();
124    },
125    tabIndex(newIndex) {
126      this.$store.dispatch('network/setSelectedTabIndex', newIndex);
127      this.$store.dispatch(
128        'network/setSelectedTabId',
129        this.ethernetData?.[newIndex]?.Id,
130      );
131      this.getModalInfo();
132    },
133  },
134  created() {
135    this.startLoader();
136    const eventBus = require('@/eventBus').default;
137    const globalSettings = new Promise((resolve) => {
138      eventBus.$once('network-global-settings-complete', resolve);
139    });
140    const interfaceSettings = new Promise((resolve) => {
141      eventBus.$once('network-interface-settings-complete', resolve);
142    });
143    const networkTableDns = new Promise((resolve) => {
144      eventBus.$once('network-table-dns-complete', resolve);
145    });
146    const networkTableIpv4 = new Promise((resolve) => {
147      eventBus.$once('network-table-ipv4-complete', resolve);
148    });
149    const networkTableIpv6 = new Promise((resolve) => {
150      eventBus.$once('network-table-ipv6-complete', resolve);
151    });
152    // Combine all child component Promises to indicate
153    // when page data load complete
154    Promise.all([
155      this.$store.dispatch('network/getEthernetData'),
156      globalSettings,
157      interfaceSettings,
158      networkTableDns,
159      networkTableIpv4,
160      networkTableIpv6,
161    ])
162      .then(() => {
163        // ensure first tab is selected and expanded (index 0). Force a change
164        // cycle to trigger BTabs to render the pane content immediately.
165        const count = this.ethernetData?.length || 0;
166        if (count > 0) {
167          // set initial selection directly to index 0
168          this.tabIndex = 0;
169          this.$store.dispatch('network/setSelectedTabIndex', 0);
170          const firstId = this.ethernetData?.[0]?.Id;
171          if (firstId)
172            this.$store.dispatch('network/setSelectedTabId', firstId);
173          this.tabsRenderKey += 1;
174        }
175      })
176      .finally(() => this.endLoader());
177  },
178  methods: {
179    getModalInfo() {
180      const settingsArray =
181        this.$store.getters['network/globalNetworkSettings'];
182      const settings = Array.isArray(settingsArray)
183        ? settingsArray[this.tabIndex]
184        : undefined;
185
186      if (!settings) return;
187      this.defaultGateway = settings.defaultGateway;
188      this.currentHostname = settings.hostname;
189      this.currentMacAddress = settings.macAddress;
190      this.ipv6DefaultGateway = settings.ipv6DefaultGateway;
191    },
192    getTabIndex(selectedIndex) {
193      this.tabIndex = selectedIndex;
194      this.$store.dispatch('network/setSelectedTabIndex', this.tabIndex);
195      this.$store.dispatch(
196        'network/setSelectedTabId',
197        this.ethernetData[selectedIndex].Id,
198      );
199      this.getModalInfo();
200    },
201    saveIpv4Address(modalFormData) {
202      this.startLoader();
203      this.$store
204        .dispatch('network/saveIpv4Address', modalFormData)
205        .then((message) => this.successToast(message))
206        .catch(({ message }) => this.errorToast(message))
207        .finally(() => this.endLoader());
208    },
209    saveIpv6Address(modalFormData) {
210      this.startLoader();
211      this.$store
212        .dispatch('network/saveIpv6Address', modalFormData)
213        .then((message) => this.successToast(message))
214        .catch(({ message }) => this.errorToast(message))
215        .finally(() => this.endLoader());
216    },
217    saveDnsAddress(modalFormData) {
218      this.startLoader();
219      this.$store
220        .dispatch('network/saveDnsAddress', modalFormData)
221        .then((message) => this.successToast(message))
222        .catch(({ message }) => this.errorToast(message))
223        .finally(() => this.endLoader());
224    },
225    saveSettings(modalFormData) {
226      this.startLoader();
227      this.$store
228        .dispatch('network/saveSettings', modalFormData)
229        .then((message) => this.successToast(message))
230        .catch(({ message }) => this.errorToast(message))
231        .finally(() => this.endLoader());
232    },
233  },
234};
235</script>
236