xref: /openbmc/webui-vue/src/views/Settings/SnmpAlerts/SnmpAlerts.vue (revision de23ea23d88451a2fa2774ec72053772603c23ae)
1<template>
2  <b-container fluid="xl">
3    <page-title :description="$t('pageSnmpAlerts.pageDescription')" />
4    <b-row>
5      <b-col xl="9" class="text-right">
6        <b-button variant="primary" @click="initModalAddDestination">
7          <icon-add />
8          {{ $t('pageSnmpAlerts.addDestination') }}
9        </b-button>
10      </b-col>
11    </b-row>
12    <b-row>
13      <b-col xl="9">
14        <table-toolbar
15          ref="toolbar"
16          :selected-items-count="selectedRows.length"
17          :actions="tableToolbarActions"
18          @clear-selected="clearSelectedRows($refs.table)"
19          @batch-action="onBatchAction"
20        />
21        <b-table
22          ref="table"
23          responsive="md"
24          selectable
25          show-empty
26          no-select-on-click
27          hover
28          :fields="fields"
29          :items="tableItems"
30          :empty-text="$t('global.table.emptyMessage')"
31          @row-selected="onRowSelected($event, tableItems.length)"
32        >
33          <!-- Checkbox column -->
34          <template #head(checkbox)>
35            <b-form-checkbox
36              v-model="tableHeaderCheckboxModel"
37              data-test-id="snmpAlerts-checkbox-selectAll"
38              :indeterminate="tableHeaderCheckboxIndeterminate"
39              @change="onChangeHeaderCheckbox($refs.table)"
40            >
41              <span class="sr-only">{{ $t('global.table.selectAll') }}</span>
42            </b-form-checkbox>
43          </template>
44          <template #cell(checkbox)="row">
45            <b-form-checkbox
46              v-model="row.rowSelected"
47              :data-test-id="`snmpAlerts-checkbox-selectRow-${row.index}`"
48              @change="toggleSelectRow($refs.table, row.index)"
49            >
50              <span class="sr-only">{{ $t('global.table.selectItem') }}</span>
51            </b-form-checkbox>
52          </template>
53
54          <!-- table actions column -->
55          <template #cell(actions)="{ item }">
56            <table-row-action
57              v-for="(action, index) in item.actions"
58              :key="index"
59              :value="action.value"
60              :enabled="action.enabled"
61              :title="action.title"
62              :data-test-id="`snmpAlerts-button-deleteRow-${item.index}`"
63              @click-table-action="onTableRowAction($event, item)"
64            >
65              <template #icon>
66                <icon-trashcan v-if="action.value === 'delete'" />
67              </template>
68            </table-row-action>
69          </template>
70        </b-table>
71      </b-col>
72    </b-row>
73    <!-- Modals -->
74    <modal-add-destination @ok="onModalOk" />
75  </b-container>
76</template>
77
78<script>
79import IconTrashcan from '@carbon/icons-vue/es/trash-can/20';
80import ModalAddDestination from './ModalAddDestination';
81import PageTitle from '@/components/Global/PageTitle';
82import IconAdd from '@carbon/icons-vue/es/add--alt/20';
83import TableToolbar from '@/components/Global/TableToolbar';
84import TableRowAction from '@/components/Global/TableRowAction';
85import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin';
86import BVToastMixin from '@/components/Mixins/BVToastMixin';
87
88import BVTableSelectableMixin, {
89  selectedRows,
90  tableHeaderCheckboxModel,
91  tableHeaderCheckboxIndeterminate,
92} from '@/components/Mixins/BVTableSelectableMixin';
93import { useI18n } from 'vue-i18n';
94import i18n from '@/i18n';
95
96export default {
97  name: 'SnmpAlerts',
98  components: {
99    PageTitle,
100    IconAdd,
101    TableToolbar,
102    IconTrashcan,
103    ModalAddDestination,
104    TableRowAction,
105  },
106  mixins: [BVTableSelectableMixin, BVToastMixin, LoadingBarMixin],
107  beforeRouteLeave(to, from, next) {
108    this.hideLoader();
109    next();
110  },
111  data() {
112    return {
113      $t: useI18n().t,
114      fields: [
115        {
116          key: 'checkbox',
117        },
118        {
119          key: 'IP',
120          label: i18n.global.t('pageSnmpAlerts.table.ipaddress'),
121        },
122        {
123          key: 'Port',
124          label: i18n.global.t('pageSnmpAlerts.table.port'),
125        },
126        {
127          key: 'actions',
128          label: '',
129          tdClass: 'text-right text-nowrap',
130        },
131      ],
132      tableToolbarActions: [
133        {
134          value: 'delete',
135          label: i18n.global.t('global.action.delete'),
136        },
137      ],
138      selectedRows: selectedRows,
139      tableHeaderCheckboxModel: tableHeaderCheckboxModel,
140      tableHeaderCheckboxIndeterminate: tableHeaderCheckboxIndeterminate,
141    };
142  },
143  computed: {
144    allSnmpDetails() {
145      return this.$store.getters['snmpAlerts/allSnmpDetails'];
146    },
147    tableItems() {
148      // transform destination data to table data
149      return this.allSnmpDetails.map((subscriptions) => {
150        const [destination, dataWithProtocol, dataWithoutProtocol] = [
151          subscriptions.Destination,
152          subscriptions.Destination.split('/')[2].split(':'),
153          subscriptions.Destination.split(':'),
154        ];
155        //condition to check if destination comes with protocol or not
156        const conditionForProtocolCheck = destination.includes('://');
157        const ip = conditionForProtocolCheck
158          ? dataWithProtocol[0]
159          : dataWithoutProtocol[0];
160        const port = conditionForProtocolCheck
161          ? dataWithProtocol[1]
162          : dataWithoutProtocol[1];
163        return {
164          IP: ip,
165          Port: port,
166          id: subscriptions.Id,
167          actions: [
168            {
169              value: 'delete',
170              enabled: true,
171              title: i18n.global.t('pageSnmpAlerts.deleteDestination'),
172            },
173          ],
174          ...subscriptions,
175        };
176      });
177    },
178  },
179  created() {
180    this.startLoader();
181    this.$store
182      .dispatch('snmpAlerts/getSnmpDetails')
183      .finally(() => this.endLoader());
184  },
185  methods: {
186    onModalOk({ ipAddress, port }) {
187      const protocolIpAddress = 'snmp://' + ipAddress;
188      const destination = port
189        ? protocolIpAddress + ':' + port
190        : protocolIpAddress;
191      const data = {
192        Destination: destination,
193        SubscriptionType: 'SNMPTrap',
194        Protocol: 'SNMPv2c',
195      };
196      this.startLoader();
197      this.$store
198        .dispatch('snmpAlerts/addDestination', { data })
199        .then((success) => this.successToast(success))
200        .catch(({ message }) => this.errorToast(message))
201        .finally(() => this.endLoader());
202    },
203    initModalAddDestination() {
204      this.$bvModal.show('add-destination');
205    },
206    initModalDeleteDestination(destination) {
207      this.$bvModal
208        .msgBoxConfirm(
209          i18n.global.t('pageSnmpAlerts.modal.deleteConfirmMessage', {
210            destination: destination.id,
211          }),
212          {
213            title: i18n.global.t(
214              'pageSnmpAlerts.modal.deleteSnmpDestinationTitle',
215            ),
216            okTitle: i18n.global.t('pageSnmpAlerts.deleteDestination'),
217            cancelTitle: i18n.global.t('global.action.cancel'),
218            autoFocusButton: 'ok',
219          },
220        )
221        .then((deleteConfirmed) => {
222          if (deleteConfirmed) {
223            this.deleteDestination(destination);
224          }
225        });
226    },
227    deleteDestination({ id }) {
228      this.startLoader();
229      this.$store
230        .dispatch('snmpAlerts/deleteDestination', id)
231        .then((success) => this.successToast(success))
232        .catch(({ message }) => this.errorToast(message))
233        .finally(() => this.endLoader());
234    },
235    onBatchAction(action) {
236      if (action === 'delete') {
237        this.$bvModal
238          .msgBoxConfirm(
239            i18n.global.t(
240              'pageSnmpAlerts.modal.batchDeleteConfirmMessage',
241              this.selectedRows.length,
242            ),
243            {
244              title: i18n.global.t(
245                'pageSnmpAlerts.modal.deleteSnmpDestinationTitle',
246                this.selectedRows.length,
247              ),
248              okTitle: i18n.global.t(
249                'pageSnmpAlerts.deleteDestination',
250                this.selectedRows.length,
251              ),
252              cancelTitle: i18n.global.t('global.action.cancel'),
253              autoFocusButton: 'ok',
254            },
255          )
256          .then((deleteConfirmed) => {
257            if (deleteConfirmed) {
258              this.startLoader();
259              this.$store
260                .dispatch(
261                  'snmpAlerts/deleteMultipleDestinations',
262                  this.selectedRows,
263                )
264                .then((messages) => {
265                  messages.forEach(({ type, message }) => {
266                    if (type === 'success') this.successToast(message);
267                    if (type === 'error') this.errorToast(message);
268                  });
269                })
270                .finally(() => this.endLoader());
271            }
272          });
273      }
274    },
275    onTableRowAction(action, row) {
276      if (action === 'delete') {
277        this.initModalDeleteDestination(row);
278      }
279    },
280  },
281};
282</script>
283