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'; 175import { useI18n } from 'vue-i18n'; 176import i18n from '@/i18n'; 177 178export default { 179 components: { IconChevron, PageSection, StatusIcon, Search, TableCellCount }, 180 mixins: [ 181 BVToastMixin, 182 TableRowExpandMixin, 183 DataFormatterMixin, 184 TableSortMixin, 185 SearchFilterMixin, 186 ], 187 data() { 188 return { 189 $t: useI18n().t, 190 isBusy: true, 191 fields: [ 192 { 193 key: 'expandRow', 194 label: '', 195 tdClass: 'table-row-expand', 196 sortable: false, 197 }, 198 { 199 key: 'id', 200 label: i18n.global.t('pageInventory.table.id'), 201 formatter: this.dataFormatter, 202 sortable: true, 203 }, 204 { 205 key: 'health', 206 label: i18n.global.t('pageInventory.table.health'), 207 formatter: this.dataFormatter, 208 sortable: true, 209 tdClass: 'text-nowrap', 210 }, 211 { 212 key: 'statusState', 213 label: i18n.global.t('pageInventory.table.state'), 214 formatter: this.dataFormatter, 215 sortable: true, 216 tdClass: 'text-nowrap', 217 }, 218 { 219 key: 'locationNumber', 220 label: i18n.global.t('pageInventory.table.locationNumber'), 221 formatter: this.dataFormatter, 222 sortable: true, 223 }, 224 { 225 key: 'identifyLed', 226 label: i18n.global.t('pageInventory.table.identifyLed'), 227 formatter: this.dataFormatter, 228 sortable: false, 229 }, 230 ], 231 searchFilter: searchFilter, 232 searchTotalFilteredRows: 0, 233 expandRowLabel: expandRowLabel, 234 }; 235 }, 236 computed: { 237 filteredRows() { 238 return this.searchFilter 239 ? this.searchTotalFilteredRows 240 : this.processors.length; 241 }, 242 processors() { 243 return this.$store.getters['processors/processors']; 244 }, 245 }, 246 created() { 247 this.$store.dispatch('processors/getProcessorsInfo').finally(() => { 248 // Emit initial data fetch complete to parent component 249 this.$root.$emit('hardware-status-processors-complete'); 250 this.isBusy = false; 251 }); 252 }, 253 methods: { 254 onFiltered(filteredItems) { 255 this.searchTotalFilteredRows = filteredItems.length; 256 }, 257 toggleIdentifyLedValue(row) { 258 this.$store 259 .dispatch('processors/updateIdentifyLedValue', { 260 uri: row.uri, 261 identifyLed: row.identifyLed, 262 }) 263 .then((message) => this.successToast(message)) 264 .catch(({ message }) => this.errorToast(message)); 265 }, 266 // TO DO: remove hasIdentifyLed when the following is merged: 267 // https://gerrit.openbmc-project.xyz/c/openbmc/bmcweb/+/37045 268 hasIdentifyLed(identifyLed) { 269 return typeof identifyLed === 'boolean'; 270 }, 271 statusStateIcon(status) { 272 switch (status) { 273 case 'Enabled': 274 return 'success'; 275 case 'Absent': 276 return 'warning'; 277 default: 278 return ''; 279 } 280 }, 281 }, 282}; 283</script> 284