xref: /openbmc/webui-vue/src/views/Logs/Dumps/Dumps.vue (revision 05887b50)
1<template>
2  <b-container fluid="xl">
3    <page-title />
4    <b-row>
5      <b-col sm="6" lg="5" xl="4">
6        <page-section :section-title="$t('pageDumps.initiateDump')">
7          <dumps-form />
8        </page-section>
9      </b-col>
10    </b-row>
11    <b-row>
12      <b-col xl="10">
13        <page-section :section-title="$t('pageDumps.dumpsAvailableOnBmc')">
14          <b-row class="align-items-start">
15            <b-col sm="8" xl="6" class="d-sm-flex align-items-end">
16              <search
17                :placeholder="$t('pageDumps.table.searchDumps')"
18                @change-search="onChangeSearchInput"
19                @clear-search="onClearSearchInput"
20              />
21              <div class="ml-sm-4">
22                <table-cell-count
23                  :filtered-items-count="filteredRows"
24                  :total-number-of-cells="allDumps.length"
25                ></table-cell-count>
26              </div>
27            </b-col>
28            <b-col sm="8" md="7" xl="6">
29              <table-date-filter @change="onChangeDateTimeFilter" />
30            </b-col>
31          </b-row>
32          <b-row>
33            <b-col class="text-right">
34              <table-filter
35                :filters="tableFilters"
36                @filter-change="onFilterChange"
37              />
38            </b-col>
39          </b-row>
40          <table-toolbar
41            :selected-items-count="selectedRows.length"
42            :actions="batchActions"
43            @clear-selected="clearSelectedRows($refs.table)"
44            @batch-action="onTableBatchAction"
45          />
46          <b-table
47            ref="table"
48            show-empty
49            hover
50            sort-icon-left
51            no-sort-reset
52            sort-desc
53            selectable
54            no-select-on-click
55            responsive="md"
56            sort-by="dateTime"
57            :fields="fields"
58            :items="filteredDumps"
59            :empty-text="$t('global.table.emptyMessage')"
60            :empty-filtered-text="$t('global.table.emptySearchMessage')"
61            :filter="searchFilter"
62            @filtered="onFiltered"
63            @row-selected="onRowSelected($event, filteredDumps.length)"
64          >
65            <!-- Checkbox column -->
66            <template #head(checkbox)>
67              <b-form-checkbox
68                v-model="tableHeaderCheckboxModel"
69                :indeterminate="tableHeaderCheckboxIndeterminate"
70                @change="onChangeHeaderCheckbox($refs.table)"
71              >
72                <span class="sr-only">{{ $t('global.table.selectAll') }}</span>
73              </b-form-checkbox>
74            </template>
75            <template #cell(checkbox)="row">
76              <b-form-checkbox
77                v-model="row.rowSelected"
78                @change="toggleSelectRow($refs.table, row.index)"
79              >
80                <span class="sr-only">{{ $t('global.table.selectItem') }}</span>
81              </b-form-checkbox>
82            </template>
83
84            <!-- Date and Time column -->
85            <template #cell(dateTime)="{ value }">
86              <p class="mb-0">{{ value | formatDate }}</p>
87              <p class="mb-0">{{ value | formatTime }}</p>
88            </template>
89
90            <!-- Size column -->
91            <template #cell(size)="{ value }">
92              {{ convertBytesToMegabytes(value) }} MB
93            </template>
94
95            <!-- Actions column -->
96            <template #cell(actions)="row">
97              <table-row-action
98                v-for="(action, index) in row.item.actions"
99                :key="index"
100                :value="action.value"
101                :title="action.title"
102                :download-location="row.item.data"
103                :export-name="exportFileName(row)"
104                @click-table-action="onTableRowAction($event, row.item)"
105              >
106                <template #icon>
107                  <icon-download v-if="action.value === 'download'" />
108                  <icon-delete v-if="action.value === 'delete'" />
109                </template>
110              </table-row-action>
111            </template>
112          </b-table>
113        </page-section>
114      </b-col>
115    </b-row>
116    <!-- Table pagination -->
117    <b-row>
118      <b-col sm="6" xl="5">
119        <b-form-group
120          class="table-pagination-select"
121          :label="$t('global.table.itemsPerPage')"
122          label-for="pagination-items-per-page"
123        >
124          <b-form-select
125            id="pagination-items-per-page"
126            v-model="perPage"
127            :options="itemsPerPageOptions"
128          />
129        </b-form-group>
130      </b-col>
131      <b-col sm="6" xl="5">
132        <b-pagination
133          v-model="currentPage"
134          first-number
135          last-number
136          :per-page="perPage"
137          :total-rows="getTotalRowCount()"
138          aria-controls="table-dump-entries"
139        />
140      </b-col>
141    </b-row>
142  </b-container>
143</template>
144
145<script>
146import IconDelete from '@carbon/icons-vue/es/trash-can/20';
147import IconDownload from '@carbon/icons-vue/es/download/20';
148import DumpsForm from './DumpsForm';
149import PageSection from '@/components/Global/PageSection';
150import PageTitle from '@/components/Global/PageTitle';
151import Search from '@/components/Global/Search';
152import TableCellCount from '@/components/Global/TableCellCount';
153import TableDateFilter from '@/components/Global/TableDateFilter';
154import TableRowAction from '@/components/Global/TableRowAction';
155import TableToolbar from '@/components/Global/TableToolbar';
156import BVTableSelectableMixin, {
157  selectedRows,
158  tableHeaderCheckboxModel,
159  tableHeaderCheckboxIndeterminate,
160} from '@/components/Mixins/BVTableSelectableMixin';
161import BVToastMixin from '@/components/Mixins/BVToastMixin';
162import BVPaginationMixin, {
163  currentPage,
164  perPage,
165  itemsPerPageOptions,
166} from '@/components/Mixins/BVPaginationMixin';
167import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin';
168import SearchFilterMixin, {
169  searchFilter,
170} from '@/components/Mixins/SearchFilterMixin';
171import TableFilter from '@/components/Global/TableFilter';
172import TableFilterMixin from '@/components/Mixins/TableFilterMixin';
173
174export default {
175  components: {
176    DumpsForm,
177    IconDelete,
178    IconDownload,
179    PageSection,
180    PageTitle,
181    Search,
182    TableCellCount,
183    TableDateFilter,
184    TableRowAction,
185    TableToolbar,
186    TableFilter,
187  },
188  mixins: [
189    BVTableSelectableMixin,
190    BVToastMixin,
191    BVPaginationMixin,
192    LoadingBarMixin,
193    SearchFilterMixin,
194    TableFilterMixin,
195  ],
196  beforeRouteLeave(to, from, next) {
197    // Hide loader if the user navigates to another page
198    // before request is fulfilled.
199    this.hideLoader();
200    next();
201  },
202  data() {
203    return {
204      fields: [
205        {
206          key: 'checkbox',
207          sortable: false,
208        },
209        {
210          key: 'dateTime',
211          label: this.$t('pageDumps.table.dateAndTime'),
212          sortable: true,
213        },
214        {
215          key: 'dumpType',
216          label: this.$t('pageDumps.table.dumpType'),
217          sortable: true,
218        },
219        {
220          key: 'id',
221          label: this.$t('pageDumps.table.id'),
222          sortable: true,
223        },
224        {
225          key: 'size',
226          label: this.$t('pageDumps.table.size'),
227          sortable: true,
228        },
229        {
230          key: 'actions',
231          sortable: false,
232          label: '',
233          tdClass: 'text-right text-nowrap',
234        },
235      ],
236      batchActions: [
237        {
238          value: 'delete',
239          label: this.$t('global.action.delete'),
240        },
241      ],
242      tableFilters: [
243        {
244          key: 'dumpType',
245          label: this.$t('pageDumps.table.dumpType'),
246          values: [
247            'BMC Dump Entry',
248            'Hostboot Dump Entry',
249            'Resource Dump Entry',
250            'System Dump Entry',
251          ],
252        },
253      ],
254      activeFilters: [],
255      currentPage: currentPage,
256      filterEndDate: null,
257      filterStartDate: null,
258      itemsPerPageOptions: itemsPerPageOptions,
259      perPage: perPage,
260      searchFilter,
261      searchTotalFilteredRows: 0,
262      selectedRows,
263      tableHeaderCheckboxIndeterminate,
264      tableHeaderCheckboxModel,
265    };
266  },
267  computed: {
268    filteredRows() {
269      return this.searchFilter
270        ? this.searchTotalFilteredRows
271        : this.filteredDumps.length;
272    },
273    allDumps() {
274      return this.$store.getters['dumps/allDumps'].map((item) => {
275        return {
276          ...item,
277          actions: [
278            {
279              value: 'download',
280              title: this.$t('global.action.download'),
281            },
282            {
283              value: 'delete',
284              title: this.$t('global.action.delete'),
285            },
286          ],
287        };
288      });
289    },
290    filteredDumpsByDate() {
291      return this.getFilteredTableDataByDate(
292        this.allDumps,
293        this.filterStartDate,
294        this.filterEndDate,
295        'dateTime'
296      );
297    },
298    filteredDumps() {
299      return this.getFilteredTableData(
300        this.filteredDumpsByDate,
301        this.activeFilters
302      );
303    },
304  },
305  created() {
306    this.startLoader();
307    this.$store.dispatch('dumps/getAllDumps').finally(() => this.endLoader());
308  },
309  methods: {
310    convertBytesToMegabytes(bytes) {
311      return parseFloat((bytes / 1000000).toFixed(3));
312    },
313    onFilterChange({ activeFilters }) {
314      this.activeFilters = activeFilters;
315    },
316    onFiltered(filteredItems) {
317      this.searchTotalFilteredRows = filteredItems.length;
318    },
319    onChangeDateTimeFilter({ fromDate, toDate }) {
320      this.filterStartDate = fromDate;
321      this.filterEndDate = toDate;
322    },
323    onTableRowAction(action, dump) {
324      if (action === 'delete') {
325        this.$bvModal
326          .msgBoxConfirm(this.$tc('pageDumps.modal.deleteDumpConfirmation'), {
327            title: this.$tc('pageDumps.modal.deleteDump'),
328            okTitle: this.$tc('pageDumps.modal.deleteDump'),
329            cancelTitle: this.$t('global.action.cancel'),
330          })
331          .then((deleteConfrimed) => {
332            if (deleteConfrimed) {
333              this.$store
334                .dispatch('dumps/deleteDumps', [dump])
335                .then((messages) => {
336                  messages.forEach(({ type, message }) => {
337                    if (type === 'success') {
338                      this.successToast(message);
339                    } else if (type === 'error') {
340                      this.errorToast(message);
341                    }
342                  });
343                });
344            }
345          });
346      }
347    },
348    onTableBatchAction(action) {
349      if (action === 'delete') {
350        this.$bvModal
351          .msgBoxConfirm(
352            this.$tc(
353              'pageDumps.modal.deleteDumpConfirmation',
354              this.selectedRows.length
355            ),
356            {
357              title: this.$tc(
358                'pageDumps.modal.deleteDump',
359                this.selectedRows.length
360              ),
361              okTitle: this.$tc(
362                'pageDumps.modal.deleteDump',
363                this.selectedRows.length
364              ),
365              cancelTitle: this.$t('global.action.cancel'),
366            }
367          )
368          .then((deleteConfrimed) => {
369            if (deleteConfrimed) {
370              if (this.selectedRows.length === this.dumps.length) {
371                this.$store
372                  .dispatch('dumps/deleteAllDumps')
373                  .then((success) => this.successToast(success))
374                  .catch(({ message }) => this.errorToast(message));
375              } else {
376                this.$store
377                  .dispatch('dumps/deleteDumps', this.selectedRows)
378                  .then((messages) => {
379                    messages.forEach(({ type, message }) => {
380                      if (type === 'success') {
381                        this.successToast(message);
382                      } else if (type === 'error') {
383                        this.errorToast(message);
384                      }
385                    });
386                  });
387              }
388            }
389          });
390      }
391    },
392    exportFileName(row) {
393      let filename = row.item.dumpType + '_' + row.item.id + '.tar.xz';
394      filename = filename.replace(RegExp(' ', 'g'), '_');
395      return filename;
396    },
397  },
398};
399</script>
400