xref: /openbmc/webui-vue/src/views/HardwareStatus/Inventory/InventoryTableDimmSlot.vue (revision d36ac8a8be8636ddd0e64ce005d507b21bcdeb00)
1<template>
2  <page-section :section-title="$t('pageInventory.dimmSlot')">
3    <b-row class="align-items-end">
4      <b-col sm="6" md="5" xl="4">
5        <search
6          @change-search="onChangeSearchInput"
7          @clear-search="onClearSearchInput"
8        />
9      </b-col>
10      <b-col sm="6" md="3" xl="2">
11        <table-cell-count
12          :filtered-items-count="filteredRows"
13          :total-number-of-cells="dimms.length"
14        ></table-cell-count>
15      </b-col>
16    </b-row>
17    <b-table
18      sort-icon-left
19      must-sort
20      hover
21      thead-class="table-light"
22      :sort-by="['health']"
23      responsive="md"
24      show-empty
25      :items="dimms"
26      :fields="fields"
27      :sort-desc="[true]"
28      :filter="searchFilter"
29      :empty-text="$t('global.table.emptyMessage')"
30      :empty-filtered-text="$t('global.table.emptySearchMessage')"
31      :busy="isBusy"
32      @filtered="onFiltered"
33    >
34      <!-- Expand chevron icon -->
35      <template #cell(expandRow)="row">
36        <b-button
37          variant="link"
38          data-test-id="hardwareStatus-button-expandDimmSlot"
39          :title="expandRowLabel"
40          class="btn-icon-only"
41          :class="{ collapsed: !row.detailsShowing }"
42          @click="toggleRowDetails(row)"
43        >
44          <icon-chevron />
45          <span class="visually-hidden">{{ expandRowLabel }}</span>
46        </b-button>
47      </template>
48
49      <!-- Health -->
50      <template #cell(health)="{ value }">
51        <status-icon :status="statusIcon(value)" />
52        {{ value }}
53      </template>
54
55      <!-- StatusState -->
56      <template #cell(statusState)="{ value }">
57        <status-icon :status="statusStateIcon(value)" />
58        {{ value }}
59      </template>
60
61      <!-- Toggle identify LED -->
62      <template #cell(identifyLed)="row">
63        <b-form-checkbox
64          v-if="hasIdentifyLed(row.item.identifyLed)"
65          v-model="row.item.identifyLed"
66          name="switch"
67          switch
68          @change="toggleIdentifyLedValue(row.item)"
69        >
70          <span v-if="row.item.identifyLed">
71            {{ $t('global.status.on') }}
72          </span>
73          <span v-else> {{ $t('global.status.off') }} </span>
74        </b-form-checkbox>
75        <div v-else>--</div>
76      </template>
77      <template #row-details="{ item }">
78        <b-container fluid>
79          <b-row>
80            <b-col sm="6" xl="6">
81              <dl>
82                <!-- Manufacturer -->
83                <dt>{{ $t('pageInventory.table.manufacturer') }}:</dt>
84                <dd>{{ dataFormatter(item.manufacturer) }}</dd>
85              </dl>
86              <dl>
87                <!-- Part Number -->
88                <dt>{{ $t('pageInventory.table.partNumber') }}:</dt>
89                <dd>{{ dataFormatter(item.partNumber) }}</dd>
90              </dl>
91              <dl>
92                <!-- Serial Number -->
93                <dt>{{ $t('pageInventory.table.serialNumber') }}:</dt>
94                <dd>{{ dataFormatter(item.serialNumber) }}</dd>
95              </dl>
96              <dl>
97                <!-- Spare Part Number -->
98                <dt>{{ $t('pageInventory.table.sparePartNumber') }}:</dt>
99                <dd>
100                  {{ dataFormatter(item.sparePartNumber) }}
101                </dd>
102              </dl>
103              <dl>
104                <!-- Model -->
105                <dt>{{ $t('pageInventory.table.model') }}:</dt>
106                <dd>{{ dataFormatter(item.model) }}</dd>
107              </dl>
108            </b-col>
109            <b-col sm="6" xl="6">
110              <dl>
111                <!-- Capacity MiB -->
112                <dt>{{ $t('pageInventory.table.capacityMiB') }}:</dt>
113                <dd>
114                  {{ dataFormatter(item.capacityMiB) }}
115                  {{ $t('unit.MiB') }}
116                </dd>
117              </dl>
118              <dl>
119                <!-- Rank Count -->
120                <dt>{{ $t('pageInventory.table.rankCount') }}:</dt>
121                <dd>{{ dataFormatter(item.rankCount) }}</dd>
122              </dl>
123              <dl>
124                <!-- Status-->
125                <dt>{{ $t('pageInventory.table.statusState') }}:</dt>
126                <dd>{{ dataFormatter(item.statusState) }}</dd>
127              </dl>
128              <dl>
129                <!-- Enabled-->
130                <dt>{{ $t('pageInventory.table.enabled') }}:</dt>
131                <dd>{{ dataFormatter(item.enabled) }}</dd>
132              </dl>
133            </b-col>
134          </b-row>
135          <div class="section-divider mb-3 mt-3"></div>
136          <b-row>
137            <b-col sm="6" xl="6">
138              <dl>
139                <!-- Description -->
140                <dt>{{ $t('pageInventory.table.description') }}:</dt>
141                <dd>{{ dataFormatter(item.description) }}</dd>
142              </dl>
143              <dl>
144                <!-- Memory Type -->
145                <dt>{{ $t('pageInventory.table.memoryType') }}:</dt>
146                <dd>{{ dataFormatter(item.memoryType) }}</dd>
147              </dl>
148              <dl>
149                <!-- Base Module Type -->
150                <dt>{{ $t('pageInventory.table.baseModuleType') }}:</dt>
151                <dd>
152                  {{ dataFormatter(item.baseModuleType) }}
153                </dd>
154              </dl>
155            </b-col>
156            <b-col sm="6" xl="6">
157              <dl>
158                <!-- Bus Width Bits -->
159                <dt>{{ $t('pageInventory.table.busWidthBits') }}:</dt>
160                <dd>
161                  {{ dataFormatter(item.busWidthBits) }}
162                  {{ $t('unit.bit') }}
163                </dd>
164              </dl>
165              <dl>
166                <!-- Data Width Bits -->
167                <dt>{{ $t('pageInventory.table.dataWidthBits') }}:</dt>
168                <dd>
169                  {{ dataFormatter(item.dataWidthBits) }}
170                  {{ $t('unit.bit') }}
171                </dd>
172              </dl>
173              <dl>
174                <!-- Operating Speed Mhz -->
175                <dt>{{ $t('pageInventory.table.operatingSpeedMhz') }}:</dt>
176                <dd>
177                  {{ dataFormatter(item.operatingSpeedMhz) }}
178                  {{ $t('unit.MHz') }}
179                </dd>
180              </dl>
181              <dl>
182                <!-- Error Correction -->
183                <dt>{{ $t('pageInventory.table.errorCorrection') }}:</dt>
184                <dd>
185                  {{ dataFormatter(item.errorCorrection) }}
186                </dd>
187              </dl>
188            </b-col>
189          </b-row>
190        </b-container>
191      </template>
192    </b-table>
193  </page-section>
194</template>
195
196<script>
197import PageSection from '@/components/Global/PageSection';
198import IconChevron from '@carbon/icons-vue/es/chevron--down/20';
199
200import StatusIcon from '@/components/Global/StatusIcon';
201import TableCellCount from '@/components/Global/TableCellCount';
202
203import BVToastMixin from '@/components/Mixins/BVToastMixin';
204import DataFormatterMixin from '@/components/Mixins/DataFormatterMixin';
205import TableSortMixin from '@/components/Mixins/TableSortMixin';
206import Search from '@/components/Global/Search';
207import SearchFilterMixin, {
208  searchFilter,
209} from '@/components/Mixins/SearchFilterMixin';
210import TableRowExpandMixin, {
211  expandRowLabel,
212} from '@/components/Mixins/TableRowExpandMixin';
213import { useI18n } from 'vue-i18n';
214import i18n from '@/i18n';
215
216export default {
217  components: {
218    IconChevron,
219    PageSection,
220    StatusIcon,
221    Search,
222    TableCellCount,
223  },
224  mixins: [
225    BVToastMixin,
226    TableRowExpandMixin,
227    DataFormatterMixin,
228    TableSortMixin,
229    SearchFilterMixin,
230  ],
231  data() {
232    return {
233      $t: useI18n().t,
234      isBusy: true,
235      fields: [
236        {
237          key: 'expandRow',
238          label: '',
239          tdClass: 'table-row-expand',
240        },
241        {
242          key: 'id',
243          label: i18n.global.t('pageInventory.table.id'),
244          formatter: this.dataFormatter,
245        },
246        {
247          key: 'health',
248          label: i18n.global.t('pageInventory.table.health'),
249          formatter: this.dataFormatter,
250          tdClass: 'text-nowrap',
251        },
252        {
253          key: 'statusState',
254          label: i18n.global.t('pageInventory.table.state'),
255          formatter: this.dataFormatter,
256          tdClass: 'text-nowrap',
257        },
258        {
259          key: 'locationNumber',
260          label: i18n.global.t('pageInventory.table.locationNumber'),
261          formatter: this.dataFormatter,
262        },
263        {
264          key: 'identifyLed',
265          label: i18n.global.t('pageInventory.table.identifyLed'),
266          formatter: this.dataFormatter,
267        },
268      ],
269      searchFilter: searchFilter,
270      searchTotalFilteredRows: 0,
271      expandRowLabel: expandRowLabel,
272    };
273  },
274  computed: {
275    filteredRows() {
276      return this.searchFilter
277        ? this.searchTotalFilteredRows
278        : this.dimms.length;
279    },
280    dimms() {
281      return this.$store.getters['memory/dimms'];
282    },
283  },
284  created() {
285    this.$store.dispatch('memory/getDimms').finally(() => {
286      // Emit initial data fetch complete to parent component
287      require('@/eventBus').default.$emit('hardware-status-dimm-slot-complete');
288      this.isBusy = false;
289    });
290  },
291  methods: {
292    sortCompare(a, b, key) {
293      if (key === 'health') {
294        return this.sortStatus(a, b, key);
295      } else if (key === 'statusState') {
296        return this.sortStatusState(a, b, key);
297      }
298    },
299    onFiltered(filteredItems) {
300      this.searchTotalFilteredRows = filteredItems.length;
301    },
302    toggleIdentifyLedValue(row) {
303      this.$store
304        .dispatch('memory/updateIdentifyLedValue', {
305          uri: row.uri,
306          identifyLed: row.identifyLed,
307        })
308        .then((message) => this.successToast(message))
309        .catch(({ message }) => this.errorToast(message));
310    },
311    hasIdentifyLed(identifyLed) {
312      return typeof identifyLed === 'boolean';
313    },
314    statusStateIcon(status) {
315      switch (status) {
316        case 'Enabled':
317          return 'success';
318        case 'Absent':
319          return 'warning';
320        default:
321          return '';
322      }
323    },
324    sortStatusState(a, b, key) {
325      const statusState = ['Enabled', 'Absent'];
326      return statusState.indexOf(a[key]) - statusState.indexOf(b[key]);
327    },
328  },
329};
330</script>
331