1<template> 2 <page-section :section-title="$t('pageInventory.chassis')"> 3 <b-table 4 responsive="md" 5 hover 6 :items="chassis" 7 :fields="fields" 8 show-empty 9 :empty-text="$t('global.table.emptyMessage')" 10 :busy="isBusy" 11 > 12 <!-- Expand chevron icon --> 13 <template #cell(expandRow)="row"> 14 <b-button 15 variant="link" 16 data-test-id="hardwareStatus-button-expandChassis" 17 :title="expandRowLabel" 18 class="btn-icon-only" 19 @click="toggleRowDetails(row)" 20 > 21 <icon-chevron /> 22 <span class="sr-only">{{ expandRowLabel }}</span> 23 </b-button> 24 </template> 25 26 <!-- Health --> 27 <template #cell(health)="{ value }"> 28 <status-icon :status="statusIcon(value)" /> 29 {{ value }} 30 </template> 31 <!-- Toggle identify LED --> 32 <template #cell(identifyLed)="row"> 33 <b-form-checkbox 34 v-if="hasIdentifyLed(row.item.identifyLed)" 35 v-model="row.item.identifyLed" 36 name="switch" 37 switch 38 @change="toggleIdentifyLedValue(row.item)" 39 > 40 <span v-if="row.item.identifyLed"> 41 {{ $t('global.status.on') }} 42 </span> 43 <span v-else> {{ $t('global.status.off') }} </span> 44 </b-form-checkbox> 45 <div v-else>--</div> 46 </template> 47 <template #row-details="{ item }"> 48 <b-container fluid> 49 <b-row> 50 <b-col class="mt-2" sm="6" xl="6"> 51 <dl> 52 <!-- Name --> 53 <dt>{{ $t('pageInventory.table.name') }}:</dt> 54 <dd>{{ dataFormatter(item.name) }}</dd> 55 <!-- Part number --> 56 <dt>{{ $t('pageInventory.table.partNumber') }}:</dt> 57 <dd>{{ dataFormatter(item.partNumber) }}</dd> 58 <!-- Serial Number --> 59 <dt>{{ $t('pageInventory.table.serialNumber') }}:</dt> 60 <dd>{{ dataFormatter(item.serialNumber) }}</dd> 61 <!-- Model --> 62 <dt>{{ $t('pageInventory.table.model') }}:</dt> 63 <dd class="mb-2"> 64 {{ dataFormatter(item.model) }} 65 </dd> 66 <!-- Asset tag --> 67 <dt>{{ $t('pageInventory.table.assetTag') }}:</dt> 68 <dd class="mb-2"> 69 {{ dataFormatter(item.assetTag) }} 70 </dd> 71 </dl> 72 </b-col> 73 <b-col class="mt-2" sm="6" xl="6"> 74 <dl> 75 <!-- Status state --> 76 <dt>{{ $t('pageInventory.table.statusState') }}:</dt> 77 <dd>{{ dataFormatter(item.statusState) }}</dd> 78 <!-- Power state --> 79 <dt>{{ $t('pageInventory.table.power') }}:</dt> 80 <dd>{{ dataFormatter(item.power) }}</dd> 81 <!-- Health rollup --> 82 <dt>{{ $t('pageInventory.table.healthRollup') }}:</dt> 83 <dd>{{ dataFormatter(item.healthRollup) }}</dd> 84 </dl> 85 </b-col> 86 </b-row> 87 <div class="section-divider mb-3 mt-3"></div> 88 <b-row> 89 <b-col class="mt-2" sm="6" xl="6"> 90 <dl> 91 <!-- Manufacturer --> 92 <dt>{{ $t('pageInventory.table.manufacturer') }}:</dt> 93 <dd>{{ dataFormatter(item.manufacturer) }}</dd> 94 <!-- Chassis Type --> 95 <dt>{{ $t('pageInventory.table.chassisType') }}:</dt> 96 <dd>{{ dataFormatter(item.chassisType) }}</dd> 97 </dl> 98 </b-col> 99 <b-col class="mt-2" sm="6" xl="6"> 100 <dl> 101 <!-- Min power --> 102 <dt>{{ $t('pageInventory.table.minPowerWatts') }}:</dt> 103 <dd>{{ dataFormatter(item.minPowerWatts) }}</dd> 104 <!-- Max power --> 105 <dt>{{ $t('pageInventory.table.maxPowerWatts') }}:</dt> 106 <dd>{{ dataFormatter(item.maxPowerWatts) }}</dd> 107 </dl> 108 </b-col> 109 </b-row> 110 </b-container> 111 </template> 112 </b-table> 113 </page-section> 114</template> 115 116<script> 117import PageSection from '@/components/Global/PageSection'; 118import IconChevron from '@carbon/icons-vue/es/chevron--down/20'; 119import BVToastMixin from '@/components/Mixins/BVToastMixin'; 120import StatusIcon from '@/components/Global/StatusIcon'; 121 122import TableRowExpandMixin, { 123 expandRowLabel, 124} from '@/components/Mixins/TableRowExpandMixin'; 125import DataFormatterMixin from '@/components/Mixins/DataFormatterMixin'; 126 127export default { 128 components: { IconChevron, PageSection, StatusIcon }, 129 mixins: [BVToastMixin, TableRowExpandMixin, DataFormatterMixin], 130 data() { 131 return { 132 isBusy: true, 133 fields: [ 134 { 135 key: 'expandRow', 136 label: '', 137 tdClass: 'table-row-expand', 138 }, 139 { 140 key: 'id', 141 label: this.$t('pageInventory.table.id'), 142 formatter: this.dataFormatter, 143 }, 144 { 145 key: 'health', 146 label: this.$t('pageInventory.table.health'), 147 formatter: this.dataFormatter, 148 tdClass: 'text-nowrap', 149 }, 150 { 151 key: 'locationNumber', 152 label: this.$t('pageInventory.table.locationNumber'), 153 formatter: this.dataFormatter, 154 }, 155 { 156 key: 'identifyLed', 157 label: this.$t('pageInventory.table.identifyLed'), 158 formatter: this.dataFormatter, 159 }, 160 ], 161 expandRowLabel: expandRowLabel, 162 }; 163 }, 164 computed: { 165 chassis() { 166 return this.$store.getters['chassis/chassis']; 167 }, 168 }, 169 created() { 170 this.$store.dispatch('chassis/getChassisInfo').finally(() => { 171 // Emit initial data fetch complete to parent component 172 this.$root.$emit('hardware-status-chassis-complete'); 173 this.isBusy = false; 174 }); 175 }, 176 methods: { 177 toggleIdentifyLedValue(row) { 178 this.$store 179 .dispatch('chassis/updateIdentifyLedValue', { 180 uri: row.uri, 181 identifyLed: row.identifyLed, 182 }) 183 .catch(({ message }) => this.errorToast(message)); 184 }, 185 // TO DO: Remove this method when the LocationIndicatorActive is added from backend. 186 hasIdentifyLed(identifyLed) { 187 return typeof identifyLed === 'boolean'; 188 }, 189 }, 190}; 191</script> 192