From 8047ae3d83ba0718fb7a42907036157e5c680b85 Mon Sep 17 00:00:00 2001 From: "Andrey V.Kosteltsev" Date: Mon, 4 Jul 2022 23:59:32 +0300 Subject: IBS: _sila UI theme --- src/components/_sila/Mixins/BVPaginationMixin.js | 34 ++++++ .../_sila/Mixins/BVTableSelectableMixin.js | 41 ++++++++ src/components/_sila/Mixins/BVToastMixin.js | 115 +++++++++++++++++++++ src/components/_sila/Mixins/DataFormatterMixin.js | 30 ++++++ src/components/_sila/Mixins/JumpLinkMixin.js | 27 +++++ src/components/_sila/Mixins/LoadingBarMixin.js | 19 ++++ .../_sila/Mixins/LocalTimezoneLabelMixin.js | 14 +++ src/components/_sila/Mixins/SearchFilterMixin.js | 14 +++ src/components/_sila/Mixins/TableFilterMixin.js | 58 +++++++++++ src/components/_sila/Mixins/TableRowExpandMixin.js | 15 +++ src/components/_sila/Mixins/TableSortMixin.js | 11 ++ src/components/_sila/Mixins/VuelidateMixin.js | 10 ++ 12 files changed, 388 insertions(+) create mode 100644 src/components/_sila/Mixins/BVPaginationMixin.js create mode 100644 src/components/_sila/Mixins/BVTableSelectableMixin.js create mode 100644 src/components/_sila/Mixins/BVToastMixin.js create mode 100644 src/components/_sila/Mixins/DataFormatterMixin.js create mode 100644 src/components/_sila/Mixins/JumpLinkMixin.js create mode 100644 src/components/_sila/Mixins/LoadingBarMixin.js create mode 100644 src/components/_sila/Mixins/LocalTimezoneLabelMixin.js create mode 100644 src/components/_sila/Mixins/SearchFilterMixin.js create mode 100644 src/components/_sila/Mixins/TableFilterMixin.js create mode 100644 src/components/_sila/Mixins/TableRowExpandMixin.js create mode 100644 src/components/_sila/Mixins/TableSortMixin.js create mode 100644 src/components/_sila/Mixins/VuelidateMixin.js (limited to 'src/components/_sila/Mixins') diff --git a/src/components/_sila/Mixins/BVPaginationMixin.js b/src/components/_sila/Mixins/BVPaginationMixin.js new file mode 100644 index 00000000..4ccf6f2c --- /dev/null +++ b/src/components/_sila/Mixins/BVPaginationMixin.js @@ -0,0 +1,34 @@ +import i18n from '@/i18n'; +export const currentPage = 1; +export const perPage = 20; +export const itemsPerPageOptions = [ + { + value: 10, + text: '10', + }, + { + value: 20, + text: '20', + }, + { + value: 30, + text: '30', + }, + { + value: 40, + text: '40', + }, + { + value: 0, + text: i18n.t('global.table.viewAll'), + }, +]; +const BVPaginationMixin = { + methods: { + getTotalRowCount(count) { + return this.perPage === 0 ? 0 : count; + }, + }, +}; + +export default BVPaginationMixin; diff --git a/src/components/_sila/Mixins/BVTableSelectableMixin.js b/src/components/_sila/Mixins/BVTableSelectableMixin.js new file mode 100644 index 00000000..b4f0b953 --- /dev/null +++ b/src/components/_sila/Mixins/BVTableSelectableMixin.js @@ -0,0 +1,41 @@ +export const selectedRows = []; +export const tableHeaderCheckboxModel = false; +export const tableHeaderCheckboxIndeterminate = false; + +const BVTableSelectableMixin = { + methods: { + clearSelectedRows(tableRef) { + if (tableRef) tableRef.clearSelected(); + }, + toggleSelectRow(tableRef, rowIndex) { + if (tableRef && rowIndex !== undefined) { + tableRef.isRowSelected(rowIndex) + ? tableRef.unselectRow(rowIndex) + : tableRef.selectRow(rowIndex); + } + }, + onRowSelected(selectedRows, totalRowsCount) { + if (selectedRows && totalRowsCount !== undefined) { + this.selectedRows = selectedRows; + if (selectedRows.length === 0) { + this.tableHeaderCheckboxIndeterminate = false; + this.tableHeaderCheckboxModel = false; + } else if (selectedRows.length === totalRowsCount) { + this.tableHeaderCheckboxIndeterminate = false; + this.tableHeaderCheckboxModel = true; + } else { + this.tableHeaderCheckboxIndeterminate = true; + this.tableHeaderCheckboxModel = true; + } + } + }, + onChangeHeaderCheckbox(tableRef) { + if (tableRef) { + if (this.tableHeaderCheckboxModel) tableRef.selectAllRows(); + else tableRef.clearSelected(); + } + }, + }, +}; + +export default BVTableSelectableMixin; diff --git a/src/components/_sila/Mixins/BVToastMixin.js b/src/components/_sila/Mixins/BVToastMixin.js new file mode 100644 index 00000000..a04ef438 --- /dev/null +++ b/src/components/_sila/Mixins/BVToastMixin.js @@ -0,0 +1,115 @@ +import StatusIcon from '../Global/StatusIcon'; + +const BVToastMixin = { + components: { + StatusIcon, + }, + methods: { + $_BVToastMixin_createTitle(title, status) { + const statusIcon = this.$createElement('StatusIcon', { + props: { status }, + }); + const titleWithIcon = this.$createElement( + 'strong', + { class: 'toast-icon' }, + [statusIcon, title] + ); + return titleWithIcon; + }, + $_BVToastMixin_createBody(messageBody) { + if (Array.isArray(messageBody)) { + return messageBody.map((message) => + this.$createElement('p', { class: 'mb-0' }, message) + ); + } else { + return [this.$createElement('p', { class: 'mb-0' }, messageBody)]; + } + }, + $_BVToastMixin_createTimestamp() { + const timestamp = this.$options.filters.formatTime(new Date()); + return this.$createElement('p', { class: 'mt-3 mb-0' }, timestamp); + }, + $_BVToastMixin_createRefreshAction() { + return this.$createElement( + 'BLink', + { + class: 'd-inline-block mt-3', + on: { + click: () => { + this.$root.$emit('refresh-application'); + }, + }, + }, + this.$t('global.action.refresh') + ); + }, + $_BVToastMixin_initToast(body, title, variant) { + this.$root.$bvToast.toast(body, { + title, + variant, + autoHideDelay: 10000, //auto hide in milliseconds + noAutoHide: variant !== 'success', + isStatus: true, + solid: true, + }); + }, + successToast( + message, + { + title: t = this.$t('global.status.success'), + timestamp, + refreshAction, + } = {} + ) { + const body = this.$_BVToastMixin_createBody(message); + const title = this.$_BVToastMixin_createTitle(t, 'success'); + if (refreshAction) body.push(this.$_BVToastMixin_createRefreshAction()); + if (timestamp) body.push(this.$_BVToastMixin_createTimestamp()); + this.$_BVToastMixin_initToast(body, title, 'success'); + }, + errorToast( + message, + { + title: t = this.$t('global.status.error'), + timestamp, + refreshAction, + } = {} + ) { + const body = this.$_BVToastMixin_createBody(message); + const title = this.$_BVToastMixin_createTitle(t, 'danger'); + if (refreshAction) body.push(this.$_BVToastMixin_createRefreshAction()); + if (timestamp) body.push(this.$_BVToastMixin_createTimestamp()); + this.$_BVToastMixin_initToast(body, title, 'danger'); + }, + warningToast( + message, + { + title: t = this.$t('global.status.warning'), + timestamp, + refreshAction, + } = {} + ) { + const body = this.$_BVToastMixin_createBody(message); + const title = this.$_BVToastMixin_createTitle(t, 'warning'); + if (refreshAction) body.push(this.$_BVToastMixin_createRefreshAction()); + if (timestamp) body.push(this.$_BVToastMixin_createTimestamp()); + this.$_BVToastMixin_initToast(body, title, 'warning'); + }, + infoToast( + message, + { + title: t = this.$t('global.status.informational'), + timestamp, + refreshAction, + } = {} + ) { + const body = this.$_BVToastMixin_createBody(message); + const title = this.$_BVToastMixin_createTitle(t, 'info'); + if (refreshAction) body.push(this.$_BVToastMixin_createRefreshAction()); + if (timestamp) body.push(this.$_BVToastMixin_createTimestamp()); + this.$_BVToastMixin_initToast(body, title, 'info'); + }, + }, +}; + +export default BVToastMixin; diff --git a/src/components/_sila/Mixins/DataFormatterMixin.js b/src/components/_sila/Mixins/DataFormatterMixin.js new file mode 100644 index 00000000..5ce79327 --- /dev/null +++ b/src/components/_sila/Mixins/DataFormatterMixin.js @@ -0,0 +1,30 @@ +const DataFormatterMixin = { + methods: { + dataFormatter(value) { + if (value === undefined || value === null || value === '') { + return '--'; + } else if (typeof value === 'number') { + return parseFloat(value.toFixed(3)); + } else { + return value; + } + }, + statusIcon(status) { + switch (status) { + case 'OK': + return 'success'; + case 'Warning': + return 'warning'; + case 'Critical': + return 'danger'; + default: + return ''; + } + }, + dataFormatterArray(value) { + return value.join(', '); + }, + }, +}; + +export default DataFormatterMixin; diff --git a/src/components/_sila/Mixins/JumpLinkMixin.js b/src/components/_sila/Mixins/JumpLinkMixin.js new file mode 100644 index 00000000..b038527b --- /dev/null +++ b/src/components/_sila/Mixins/JumpLinkMixin.js @@ -0,0 +1,27 @@ +const JumpLinkMixin = { + methods: { + setFocus(element) { + element.setAttribute('tabindex', '-1'); + element.focus(); + // Reason: https://axesslab.com/skip-links/#update-3-a-comment-from-gov-uk + element.removeAttribute('tabindex'); + }, + scrollToOffset(event) { + // Select element to scroll to + const ref = event.target.getAttribute('data-ref'); + const element = this.$refs[ref].$el; + + // Set focus and tabindex on selected element + this.setFocus(element); + + // Set scroll offset below header + const offset = element.offsetTop - 50; + window.scroll({ + top: offset, + behavior: 'smooth', + }); + }, + }, +}; + +export default JumpLinkMixin; diff --git a/src/components/_sila/Mixins/LoadingBarMixin.js b/src/components/_sila/Mixins/LoadingBarMixin.js new file mode 100644 index 00000000..d1152703 --- /dev/null +++ b/src/components/_sila/Mixins/LoadingBarMixin.js @@ -0,0 +1,19 @@ +export const loading = true; + +const LoadingBarMixin = { + methods: { + startLoader() { + this.$root.$emit('loader-start'); + this.loading = true; + }, + endLoader() { + this.$root.$emit('loader-end'); + this.loading = false; + }, + hideLoader() { + this.$root.$emit('loader-hide'); + }, + }, +}; + +export default LoadingBarMixin; diff --git a/src/components/_sila/Mixins/LocalTimezoneLabelMixin.js b/src/components/_sila/Mixins/LocalTimezoneLabelMixin.js new file mode 100644 index 00000000..6b4141c6 --- /dev/null +++ b/src/components/_sila/Mixins/LocalTimezoneLabelMixin.js @@ -0,0 +1,14 @@ +import { format } from 'date-fns-tz'; + +const LocalTimezoneLabelMixin = { + methods: { + localOffset() { + const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone; + const shortTz = this.$options.filters.shortTimeZone(new Date()); + const pattern = `'${shortTz}' O`; + return format(new Date(), pattern, { timezone }).replace('GMT', 'UTC'); + }, + }, +}; + +export default LocalTimezoneLabelMixin; diff --git a/src/components/_sila/Mixins/SearchFilterMixin.js b/src/components/_sila/Mixins/SearchFilterMixin.js new file mode 100644 index 00000000..a4819e26 --- /dev/null +++ b/src/components/_sila/Mixins/SearchFilterMixin.js @@ -0,0 +1,14 @@ +export const searchFilter = null; + +const SearchFilterMixin = { + methods: { + onChangeSearchInput(searchValue) { + this.searchFilter = searchValue; + }, + onClearSearchInput() { + this.searchFilter = null; + }, + }, +}; + +export default SearchFilterMixin; diff --git a/src/components/_sila/Mixins/TableFilterMixin.js b/src/components/_sila/Mixins/TableFilterMixin.js new file mode 100644 index 00000000..7a2cc540 --- /dev/null +++ b/src/components/_sila/Mixins/TableFilterMixin.js @@ -0,0 +1,58 @@ +import { includes } from 'lodash'; + +const TableFilterMixin = { + methods: { + getFilteredTableData(tableData = [], filters = []) { + const filterItems = filters.reduce((arr, filter) => { + return [...arr, ...filter.values]; + }, []); + // If no filters are active, then return all table data + if (filterItems.length === 0) return tableData; + + // Check if row property value is included in list of + // active filters + return tableData.filter((row) => { + let returnRow = false; + for (const { key, values } of filters) { + const rowProperty = row[key]; + if (rowProperty && includes(values, rowProperty)) { + returnRow = true; + break; + } + } + return returnRow; + }); + }, + getFilteredTableDataByDate( + tableData = [], + startDate, + endDate, + propertyKey = 'date' + ) { + if (!startDate && !endDate) return tableData; + let startDateInMs = startDate ? startDate.getTime() : 0; + let endDateInMs = endDate ? endDate.getTime() : Number.POSITIVE_INFINITY; + + const isUtcDisplay = this.$store.getters['global/isUtcDisplay']; + + //Offset preference selected + if (!isUtcDisplay) { + startDateInMs = startDate + ? startDate.getTime() + startDate.getTimezoneOffset() * 60000 + : 0; + endDateInMs = endDate + ? endDate.getTime() + endDate.getTimezoneOffset() * 60000 + : Number.POSITIVE_INFINITY; + } + + return tableData.filter((row) => { + const date = row[propertyKey]; + if (!(date instanceof Date)) return; + const dateInMs = date.getTime(); + if (dateInMs >= startDateInMs && dateInMs <= endDateInMs) return row; + }); + }, + }, +}; + +export default TableFilterMixin; diff --git a/src/components/_sila/Mixins/TableRowExpandMixin.js b/src/components/_sila/Mixins/TableRowExpandMixin.js new file mode 100644 index 00000000..7f815a46 --- /dev/null +++ b/src/components/_sila/Mixins/TableRowExpandMixin.js @@ -0,0 +1,15 @@ +import i18n from '@/i18n'; +export const expandRowLabel = i18n.t('global.table.expandTableRow'); + +const TableRowExpandMixin = { + methods: { + toggleRowDetails(row) { + row.toggleDetails(); + row.detailsShowing + ? (this.expandRowLabel = this.$t('global.table.expandTableRow')) + : (this.expandRowLabel = this.$t('global.table.collapseTableRow')); + }, + }, +}; + +export default TableRowExpandMixin; diff --git a/src/components/_sila/Mixins/TableSortMixin.js b/src/components/_sila/Mixins/TableSortMixin.js new file mode 100644 index 00000000..c0997350 --- /dev/null +++ b/src/components/_sila/Mixins/TableSortMixin.js @@ -0,0 +1,11 @@ +const STATUS = ['OK', 'Warning', 'Critical']; + +const TableSortMixin = { + methods: { + sortStatus(a, b, key) { + return STATUS.indexOf(a[key]) - STATUS.indexOf(b[key]); + }, + }, +}; + +export default TableSortMixin; diff --git a/src/components/_sila/Mixins/VuelidateMixin.js b/src/components/_sila/Mixins/VuelidateMixin.js new file mode 100644 index 00000000..fec85251 --- /dev/null +++ b/src/components/_sila/Mixins/VuelidateMixin.js @@ -0,0 +1,10 @@ +const VuelidateMixin = { + methods: { + getValidationState(model) { + const { $dirty, $error } = model; + return $dirty ? !$error : null; + }, + }, +}; + +export default VuelidateMixin; -- cgit v1.2.3