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