1<template> 2 <page-section :section-title="$t('pageInventory.powerSupplies')"> 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="powerSupplies.length" 14 ></table-cell-count> 15 </b-col> 16 </b-row> 17 <b-table 18 sort-icon-left 19 no-sort-reset 20 hover 21 responsive="md" 22 sort-by="health" 23 show-empty 24 :items="powerSupplies" 25 :fields="fields" 26 :sort-desc="true" 27 :sort-compare="sortCompare" 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-expandPowerSupplies" 39 :title="expandRowLabel" 40 class="btn-icon-only" 41 @click="toggleRowDetails(row)" 42 > 43 <icon-chevron /> 44 <span class="sr-only">{{ expandRowLabel }}</span> 45 </b-button> 46 </template> 47 48 <!-- Health --> 49 <template #cell(health)="{ value }"> 50 <status-icon :status="statusIcon(value)" /> 51 {{ value }} 52 </template> 53 54 <template #row-details="{ item }"> 55 <b-container fluid> 56 <b-row> 57 <b-col sm="6" xl="4"> 58 <dl> 59 <!-- Name --> 60 <dt>{{ $t('pageInventory.table.name') }}:</dt> 61 <dd>{{ dataFormatter(item.name) }}</dd> 62 <!-- Part number --> 63 <dt>{{ $t('pageInventory.table.partNumber') }}:</dt> 64 <dd>{{ dataFormatter(item.partNumber) }}</dd> 65 <!-- Serial number --> 66 <dt>{{ $t('pageInventory.table.serialNumber') }}:</dt> 67 <dd>{{ dataFormatter(item.serialNumber) }}</dd> 68 <!-- Spare part number --> 69 <dt>{{ $t('pageInventory.table.sparePartNumber') }}:</dt> 70 <dd>{{ dataFormatter(item.sparePartNumber) }}</dd> 71 <!-- Model --> 72 <dt>{{ $t('pageInventory.table.model') }}:</dt> 73 <dd>{{ dataFormatter(item.model) }}</dd> 74 </dl> 75 </b-col> 76 <b-col sm="6" xl="4"> 77 <dl> 78 <!-- Status state --> 79 <dt>{{ $t('pageInventory.table.statusState') }}:</dt> 80 <dd>{{ dataFormatter(item.statusState) }}</dd> 81 <!-- Status Health rollup state --> 82 <dt>{{ $t('pageInventory.table.statusHealthRollup') }}:</dt> 83 <dd>{{ dataFormatter(item.statusHealth) }}</dd> 84 <!-- Efficiency percent --> 85 <dt>{{ $t('pageInventory.table.efficiencyPercent') }}:</dt> 86 <dd> 87 {{ dataFormatter(item.efficiencyPercent) }} 88 {{ $t('unit.Percent') }} 89 </dd> 90 <!-- Power input watts --> 91 <dt>{{ $t('pageInventory.table.powerInputWatts') }}:</dt> 92 <dd> 93 {{ dataFormatter(item.powerInputWatts) }} 94 {{ $t('unit.W') }} 95 </dd> 96 </dl> 97 </b-col> 98 </b-row> 99 <div class="section-divider mb-3 mt-3"></div> 100 <b-row> 101 <b-col sm="6" xl="4"> 102 <dl> 103 <!-- Manufacturer --> 104 <dt>{{ $t('pageInventory.table.manufacturer') }}:</dt> 105 <dd>{{ dataFormatter(item.manufacturer) }}</dd> 106 </dl> 107 </b-col> 108 <b-col sm="6" xl="4"> 109 <dl> 110 <!-- Firmware version --> 111 <dt>{{ $t('pageInventory.table.firmwareVersion') }}:</dt> 112 <dd>{{ dataFormatter(item.firmwareVersion) }}</dd> 113 </dl> 114 </b-col> 115 </b-row> 116 </b-container> 117 </template> 118 </b-table> 119 </page-section> 120</template> 121 122<script> 123import PageSection from '@/components/Global/PageSection'; 124import IconChevron from '@carbon/icons-vue/es/chevron--down/20'; 125 126import StatusIcon from '@/components/Global/StatusIcon'; 127import TableCellCount from '@/components/Global/TableCellCount'; 128import DataFormatterMixin from '@/components/Mixins/DataFormatterMixin'; 129import TableSortMixin from '@/components/Mixins/TableSortMixin'; 130import Search from '@/components/Global/Search'; 131import SearchFilterMixin, { 132 searchFilter, 133} from '@/components/Mixins/SearchFilterMixin'; 134import TableRowExpandMixin, { 135 expandRowLabel, 136} from '@/components/Mixins/TableRowExpandMixin'; 137 138export default { 139 components: { IconChevron, PageSection, StatusIcon, Search, TableCellCount }, 140 mixins: [ 141 TableRowExpandMixin, 142 DataFormatterMixin, 143 TableSortMixin, 144 SearchFilterMixin, 145 ], 146 data() { 147 return { 148 isBusy: true, 149 fields: [ 150 { 151 key: 'expandRow', 152 label: '', 153 tdClass: 'table-row-expand', 154 sortable: false, 155 }, 156 { 157 key: 'id', 158 label: this.$t('pageInventory.table.id'), 159 formatter: this.dataFormatter, 160 sortable: true, 161 }, 162 { 163 key: 'health', 164 label: this.$t('pageInventory.table.health'), 165 formatter: this.dataFormatter, 166 sortable: true, 167 tdClass: 'text-nowrap', 168 }, 169 { 170 key: 'locationNumber', 171 label: this.$t('pageInventory.table.locationNumber'), 172 formatter: this.dataFormatter, 173 sortable: true, 174 }, 175 { 176 key: 'identifyLed', 177 label: this.$t('pageInventory.table.identifyLed'), 178 formatter: this.dataFormatter, 179 }, 180 ], 181 searchFilter: searchFilter, 182 searchTotalFilteredRows: 0, 183 expandRowLabel: expandRowLabel, 184 }; 185 }, 186 computed: { 187 filteredRows() { 188 return this.searchFilter 189 ? this.searchTotalFilteredRows 190 : this.powerSupplies.length; 191 }, 192 powerSupplies() { 193 return this.$store.getters['powerSupply/powerSupplies']; 194 }, 195 }, 196 created() { 197 this.$store.dispatch('powerSupply/getAllPowerSupplies').finally(() => { 198 // Emit initial data fetch complete to parent component 199 this.$root.$emit('hardware-status-power-supplies-complete'); 200 this.isBusy = false; 201 }); 202 }, 203 methods: { 204 sortCompare(a, b, key) { 205 if (key === 'health') { 206 return this.sortStatus(a, b, key); 207 } 208 }, 209 onFiltered(filteredItems) { 210 this.searchTotalFilteredRows = filteredItems.length; 211 }, 212 }, 213}; 214</script> 215