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