1<template>
2  <b-container fluid="xl">
3    <page-title />
4    <b-row class="align-items-end">
5      <b-col sm="6" md="5" xl="4">
6        <search
7          :placeholder="$t('pageSensors.searchForSensors')"
8          data-test-id="sensors-input-searchForSensors"
9          @change-search="onChangeSearchInput"
10          @clear-search="onClearSearchInput"
11        />
12      </b-col>
13      <b-col sm="3" md="3" xl="2">
14        <table-cell-count
15          :filtered-items-count="filteredRows"
16          :total-number-of-cells="allSensors.length"
17        ></table-cell-count>
18      </b-col>
19      <b-col sm="3" md="4" xl="6" class="text-right">
20        <table-filter :filters="tableFilters" @filter-change="onFilterChange" />
21      </b-col>
22    </b-row>
23    <b-row>
24      <b-col xl="12">
25        <table-toolbar
26          ref="toolbar"
27          :selected-items-count="selectedRows.length"
28          @clear-selected="clearSelectedRows($refs.table)"
29        >
30          <template #toolbar-buttons>
31            <table-toolbar-export
32              :data="selectedRows"
33              :file-name="exportFileNameByDate()"
34            />
35          </template>
36        </table-toolbar>
37        <b-table
38          ref="table"
39          responsive="md"
40          selectable
41          no-select-on-click
42          sort-icon-left
43          hover
44          no-sort-reset
45          sticky-header="75vh"
46          sort-by="status"
47          show-empty
48          :no-border-collapse="true"
49          :items="filteredSensors"
50          :fields="fields"
51          :sort-desc="true"
52          :sort-compare="sortCompare"
53          :filter="searchFilter"
54          :empty-text="$t('global.table.emptyMessage')"
55          :empty-filtered-text="$t('global.table.emptySearchMessage')"
56          :busy="isBusy"
57          @filtered="onFiltered"
58          @row-selected="onRowSelected($event, filteredSensors.length)"
59        >
60          <!-- Checkbox column -->
61          <template #head(checkbox)>
62            <b-form-checkbox
63              v-model="tableHeaderCheckboxModel"
64              :indeterminate="tableHeaderCheckboxIndeterminate"
65              @change="onChangeHeaderCheckbox($refs.table)"
66            >
67              <span class="sr-only">{{ $t('global.table.selectAll') }}</span>
68            </b-form-checkbox>
69          </template>
70          <template #cell(checkbox)="row">
71            <b-form-checkbox
72              v-model="row.rowSelected"
73              @change="toggleSelectRow($refs.table, row.index)"
74            >
75              <span class="sr-only">{{ $t('global.table.selectItem') }}</span>
76            </b-form-checkbox>
77          </template>
78
79          <template #cell(status)="{ value }">
80            <status-icon :status="statusIcon(value)" /> {{ value }}
81          </template>
82          <template #cell(currentValue)="data">
83            {{ data.value }} {{ data.item.units }}
84          </template>
85          <template #cell(lowerCaution)="data">
86            {{ data.value }} {{ data.item.units }}
87          </template>
88          <template #cell(upperCaution)="data">
89            {{ data.value }} {{ data.item.units }}
90          </template>
91          <template #cell(lowerCritical)="data">
92            {{ data.value }} {{ data.item.units }}
93          </template>
94          <template #cell(upperCritical)="data">
95            {{ data.value }} {{ data.item.units }}
96          </template>
97        </b-table>
98      </b-col>
99    </b-row>
100  </b-container>
101</template>
102
103<script>
104import PageTitle from '@/components/Global/PageTitle';
105import Search from '@/components/Global/Search';
106import StatusIcon from '@/components/Global/StatusIcon';
107import TableFilter from '@/components/Global/TableFilter';
108import TableToolbar from '@/components/Global/TableToolbar';
109import TableToolbarExport from '@/components/Global/TableToolbarExport';
110import TableCellCount from '@/components/Global/TableCellCount';
111
112import BVTableSelectableMixin, {
113  selectedRows,
114  tableHeaderCheckboxModel,
115  tableHeaderCheckboxIndeterminate,
116} from '@/components/Mixins/BVTableSelectableMixin';
117import LoadingBarMixin from '@/components/Mixins/LoadingBarMixin';
118import TableFilterMixin from '@/components/Mixins/TableFilterMixin';
119import DataFormatterMixin from '@/components/Mixins/DataFormatterMixin';
120import TableSortMixin from '@/components/Mixins/TableSortMixin';
121import SearchFilterMixin, {
122  searchFilter,
123} from '@/components/Mixins/SearchFilterMixin';
124import { useI18n } from 'vue-i18n';
125import i18n from '@/i18n';
126
127export default {
128  name: 'Sensors',
129  components: {
130    PageTitle,
131    Search,
132    StatusIcon,
133    TableCellCount,
134    TableFilter,
135    TableToolbar,
136    TableToolbarExport,
137  },
138  mixins: [
139    TableFilterMixin,
140    BVTableSelectableMixin,
141    LoadingBarMixin,
142    DataFormatterMixin,
143    TableSortMixin,
144    SearchFilterMixin,
145  ],
146  beforeRouteLeave(to, from, next) {
147    this.hideLoader();
148    next();
149  },
150  data() {
151    return {
152      $t: useI18n().t,
153      isBusy: true,
154      fields: [
155        {
156          key: 'checkbox',
157          sortable: false,
158          label: '',
159        },
160        {
161          key: 'name',
162          sortable: true,
163          label: i18n.global.t('pageSensors.table.name'),
164        },
165        {
166          key: 'status',
167          sortable: true,
168          label: i18n.global.t('pageSensors.table.status'),
169          tdClass: 'text-nowrap',
170        },
171        {
172          key: 'lowerCritical',
173          formatter: this.dataFormatter,
174          label: i18n.global.t('pageSensors.table.lowerCritical'),
175        },
176        {
177          key: 'lowerCaution',
178          formatter: this.dataFormatter,
179          label: i18n.global.t('pageSensors.table.lowerWarning'),
180        },
181
182        {
183          key: 'currentValue',
184          formatter: this.dataFormatter,
185          label: i18n.global.t('pageSensors.table.currentValue'),
186        },
187        {
188          key: 'upperCaution',
189          formatter: this.dataFormatter,
190          label: i18n.global.t('pageSensors.table.upperWarning'),
191        },
192        {
193          key: 'upperCritical',
194          formatter: this.dataFormatter,
195          label: i18n.global.t('pageSensors.table.upperCritical'),
196        },
197      ],
198      tableFilters: [
199        {
200          key: 'status',
201          label: i18n.global.t('pageSensors.table.status'),
202          values: [
203            i18n.global.t('global.action.ok'),
204            i18n.global.t('global.action.warning'),
205            i18n.global.t('global.action.critical'),
206          ],
207        },
208      ],
209      activeFilters: [],
210      searchFilter: searchFilter,
211      searchTotalFilteredRows: 0,
212      selectedRows: selectedRows,
213      tableHeaderCheckboxModel: tableHeaderCheckboxModel,
214      tableHeaderCheckboxIndeterminate: tableHeaderCheckboxIndeterminate,
215    };
216  },
217  computed: {
218    allSensors() {
219      return this.$store.getters['sensors/sensors'];
220    },
221    filteredRows() {
222      return this.searchFilter
223        ? this.searchTotalFilteredRows
224        : this.filteredSensors.length;
225    },
226    filteredSensors() {
227      return this.getFilteredTableData(this.allSensors, this.activeFilters);
228    },
229  },
230  created() {
231    this.startLoader();
232    this.$store.dispatch('sensors/getAllSensors').finally(() => {
233      this.endLoader();
234      this.isBusy = false;
235    });
236  },
237  methods: {
238    sortCompare(a, b, key) {
239      if (key === 'status') {
240        return this.sortStatus(a, b, key);
241      }
242    },
243    onFilterChange({ activeFilters }) {
244      this.activeFilters = activeFilters;
245    },
246    onFiltered(filteredItems) {
247      this.searchTotalFilteredRows = filteredItems.length;
248    },
249    onChangeSearchInput(event) {
250      this.searchFilter = event;
251    },
252    exportFileNameByDate() {
253      // Create export file name based on date
254      let date = new Date();
255      date =
256        date.toISOString().slice(0, 10) +
257        '_' +
258        date.toString().split(':').join('-').split(' ')[4];
259      return i18n.global.t('pageSensors.exportFilePrefix') + date;
260    },
261  },
262};
263</script>
264