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