Merge pull request #125 from ONLYOFFICE/hotfix/filter-input-hotfix
Hotfix/filter input hotfix
This commit is contained in:
commit
d6c58eb49c
@ -16,10 +16,12 @@ import find from "lodash/find";
|
||||
import result from "lodash/result";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { withRouter } from "react-router";
|
||||
import { constants, FilterInput, store, Loaders } from "asc-web-common";
|
||||
import { constants, FilterInput, store, Loaders, utils } from "asc-web-common";
|
||||
import isEqual from "lodash/isEqual";
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
|
||||
const { withLayoutSize } = utils;
|
||||
|
||||
const {
|
||||
getCurrentUser,
|
||||
getSettingsCustomNames,
|
||||
@ -287,20 +289,22 @@ class SectionFilterContent extends React.Component {
|
||||
this.props.selectedFolderId !== nextProps.selectedFolderId ||
|
||||
this.state.isReady !== nextState.isReady ||
|
||||
this.props.viewAs !== nextProps.viewAs ||
|
||||
this.props.firstLoad !== nextProps.firstLoad
|
||||
this.props.firstLoad !== nextProps.firstLoad ||
|
||||
this.props.sectionWidth !== nextProps.sectionWidth
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log("Filter render");
|
||||
const selectedFilterData = this.getSelectedFilterData();
|
||||
const { t, language, firstLoad } = this.props;
|
||||
const { t, language, firstLoad, sectionWidth } = this.props;
|
||||
const filterColumnCount =
|
||||
window.innerWidth < 500 ? {} : { filterColumnCount: 3 };
|
||||
return firstLoad ? (
|
||||
<Loaders.Filter />
|
||||
) : (
|
||||
<FilterInput
|
||||
sectionWidth={sectionWidth}
|
||||
getFilterData={this.getData}
|
||||
getSortData={this.getSortData}
|
||||
selectedFilterData={selectedFilterData}
|
||||
@ -338,4 +342,4 @@ export default connect(mapStateToProps, {
|
||||
fetchFiles,
|
||||
setViewAs,
|
||||
setIsLoading,
|
||||
})(withRouter(withTranslation()(SectionFilterContent)));
|
||||
})(withRouter(withLayoutSize(withTranslation()(SectionFilterContent))));
|
||||
|
@ -6,7 +6,7 @@ import result from "lodash/result";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { withRouter } from "react-router";
|
||||
import { getFilterByLocation } from "../../../../../helpers/converters";
|
||||
import { store, FilterInput, Loaders } from "asc-web-common";
|
||||
import { store, FilterInput, Loaders, utils } from "asc-web-common";
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
import { getFilter, getGroups } from "../../../../../store/people/selectors";
|
||||
const {
|
||||
@ -17,6 +17,8 @@ const {
|
||||
getIsLoaded,
|
||||
} = store.auth.selectors;
|
||||
|
||||
const { withLayoutSize } = utils;
|
||||
|
||||
const getEmployeeStatus = (filterValues) => {
|
||||
const employeeStatus = result(
|
||||
find(filterValues, (value) => {
|
||||
@ -248,9 +250,10 @@ class SectionFilterContent extends React.Component {
|
||||
|
||||
render() {
|
||||
const selectedFilterData = this.getSelectedFilterData();
|
||||
const { t, language, isLoaded } = this.props;
|
||||
const { t, language, isLoaded, sectionWidth } = this.props;
|
||||
return isLoaded ? (
|
||||
<FilterInput
|
||||
sectionWidth={sectionWidth}
|
||||
getFilterData={this.getData}
|
||||
getSortData={this.getSortData}
|
||||
selectedFilterData={selectedFilterData}
|
||||
@ -282,5 +285,5 @@ function mapStateToProps(state) {
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, { fetchPeople })(
|
||||
withRouter(withTranslation()(SectionFilterContent))
|
||||
withRouter(withLayoutSize(withTranslation()(SectionFilterContent)))
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "asc-web-common",
|
||||
"version": "1.0.279",
|
||||
"version": "1.0.275",
|
||||
"description": "Ascensio System SIA common components and solutions library",
|
||||
"license": "AGPL-3.0",
|
||||
"files": [
|
||||
|
@ -2,7 +2,6 @@ import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import { SearchInput } from "asc-web-components";
|
||||
import isEqual from "lodash/isEqual";
|
||||
import throttle from "lodash/throttle";
|
||||
import FilterBlock from "./sub-components/FilterBlock";
|
||||
import SortComboBox from "./sub-components/SortComboBox";
|
||||
import ViewSelector from "./sub-components/ViewSelector";
|
||||
@ -81,203 +80,122 @@ const convertToInternalData = function (fullDataArray, inputDataArray) {
|
||||
return filterItems;
|
||||
};
|
||||
|
||||
const minWidth = 170;
|
||||
const filterItemPadding = 60;
|
||||
const maxFilterItemWidth = 260;
|
||||
const itemsContainerWidth = 40;
|
||||
const sectionPaddings = 48;
|
||||
|
||||
class FilterInput extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.isResizeUpdate = false;
|
||||
this.minWidth = 190;
|
||||
const { selectedFilterData, getSortData, value } = props;
|
||||
const { sortDirection, sortId, inputValue } = selectedFilterData;
|
||||
const sortData = getSortData();
|
||||
|
||||
function getDefaultFilterData() {
|
||||
const filterData = props.getFilterData();
|
||||
const filterItems = [];
|
||||
const selectedFilterData = cloneObjectsArray(
|
||||
props.selectedFilterData.filterValues
|
||||
);
|
||||
selectedFilterData.forEach((defaultFilterValue) => {
|
||||
const filterValue = filterData.find(
|
||||
(x) =>
|
||||
x.key ===
|
||||
defaultFilterValue.key.replace(
|
||||
defaultFilterValue.group + "_",
|
||||
""
|
||||
) && x.group === defaultFilterValue.group
|
||||
);
|
||||
let groupLabel = "";
|
||||
|
||||
const groupFilterItem = filterData.find(
|
||||
(x) => x.key === defaultFilterValue.group
|
||||
);
|
||||
if (groupFilterItem != undefined) {
|
||||
groupLabel = groupFilterItem.label;
|
||||
} else {
|
||||
const subgroupFilterItem = filterData.find(
|
||||
(x) => x.subgroup === defaultFilterValue.group
|
||||
);
|
||||
if (subgroupFilterItem != undefined) {
|
||||
groupLabel = subgroupFilterItem.label;
|
||||
}
|
||||
}
|
||||
|
||||
if (filterValue != undefined) {
|
||||
defaultFilterValue.key =
|
||||
defaultFilterValue.group + "_" + defaultFilterValue.key;
|
||||
defaultFilterValue.label = filterValue.label;
|
||||
defaultFilterValue.groupLabel = groupLabel;
|
||||
filterItems.push(defaultFilterValue);
|
||||
}
|
||||
});
|
||||
return filterItems;
|
||||
}
|
||||
|
||||
let filterValues = props.selectedFilterData ? getDefaultFilterData() : [];
|
||||
filterValues = [
|
||||
...filterValues,
|
||||
...this.convertSelectorToInternalData(
|
||||
props.getFilterData(),
|
||||
cloneObjectsArray(props.selectedFilterData.filterValues)
|
||||
),
|
||||
];
|
||||
const filterValues = selectedFilterData ? this.getDefaultFilterData() : [];
|
||||
|
||||
this.state = {
|
||||
sortDirection:
|
||||
props.selectedFilterData.sortDirection === "desc" ? true : false,
|
||||
sortDirection: sortDirection === "desc" ? true : false,
|
||||
sortId:
|
||||
props
|
||||
.getSortData()
|
||||
.findIndex((x) => x.key === props.selectedFilterData.sortId) != -1
|
||||
? props.selectedFilterData.sortId
|
||||
: props.getSortData().length > 0
|
||||
? props.getSortData()[0].key
|
||||
sortData.findIndex((x) => x.key === sortId) != -1
|
||||
? sortId
|
||||
: sortData.length > 0
|
||||
? sortData[0].key
|
||||
: "",
|
||||
searchText: props.selectedFilterData.inputValue || props.value,
|
||||
searchText: inputValue || value,
|
||||
|
||||
filterValues,
|
||||
openFilterItems: [],
|
||||
hideFilterItems: [],
|
||||
hiddenFilterItems: [],
|
||||
needUpdateFilter: false,
|
||||
};
|
||||
|
||||
this.searchWrapper = React.createRef();
|
||||
this.filterWrapper = React.createRef();
|
||||
|
||||
this.onClickSortItem = this.onClickSortItem.bind(this);
|
||||
this.onSortDirectionClick = this.onSortDirectionClick.bind(this);
|
||||
this.onChangeSortDirection = this.onChangeSortDirection.bind(this);
|
||||
this.onSearch = this.onSearch.bind(this);
|
||||
this.onChangeFilter = this.onChangeFilter.bind(this);
|
||||
|
||||
this.onSearchChanged = this.onSearchChanged.bind(this);
|
||||
|
||||
this.getDefaultSelectedIndex = this.getDefaultSelectedIndex.bind(this);
|
||||
|
||||
this.updateFilter = this.updateFilter.bind(this);
|
||||
this.onClickFilterItem = this.onClickFilterItem.bind(this);
|
||||
this.getFilterData = this.getFilterData.bind(this);
|
||||
this.onFilterRender = this.onFilterRender.bind(this);
|
||||
this.onDeleteFilterItem = this.onDeleteFilterItem.bind(this);
|
||||
this.clearFilter = this.clearFilter.bind(this);
|
||||
|
||||
this.onClickViewSelector = this.onClickViewSelector.bind(this);
|
||||
|
||||
this.throttledResize = throttle(this.resize, 300);
|
||||
this.rectComboBoxRef = React.createRef();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
window.addEventListener("resize", this.throttledResize);
|
||||
if (this.state.filterValues.length > 0) this.updateFilter();
|
||||
}
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener("resize", this.throttledResize);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
const { selectedFilterData, sectionWidth, getSortData } = this.props;
|
||||
const { filterValues, searchText } = this.state;
|
||||
const { sortDirection, sortId, inputValue } = selectedFilterData;
|
||||
|
||||
if (
|
||||
this.props.needForUpdate &&
|
||||
this.props.needForUpdate(prevProps, this.props)
|
||||
) {
|
||||
let internalFilterData = convertToInternalData(
|
||||
this.props.getFilterData(),
|
||||
cloneObjectsArray(this.props.selectedFilterData.filterValues)
|
||||
cloneObjectsArray(selectedFilterData.filterValues)
|
||||
);
|
||||
this.updateFilter(internalFilterData);
|
||||
}
|
||||
|
||||
if (sectionWidth !== prevProps.sectionWidth) {
|
||||
this.updateFilter();
|
||||
}
|
||||
|
||||
if (
|
||||
(!isEqual(selectedFilterData.filterValues, filterValues) ||
|
||||
inputValue !== searchText) &&
|
||||
sectionWidth !== prevProps.sectionWidth
|
||||
) {
|
||||
const sortData = getSortData();
|
||||
const filterValues = this.getDefaultFilterData();
|
||||
this.setState({
|
||||
sortDirection: sortDirection === "desc" ? true : false,
|
||||
sortId:
|
||||
sortData.findIndex((x) => x.key === sortId) != -1
|
||||
? sortId
|
||||
: sortData.length > 0
|
||||
? sortData[0].key
|
||||
: "",
|
||||
filterValues: filterValues,
|
||||
searchText: selectedFilterData.inputValue || "",
|
||||
});
|
||||
this.updateFilter(filterValues);
|
||||
}
|
||||
|
||||
if (
|
||||
!isEqual(
|
||||
prevProps.selectedFilterData.filterValues,
|
||||
selectedFilterData.filterValues
|
||||
) &&
|
||||
selectedFilterData.filterValues &&
|
||||
(selectedFilterData.filterValues.length === 0 ||
|
||||
(selectedFilterData.filterValues.length === 1 &&
|
||||
selectedFilterData.filterValues[0].key === "null")) &&
|
||||
!selectedFilterData.inputValue
|
||||
) {
|
||||
this.clearFilter();
|
||||
}
|
||||
}
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
const {
|
||||
selectedFilterData,
|
||||
getFilterData,
|
||||
getSortData,
|
||||
value,
|
||||
id,
|
||||
isDisabled,
|
||||
size,
|
||||
placeholder,
|
||||
sectionWidth,
|
||||
} = this.props;
|
||||
if (!isEqual(selectedFilterData, nextProps.selectedFilterData)) {
|
||||
let internalFilterData = cloneObjectsArray(this.state.filterValues);
|
||||
if (nextProps.selectedFilterData.filterValues) {
|
||||
internalFilterData = convertToInternalData(
|
||||
getFilterData(),
|
||||
cloneObjectsArray(nextProps.selectedFilterData.filterValues)
|
||||
);
|
||||
let internalFilterDataSelectors = this.convertSelectorToInternalData(
|
||||
getFilterData(),
|
||||
cloneObjectsArray(nextProps.selectedFilterData.filterValues)
|
||||
);
|
||||
internalFilterData = internalFilterData.concat(
|
||||
internalFilterDataSelectors
|
||||
);
|
||||
this.updateFilter(internalFilterData);
|
||||
}
|
||||
this.setState({
|
||||
sortDirection:
|
||||
nextProps.selectedFilterData.sortDirection === "desc" ? true : false,
|
||||
sortId:
|
||||
getSortData().findIndex(
|
||||
(x) => x.key === nextProps.selectedFilterData.sortId
|
||||
) != -1
|
||||
? nextProps.selectedFilterData.sortId
|
||||
: "",
|
||||
filterValues: internalFilterData,
|
||||
searchText: nextProps.selectedFilterData.inputValue || value,
|
||||
});
|
||||
|
||||
if (
|
||||
!isEqual(selectedFilterData, nextProps.selectedFilterData) ||
|
||||
this.props.viewAs !== nextProps.viewAs ||
|
||||
this.props.widthProp !== nextProps.widthProp ||
|
||||
sectionWidth !== nextProps.sectionWidth
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.props.viewAs !== nextProps.viewAs) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.props.isReady !== nextProps.isReady) {
|
||||
let internalFilterData = cloneObjectsArray(this.state.filterValues);
|
||||
internalFilterData = convertToInternalData(
|
||||
getFilterData(),
|
||||
cloneObjectsArray(nextProps.selectedFilterData.filterValues)
|
||||
);
|
||||
|
||||
let internalFilterDataSelectors = this.convertSelectorToInternalData(
|
||||
getFilterData(),
|
||||
cloneObjectsArray(nextProps.selectedFilterData.filterValues)
|
||||
);
|
||||
internalFilterData = internalFilterData.concat(
|
||||
internalFilterDataSelectors
|
||||
);
|
||||
this.updateFilter(internalFilterData);
|
||||
|
||||
this.setState({
|
||||
sortDirection:
|
||||
nextProps.selectedFilterData.sortDirection === "desc" ? true : false,
|
||||
sortId:
|
||||
getSortData().findIndex(
|
||||
(x) => x.key === nextProps.selectedFilterData.sortId
|
||||
) != -1
|
||||
? nextProps.selectedFilterData.sortId
|
||||
: "",
|
||||
filterValues: internalFilterData,
|
||||
searchText: nextProps.selectedFilterData.inputValue || value,
|
||||
});
|
||||
// return true;
|
||||
}
|
||||
|
||||
if (
|
||||
id != nextProps.id ||
|
||||
isDisabled != nextProps.isDisabled ||
|
||||
@ -286,96 +204,41 @@ class FilterInput extends React.Component {
|
||||
value != nextProps.value
|
||||
)
|
||||
return true;
|
||||
if (this.isResizeUpdate) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !isEqual(this.state, nextState);
|
||||
}
|
||||
|
||||
convertSelectorToInternalData = (filterData, filterValues) => {
|
||||
const resultValues = [];
|
||||
filterValues.forEach((item) => {
|
||||
const isSelector = item.group.includes("filter-author");
|
||||
if (isSelector) {
|
||||
const typeSelector = item.key.includes("user")
|
||||
? "user"
|
||||
: item.key.includes("group")
|
||||
? "group"
|
||||
: null;
|
||||
const hasUnderscore = item.key.indexOf("_") !== -1;
|
||||
const key = hasUnderscore
|
||||
? item.key.slice(0, item.key.indexOf("_"))
|
||||
: item.key;
|
||||
const finded = filterData.find(
|
||||
(x) => x.key === key && x.group === item.group
|
||||
);
|
||||
if (!finded) return;
|
||||
const convertedItem = {
|
||||
key: item.group + "_" + item.key,
|
||||
label: finded.label,
|
||||
group: item.group,
|
||||
groupLabel: finded.label,
|
||||
typeSelector,
|
||||
groupsCaption: finded.groupsCaption,
|
||||
defaultOptionLabel: finded.defaultOptionLabel,
|
||||
defaultOption: finded.defaultOption,
|
||||
defaultSelectLabel: finded.defaultSelectLabel,
|
||||
selectedItem: finded.selectedItem,
|
||||
};
|
||||
resultValues.push(convertedItem);
|
||||
}
|
||||
});
|
||||
return resultValues;
|
||||
};
|
||||
|
||||
resize = () => {
|
||||
this.isResizeUpdate = true;
|
||||
this.setState({
|
||||
filterValues: this.state.filterValues,
|
||||
openFilterItems: this.state.filterValues,
|
||||
hideFilterItems: [],
|
||||
});
|
||||
};
|
||||
onChangeSortDirection(key) {
|
||||
onChangeSortDirection = (key) => {
|
||||
this.onFilter(
|
||||
this.state.filterValues,
|
||||
this.state.sortId,
|
||||
key ? "desc" : "asc"
|
||||
);
|
||||
this.setState({ sortDirection: !!key });
|
||||
}
|
||||
onClickViewSelector(item) {
|
||||
};
|
||||
onClickViewSelector = (item) => {
|
||||
const itemId = (item.target && item.target.dataset.for) || item;
|
||||
const viewAs = itemId.indexOf("row") === -1 ? "tile" : "row";
|
||||
this.props.onChangeViewAs(viewAs);
|
||||
}
|
||||
getDefaultSelectedIndex() {
|
||||
const sortData = this.props.getSortData();
|
||||
if (sortData.length > 0) {
|
||||
const defaultIndex = sortData.findIndex(
|
||||
(x) => x.key === this.state.sortId
|
||||
);
|
||||
return defaultIndex != -1 ? defaultIndex : 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
onClickSortItem(key) {
|
||||
};
|
||||
|
||||
onClickSortItem = (key) => {
|
||||
this.setState({ sortId: key });
|
||||
this.onFilter(
|
||||
this.state.filterValues,
|
||||
key,
|
||||
this.state.sortDirection ? "desc" : "asc"
|
||||
);
|
||||
}
|
||||
onSortDirectionClick() {
|
||||
};
|
||||
onSortDirectionClick = () => {
|
||||
this.onFilter(
|
||||
this.state.filterValues,
|
||||
this.state.sortId,
|
||||
!this.state.sortDirection ? "desc" : "asc"
|
||||
);
|
||||
this.setState({ sortDirection: !this.state.sortDirection });
|
||||
}
|
||||
onSearchChanged(value) {
|
||||
};
|
||||
onSearchChanged = (value) => {
|
||||
this.setState({ searchText: value });
|
||||
this.onFilter(
|
||||
this.state.filterValues,
|
||||
@ -383,23 +246,93 @@ class FilterInput extends React.Component {
|
||||
this.state.sortDirection ? "desc" : "asc",
|
||||
value
|
||||
);
|
||||
}
|
||||
onSearch(result) {
|
||||
};
|
||||
onSearch = (result) => {
|
||||
this.onFilter(
|
||||
result.filterValues,
|
||||
this.state.sortId,
|
||||
this.state.sortDirection ? "desc" : "asc"
|
||||
);
|
||||
};
|
||||
getDefaultFilterData = () => {
|
||||
const { getFilterData, selectedFilterData } = this.props;
|
||||
const filterData = getFilterData();
|
||||
const filterItems = [];
|
||||
const filterValues = cloneObjectsArray(selectedFilterData.filterValues);
|
||||
|
||||
for (let item of filterValues) {
|
||||
const filterValue = filterData.find(
|
||||
(x) => x.key === item.key && x.group === item.group
|
||||
);
|
||||
|
||||
if (!filterValue) {
|
||||
const isSelector = item.group.includes("filter-author");
|
||||
|
||||
if (isSelector) {
|
||||
const typeSelector = item.key.includes("user")
|
||||
? "user"
|
||||
: item.key.includes("group")
|
||||
? "group"
|
||||
: null;
|
||||
const underlined = item.key.indexOf("_") !== -1;
|
||||
const key = underlined
|
||||
? item.key.slice(0, item.key.indexOf("_"))
|
||||
: item.key;
|
||||
const filesFilterValue = filterData.find(
|
||||
(x) => x.key === key && x.group === item.group
|
||||
);
|
||||
|
||||
if (filesFilterValue) {
|
||||
const convertedItem = {
|
||||
key: item.group + "_" + item.key,
|
||||
label: filesFilterValue.label,
|
||||
group: item.group,
|
||||
groupLabel: filesFilterValue.label,
|
||||
typeSelector,
|
||||
groupsCaption: filesFilterValue.groupsCaption,
|
||||
defaultOptionLabel: filesFilterValue.defaultOptionLabel,
|
||||
defaultOption: filesFilterValue.defaultOption,
|
||||
defaultSelectLabel: filesFilterValue.defaultSelectLabel,
|
||||
selectedItem: filesFilterValue.selectedItem,
|
||||
};
|
||||
filterItems.push(convertedItem);
|
||||
}
|
||||
getFilterData() {
|
||||
const _this = this;
|
||||
}
|
||||
}
|
||||
|
||||
let groupLabel = "";
|
||||
const groupFilterItem = filterData.find((x) => x.key === item.group);
|
||||
if (groupFilterItem) {
|
||||
groupLabel = groupFilterItem.label;
|
||||
} else {
|
||||
const subgroupFilterItem = filterData.find(
|
||||
(x) => x.subgroup === item.group
|
||||
);
|
||||
if (subgroupFilterItem) {
|
||||
groupLabel = subgroupFilterItem.label;
|
||||
}
|
||||
}
|
||||
|
||||
if (filterValue) {
|
||||
item.key = item.group + "_" + item.key;
|
||||
item.label = filterValue.selectedItem
|
||||
? filterValue.selectedItem.label
|
||||
: filterValue.label;
|
||||
item.groupLabel = groupLabel;
|
||||
filterItems.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
return filterItems;
|
||||
};
|
||||
getFilterData = () => {
|
||||
const d = this.props.getFilterData();
|
||||
const result = [];
|
||||
d.forEach((element) => {
|
||||
if (!element.inSubgroup) {
|
||||
element.onClick =
|
||||
!element.isSeparator && !element.isHeader && !element.disabled
|
||||
? (e) => _this.props.onClickFilterItem(e, element)
|
||||
? () => this.onClickFilterItem(element)
|
||||
: undefined;
|
||||
element.key =
|
||||
element.group != element.key
|
||||
@ -413,13 +346,13 @@ class FilterInput extends React.Component {
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
clearFilter() {
|
||||
};
|
||||
clearFilter = () => {
|
||||
this.setState({
|
||||
searchText: "",
|
||||
filterValues: [],
|
||||
openFilterItems: [],
|
||||
hideFilterItems: [],
|
||||
hiddenFilterItems: [],
|
||||
});
|
||||
this.onFilter(
|
||||
[],
|
||||
@ -427,77 +360,135 @@ class FilterInput extends React.Component {
|
||||
this.state.sortDirection ? "desc" : "asc",
|
||||
""
|
||||
);
|
||||
};
|
||||
|
||||
getTextWidth = (text, font) => {
|
||||
var canvas =
|
||||
this.getTextWidth.canvas ||
|
||||
(this.getTextWidth.canvas = document.createElement("canvas"));
|
||||
var context = canvas.getContext("2d");
|
||||
context.font = font;
|
||||
var metrics = context.measureText(text);
|
||||
return metrics.width;
|
||||
};
|
||||
|
||||
calcHiddenItemWidth = (item) => {
|
||||
if (!item) return;
|
||||
let label = this.getItemLabel(item);
|
||||
|
||||
const itemWidth =
|
||||
this.getTextWidth(
|
||||
item.groupLabel + " " + label,
|
||||
"bolder 13px sans-serif"
|
||||
) + filterItemPadding;
|
||||
return itemWidth;
|
||||
};
|
||||
|
||||
addItems = (searchWidth) => {
|
||||
const { hiddenFilterItems } = this.state;
|
||||
if (hiddenFilterItems.length === 0) return 0;
|
||||
|
||||
let newSearchWidth = searchWidth;
|
||||
let numberOfHiddenItems = hiddenFilterItems.length;
|
||||
|
||||
for (let i = 0; i < hiddenFilterItems.length; i++) {
|
||||
let hiddenItemWidth = this.calcHiddenItemWidth(hiddenFilterItems[i]);
|
||||
|
||||
if (hiddenItemWidth > maxFilterItemWidth)
|
||||
hiddenItemWidth = maxFilterItemWidth;
|
||||
newSearchWidth = newSearchWidth - hiddenItemWidth;
|
||||
if (newSearchWidth >= minWidth) {
|
||||
numberOfHiddenItems--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
updateFilter(inputFilterItems) {
|
||||
const currentFilterItems =
|
||||
inputFilterItems || cloneObjectsArray(this.state.filterValues);
|
||||
}
|
||||
|
||||
return numberOfHiddenItems;
|
||||
};
|
||||
|
||||
hideItems = (searchWidth, currentFilterItems) => {
|
||||
const { hiddenFilterItems } = this.state;
|
||||
let newSearchWidth = searchWidth;
|
||||
let numberOfHiddenItems = hiddenFilterItems.length;
|
||||
|
||||
for (let i = currentFilterItems.length - 1; i >= 0; i--) {
|
||||
if (currentFilterItems[i].id === "styled-hide-filter") continue;
|
||||
const filterItemWidth = currentFilterItems[i].getBoundingClientRect()
|
||||
.width;
|
||||
newSearchWidth = newSearchWidth + filterItemWidth;
|
||||
numberOfHiddenItems++;
|
||||
if (numberOfHiddenItems === 1) newSearchWidth - itemsContainerWidth; // subtract the width of hidden block
|
||||
|
||||
if (newSearchWidth > minWidth) break;
|
||||
}
|
||||
|
||||
return numberOfHiddenItems;
|
||||
};
|
||||
|
||||
calcHiddenItems = (searchWidth, currentFilterItems) => {
|
||||
const { hiddenFilterItems } = this.state;
|
||||
|
||||
if (!searchWidth || currentFilterItems.length === 0)
|
||||
return hiddenFilterItems.length;
|
||||
const numberOfHiddenItems =
|
||||
searchWidth < minWidth
|
||||
? this.hideItems(searchWidth, currentFilterItems)
|
||||
: this.addItems(searchWidth);
|
||||
|
||||
return numberOfHiddenItems;
|
||||
};
|
||||
|
||||
updateFilter = (inputFilterItems) => {
|
||||
const { sectionWidth } = this.props;
|
||||
const currentFilterItems = inputFilterItems
|
||||
? cloneObjectsArray(inputFilterItems)
|
||||
: cloneObjectsArray(this.state.filterValues);
|
||||
const fullWidth = this.searchWrapper.current.getBoundingClientRect().width;
|
||||
const filterWidth = this.filterWrapper.current.getBoundingClientRect()
|
||||
.width;
|
||||
const comboBoxWidth = this.rectComboBoxRef.current.getBoundingClientRect()
|
||||
.width;
|
||||
|
||||
const searchWidth = sectionWidth
|
||||
? sectionWidth - filterWidth - comboBoxWidth - sectionPaddings
|
||||
: fullWidth - filterWidth;
|
||||
|
||||
const filterArr = Array.from(
|
||||
Array.from(this.filterWrapper.current.children).find(
|
||||
(x) => x.id === "filter-items-container"
|
||||
).children
|
||||
);
|
||||
const searchFilterButton = Array.from(
|
||||
this.filterWrapper.current.children
|
||||
).find((x) => x.id != "filter-items-container");
|
||||
|
||||
const filterButton = searchFilterButton
|
||||
? Array.from(searchFilterButton.children)[0]
|
||||
: null;
|
||||
|
||||
if (fullWidth <= this.minWidth && fullWidth > 0) {
|
||||
const numberOfHiddenItems = this.calcHiddenItems(searchWidth, filterArr);
|
||||
if (searchWidth !== 0 && currentFilterItems.length > 0) {
|
||||
this.setState({
|
||||
openFilterItems: [],
|
||||
hideFilterItems: cloneObjectsArray(currentFilterItems),
|
||||
openFilterItems: numberOfHiddenItems
|
||||
? currentFilterItems.slice(
|
||||
0,
|
||||
currentFilterItems.length - numberOfHiddenItems
|
||||
)
|
||||
: currentFilterItems.slice(),
|
||||
hiddenFilterItems: numberOfHiddenItems
|
||||
? currentFilterItems.slice(-numberOfHiddenItems)
|
||||
: [],
|
||||
});
|
||||
} else if (filterWidth > fullWidth / 2) {
|
||||
let newOpenFilterItems = cloneObjectsArray(currentFilterItems);
|
||||
let newHideFilterItems = [];
|
||||
}
|
||||
};
|
||||
|
||||
let elementsWidth = 0;
|
||||
Array.from(filterArr).forEach((element) => {
|
||||
elementsWidth = elementsWidth + element.getBoundingClientRect().width;
|
||||
});
|
||||
getItemLabel = (item) => {
|
||||
let label = "";
|
||||
|
||||
if (
|
||||
filterButton !== null &&
|
||||
elementsWidth >=
|
||||
fullWidth / 3 - filterButton.getBoundingClientRect().width
|
||||
) {
|
||||
for (let i = 0; i < filterArr.length; i++) {
|
||||
if (
|
||||
elementsWidth >
|
||||
fullWidth / 3 - filterButton.getBoundingClientRect().width
|
||||
) {
|
||||
elementsWidth =
|
||||
elementsWidth - filterArr[i].getBoundingClientRect().width;
|
||||
const hiddenItem = currentFilterItems.find(
|
||||
(x) => x.key === filterArr[i].getAttribute("id")
|
||||
);
|
||||
if (hiddenItem) newHideFilterItems.push(hiddenItem);
|
||||
newOpenFilterItems.splice(
|
||||
newOpenFilterItems.findIndex(
|
||||
(x) => x.key === filterArr[i].getAttribute("id")
|
||||
),
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.setState({
|
||||
openFilterItems: newOpenFilterItems,
|
||||
hideFilterItems: newHideFilterItems,
|
||||
});
|
||||
if (item.selectedItem) {
|
||||
label = item.selectedItem.label
|
||||
? item.selectedItem.label
|
||||
: item.defaultSelectLabel;
|
||||
} else {
|
||||
this.setState({
|
||||
openFilterItems: currentFilterItems.slice(),
|
||||
hideFilterItems: [],
|
||||
});
|
||||
label = item.label;
|
||||
}
|
||||
}
|
||||
onDeleteFilterItem(key) {
|
||||
return label;
|
||||
};
|
||||
|
||||
onDeleteFilterItem = (key) => {
|
||||
const currentFilterItems = this.state.filterValues.slice();
|
||||
const indexFilterItem = currentFilterItems.findIndex((x) => x.key === key);
|
||||
if (indexFilterItem != -1) {
|
||||
@ -506,7 +497,7 @@ class FilterInput extends React.Component {
|
||||
this.setState({
|
||||
filterValues: currentFilterItems,
|
||||
openFilterItems: currentFilterItems,
|
||||
hideFilterItems: [],
|
||||
hiddenFilterItems: [],
|
||||
});
|
||||
let filterValues = cloneObjectsArray(currentFilterItems);
|
||||
filterValues = filterValues.map(function (item) {
|
||||
@ -518,8 +509,8 @@ class FilterInput extends React.Component {
|
||||
this.state.sortId,
|
||||
this.state.sortDirection ? "desc" : "asc"
|
||||
);
|
||||
}
|
||||
onFilter(filterValues, sortId, sortDirection, searchText) {
|
||||
};
|
||||
onFilter = (filterValues, sortId, sortDirection, searchText) => {
|
||||
let cloneFilterValues = cloneObjectsArray(filterValues);
|
||||
cloneFilterValues = cloneFilterValues.map(function (item) {
|
||||
item.key = item.key.replace(item.group + "_", "");
|
||||
@ -531,8 +522,8 @@ class FilterInput extends React.Component {
|
||||
sortId: sortId,
|
||||
sortDirection: sortDirection,
|
||||
});
|
||||
}
|
||||
onChangeFilter(result) {
|
||||
};
|
||||
onChangeFilter = (result) => {
|
||||
this.setState({
|
||||
searchText: result.inputValue,
|
||||
filterValues: result.filterValues,
|
||||
@ -543,24 +534,21 @@ class FilterInput extends React.Component {
|
||||
this.state.sortDirection ? "desc" : "asc",
|
||||
result.inputValue
|
||||
);
|
||||
}
|
||||
onFilterRender() {
|
||||
if (this.isResizeUpdate) {
|
||||
this.isResizeUpdate = false;
|
||||
}
|
||||
};
|
||||
onFilterRender = () => {
|
||||
this.setState({
|
||||
needUpdateFilter: false,
|
||||
});
|
||||
|
||||
if (this.searchWrapper.current && this.filterWrapper.current) {
|
||||
const fullWidth = this.searchWrapper.current.getBoundingClientRect()
|
||||
.width;
|
||||
const filterWidth = this.filterWrapper.current.getBoundingClientRect()
|
||||
.width;
|
||||
if (fullWidth <= this.minWidth || filterWidth > fullWidth / 2)
|
||||
this.updateFilter();
|
||||
}
|
||||
}
|
||||
onClickFilterItem(event, filterItem) {
|
||||
};
|
||||
onClickFilterItem = (event, filterItem) => {
|
||||
const currentFilterItems = cloneObjectsArray(this.state.filterValues);
|
||||
|
||||
this.setState({
|
||||
needUpdateFilter: true,
|
||||
});
|
||||
|
||||
if (filterItem.isSelector) {
|
||||
const indexFilterItem = currentFilterItems.findIndex(
|
||||
(x) => x.group === filterItem.group
|
||||
@ -601,7 +589,7 @@ class FilterInput extends React.Component {
|
||||
this.setState({
|
||||
filterValues: currentFilterItems,
|
||||
openFilterItems: currentFilterItems,
|
||||
hideFilterItems: [],
|
||||
hiddenFilterItems: [],
|
||||
});
|
||||
|
||||
if (selectFilterItem.selectedItem.key) {
|
||||
@ -647,7 +635,7 @@ class FilterInput extends React.Component {
|
||||
this.setState({
|
||||
filterValues: currentFilterItems,
|
||||
openFilterItems: currentFilterItems,
|
||||
hideFilterItems: [],
|
||||
hiddenFilterItems: [],
|
||||
});
|
||||
} else if (subgroupItems.length === 1) {
|
||||
const selectFilterItem = {
|
||||
@ -678,7 +666,7 @@ class FilterInput extends React.Component {
|
||||
this.setState({
|
||||
filterValues: currentFilterItems,
|
||||
openFilterItems: currentFilterItems,
|
||||
hideFilterItems: [],
|
||||
hiddenFilterItems: [],
|
||||
});
|
||||
}
|
||||
} else {
|
||||
@ -705,7 +693,7 @@ class FilterInput extends React.Component {
|
||||
this.setState({
|
||||
filterValues: currentFilterItems,
|
||||
openFilterItems: currentFilterItems,
|
||||
hideFilterItems: [],
|
||||
hiddenFilterItems: [],
|
||||
});
|
||||
|
||||
const clone = cloneObjectsArray(
|
||||
@ -721,7 +709,7 @@ class FilterInput extends React.Component {
|
||||
this.state.sortDirection ? "desc" : "asc"
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
/* eslint-disable react/prop-types */
|
||||
@ -741,6 +729,7 @@ class FilterInput extends React.Component {
|
||||
viewAs,
|
||||
contextMenuHeader,
|
||||
isMobile,
|
||||
sectionWidth,
|
||||
} = this.props;
|
||||
/* eslint-enable react/prop-types */
|
||||
|
||||
@ -748,12 +737,13 @@ class FilterInput extends React.Component {
|
||||
searchText,
|
||||
filterValues,
|
||||
openFilterItems,
|
||||
hideFilterItems,
|
||||
hiddenFilterItems,
|
||||
sortId,
|
||||
sortDirection,
|
||||
} = this.state;
|
||||
|
||||
// console.log("filter input render, openFilterItems", openFilterItems, 'hideFilterItems', hideFilterItems);
|
||||
const smallSectionWidth = sectionWidth ? sectionWidth < 900 : false;
|
||||
|
||||
let iconSize = 30;
|
||||
switch (size) {
|
||||
case "base":
|
||||
@ -769,13 +759,14 @@ class FilterInput extends React.Component {
|
||||
}
|
||||
return (
|
||||
<StyledFilterInput
|
||||
smallSectionWidth={smallSectionWidth}
|
||||
isMobile={isMobile}
|
||||
viewAs={viewAs}
|
||||
className={className}
|
||||
id={id}
|
||||
style={style}
|
||||
>
|
||||
<div className="styled-search-input" ref={this.searchWrapper}>
|
||||
<div className="styled-search-input test" ref={this.searchWrapper}>
|
||||
<SearchInput
|
||||
id={id}
|
||||
isDisabled={isDisabled}
|
||||
@ -796,20 +787,20 @@ class FilterInput extends React.Component {
|
||||
<FilterBlock
|
||||
contextMenuHeader={contextMenuHeader}
|
||||
openFilterItems={openFilterItems}
|
||||
hideFilterItems={hideFilterItems}
|
||||
hiddenFilterItems={hiddenFilterItems}
|
||||
iconSize={iconSize}
|
||||
getFilterData={getFilterData}
|
||||
onClickFilterItem={this.onClickFilterItem}
|
||||
onDeleteFilterItem={this.onDeleteFilterItem}
|
||||
isResizeUpdate={this.isResizeUpdate}
|
||||
onRender={this.onFilterRender}
|
||||
onFilterRender={this.onFilterRender}
|
||||
isDisabled={isDisabled}
|
||||
columnCount={filterColumnCount}
|
||||
needUpdateFilter={this.state.needUpdateFilter}
|
||||
/>
|
||||
</div>
|
||||
</SearchInput>
|
||||
</div>
|
||||
|
||||
<div ref={this.rectComboBoxRef}>
|
||||
<SortComboBox
|
||||
options={getSortData()}
|
||||
isDisabled={isDisabled}
|
||||
@ -827,6 +818,7 @@ class FilterInput extends React.Component {
|
||||
directionAscLabel={directionAscLabel}
|
||||
directionDescLabel={directionDescLabel}
|
||||
/>
|
||||
</div>
|
||||
{viewAs && (
|
||||
<ViewSelector
|
||||
isDisabled={isDisabled}
|
||||
@ -853,6 +845,9 @@ FilterInput.protoTypes = {
|
||||
filterColumnCount: PropTypes.number,
|
||||
onChangeViewAs: PropTypes.func,
|
||||
contextMenuHeader: PropTypes.string,
|
||||
sectionWidth: PropTypes.number,
|
||||
getSortData: PropTypes.func,
|
||||
value: PropTypes.string,
|
||||
};
|
||||
|
||||
FilterInput.defaultProps = {
|
||||
|
@ -107,7 +107,7 @@ const StyledFilterInput = styled.div`
|
||||
margin-left: 8px;
|
||||
|
||||
${(props) =>
|
||||
props.isMobile &&
|
||||
(props.isMobile || props.smallSectionWidth) &&
|
||||
`
|
||||
width: 50px;
|
||||
.optionalBlock ~ div:first-child{
|
||||
|
@ -39,6 +39,7 @@ class FilterItem extends React.Component {
|
||||
isOpen: false,
|
||||
isOpenSelector: !isOpenSelector,
|
||||
selectedOption,
|
||||
needUpdate: false,
|
||||
};
|
||||
}
|
||||
|
||||
@ -48,7 +49,6 @@ class FilterItem extends React.Component {
|
||||
if (
|
||||
selectedItem &&
|
||||
selectedItem.key !== this.state.selectedOption.key &&
|
||||
selectedItem.key !== this.state.selectedOption.key &&
|
||||
selectedItem.key !== prevProps.selectedItem.key
|
||||
) {
|
||||
const selectedOption = selectedItem.key
|
||||
@ -67,6 +67,11 @@ class FilterItem extends React.Component {
|
||||
selectedOption,
|
||||
});
|
||||
}
|
||||
|
||||
if (this.state.needUpdate) {
|
||||
this.props.onFilterRender();
|
||||
this.setNeedUpdate(false);
|
||||
}
|
||||
}
|
||||
|
||||
onSelect = (option) => {
|
||||
@ -85,6 +90,12 @@ class FilterItem extends React.Component {
|
||||
|
||||
toggleCombobox = (e, isOpen) => this.setState({ isOpen });
|
||||
|
||||
setNeedUpdate = (needUpdate) => {
|
||||
this.setState({
|
||||
needUpdate,
|
||||
});
|
||||
};
|
||||
|
||||
onCancelSelector = (e) => {
|
||||
if (
|
||||
this.state.isOpenSelector &&
|
||||
@ -260,47 +271,64 @@ class FilterBlock extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
const { hideFilterItems, openFilterItems } = props;
|
||||
const { hiddenFilterItems, openFilterItems } = props;
|
||||
|
||||
this.state = {
|
||||
hideFilterItems: hideFilterItems || [],
|
||||
hiddenFilterItems: hiddenFilterItems || [],
|
||||
openFilterItems: openFilterItems || [],
|
||||
needUpdate: false,
|
||||
};
|
||||
|
||||
this.throttledRender = throttle(this.onRender, 100);
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.throttledRender();
|
||||
componentDidMount() {
|
||||
this.setNeedUpdate(true);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
const { needUpdate } = this.state;
|
||||
const { needUpdateFilter } = this.props;
|
||||
if (
|
||||
(needUpdate || needUpdateFilter) &&
|
||||
(!isEqual(prevState.openFilterItems, this.state.openFilterItems) ||
|
||||
!isEqual(prevState.hiddenFilterItems, this.state.hiddenFilterItems))
|
||||
) {
|
||||
this.props.onFilterRender();
|
||||
this.setNeedUpdate(false);
|
||||
}
|
||||
}
|
||||
|
||||
shouldComponentUpdate(nextProps, nextState) {
|
||||
const { hideFilterItems, openFilterItems } = nextProps;
|
||||
const { hiddenFilterItems, openFilterItems } = nextProps;
|
||||
|
||||
if (!isEqual(this.props, nextProps)) {
|
||||
if (
|
||||
!isEqual(this.props.hideFilterItems, hideFilterItems) ||
|
||||
!isEqual(this.props.hiddenFilterItems, hiddenFilterItems) ||
|
||||
!isEqual(this.props.openFilterItems, openFilterItems)
|
||||
) {
|
||||
this.setState({
|
||||
hideFilterItems,
|
||||
hiddenFilterItems,
|
||||
openFilterItems,
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (this.props.isResizeUpdate) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !isEqual(this.state, nextState);
|
||||
}
|
||||
|
||||
onDeleteFilterItem = (key) => {
|
||||
this.props.onDeleteFilterItem(key);
|
||||
this.setNeedUpdate(true);
|
||||
};
|
||||
|
||||
setNeedUpdate = (needUpdate) => {
|
||||
this.setState({
|
||||
needUpdate,
|
||||
});
|
||||
};
|
||||
getFilterItems = () => {
|
||||
const { openFilterItems, hideFilterItems } = this.state;
|
||||
const { openFilterItems, hiddenFilterItems } = this.state;
|
||||
const _this = this;
|
||||
let result = [];
|
||||
let openItems = [];
|
||||
@ -339,13 +367,14 @@ class FilterBlock extends React.Component {
|
||||
defaultOption={defaultOption}
|
||||
defaultSelectLabel={defaultSelectLabel}
|
||||
selectedItem={selectedItem}
|
||||
onFilterRender={_this.props.onFilterRender}
|
||||
></FilterItem>
|
||||
);
|
||||
});
|
||||
}
|
||||
if (hideFilterItems.length > 0) {
|
||||
if (hiddenFilterItems.length > 0) {
|
||||
let open = false;
|
||||
let hideFilterItemsList = hideFilterItems.map(function (item) {
|
||||
let hideFilterItemsList = hiddenFilterItems.map(function (item) {
|
||||
const {
|
||||
key,
|
||||
group,
|
||||
@ -379,13 +408,14 @@ class FilterBlock extends React.Component {
|
||||
defaultOption={defaultOption}
|
||||
defaultSelectLabel={defaultSelectLabel}
|
||||
selectedItem={selectedItem}
|
||||
onFilterRender={_this.props.onFilterRender}
|
||||
></FilterItem>
|
||||
);
|
||||
});
|
||||
hideItems.push(
|
||||
<HideFilter
|
||||
key="hide-filter"
|
||||
count={hideFilterItems.length}
|
||||
count={hiddenFilterItems.length}
|
||||
isDisabled={this.props.isDisabled}
|
||||
open={open}
|
||||
>
|
||||
@ -420,9 +450,6 @@ class FilterBlock extends React.Component {
|
||||
return result;
|
||||
};
|
||||
|
||||
onRender = () => {
|
||||
this.props.onRender();
|
||||
};
|
||||
render() {
|
||||
const _this = this;
|
||||
const filterItems = this.getFilterItems();
|
||||
@ -453,10 +480,9 @@ class FilterBlock extends React.Component {
|
||||
}
|
||||
FilterBlock.propTypes = {
|
||||
getFilterData: PropTypes.func,
|
||||
hideFilterItems: PropTypes.array,
|
||||
hiddenFilterItems: PropTypes.array,
|
||||
iconSize: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
||||
isDisabled: PropTypes.bool,
|
||||
isResizeUpdate: PropTypes.bool,
|
||||
onDeleteFilterItem: PropTypes.func,
|
||||
onRender: PropTypes.func,
|
||||
openFilterItems: PropTypes.array,
|
||||
|
@ -39,6 +39,7 @@ class HideFilter extends React.Component {
|
||||
className="styled-hide-filter"
|
||||
onClick={this.onClick.bind(this, !popoverOpen)}
|
||||
ref={this.ref}
|
||||
id="styled-hide-filter"
|
||||
>
|
||||
<StyledHideFilterButton id="PopoverLegacy" isDisabled={isDisabled}>
|
||||
{count}
|
||||
|
@ -107,3 +107,5 @@ export function showLoader() {
|
||||
document.body.classList.add("loading");
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
export { withLayoutSize } from "./withLayoutSize";
|
||||
|
15
web/ASC.Web.Common/src/utils/withLayoutSize.js
Normal file
15
web/ASC.Web.Common/src/utils/withLayoutSize.js
Normal file
@ -0,0 +1,15 @@
|
||||
import * as React from "react";
|
||||
import { utils } from "asc-web-components";
|
||||
const { Consumer } = utils.context;
|
||||
|
||||
export function withLayoutSize(Component) {
|
||||
return function LayoutSizeComponent(props) {
|
||||
return (
|
||||
<Consumer>
|
||||
{(context) => {
|
||||
return <Component {...props} {...context} />;
|
||||
}}
|
||||
</Consumer>
|
||||
);
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user