Merge branch 'develop' into refactoring/files-thirdparty

This commit is contained in:
pavelbannov 2020-11-18 15:19:36 +03:00
commit 93410996f0
25 changed files with 438 additions and 530 deletions

View File

@ -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))));

View File

@ -32,7 +32,7 @@ using ASC.Files.Thirdparty;
namespace ASC.Files.Core
{
[Scope(typeof(CachedProviderAccountDao), Additional = typeof(ProviderAccountDaoExtension))]
[Scope(typeof(ProviderAccountDao), Additional = typeof(ProviderAccountDaoExtension))]
public interface IProviderDao
{
IProviderInfo GetProviderInfo(int linkId);

View File

@ -19,7 +19,7 @@ namespace ASC.Files.Core.EF
public override object[] GetKeys()
{
return new object[] { Id };
return new object[] { HashId };
}
}

View File

@ -48,7 +48,7 @@ namespace ASC.Files.Thirdparty.Box
{
internal abstract class BoxDaoBase : ThirdPartyProviderDao<BoxProviderInfo>
{
public override string Id { get => "box"; }
protected override string Id { get => "box"; }
public BoxDaoBase(
IServiceProvider serviceProvider,

View File

@ -183,7 +183,7 @@ namespace ASC.Files.Thirdparty.Box
internal BoxStorage CreateStorage(OAuth20Token token, int id)
{
if (Storage != null) return Storage;
if (Storage != null && Storage.IsOpened) return Storage;
var boxStorage = new BoxStorage();
CheckToken(token, id);
@ -199,7 +199,7 @@ namespace ASC.Files.Thirdparty.Box
{
token = OAuth20TokenHelper.RefreshToken<BoxLoginProvider>(ConsumerFactory, token);
var dbDao = ServiceProvider.GetService<CachedProviderAccountDao>();
var dbDao = ServiceProvider.GetService<ProviderAccountDao>();
dbDao.UpdateProviderInfo(id, new AuthData(token: token.ToJson()));
}
}

View File

@ -1,125 +0,0 @@
/*
*
* (c) Copyright Ascensio System Limited 2010-2018
*
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
* In accordance with Section 7(a) of the GNU GPL its Section 15 shall be amended to the effect that
* Ascensio System SIA expressly excludes the warranty of non-infringement of any third-party rights.
*
* THIS PROGRAM IS DISTRIBUTED WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR
* FITNESS FOR A PARTICULAR PURPOSE. For more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
*
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
*
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
*
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
* relevant author attributions when distributing the software. If the display of the logo in its graphic
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
* in every copy of the program you distribute.
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
*
*/
using System;
using System.Collections.Concurrent;
using System.Globalization;
using ASC.Common;
using ASC.Common.Caching;
using ASC.Common.Logging;
using ASC.Core;
using ASC.Core.Common.Configuration;
using ASC.Core.Common.EF;
using ASC.Core.Tenants;
using ASC.Files.Core;
using ASC.Files.Core.EF;
using ASC.Security.Cryptography;
using Microsoft.Extensions.Options;
namespace ASC.Files.Thirdparty
{
[Singletone]
internal class CachedProviderAccountDaoNotify
{
public ConcurrentDictionary<string, IProviderInfo> Cache { get; private set; }
internal ICacheNotify<ProviderAccountCacheItem> CacheNotify { get; set; }
public CachedProviderAccountDaoNotify(ICacheNotify<ProviderAccountCacheItem> cacheNotify)
{
Cache = new ConcurrentDictionary<string, IProviderInfo>();
CacheNotify = cacheNotify;
cacheNotify.Subscribe((i) => RemoveFromCache(i.Key), CacheNotifyAction.Any);
}
private void RemoveFromCache(string key)
{
Cache.TryRemove(key, out _);
}
}
[Scope]
internal class CachedProviderAccountDao : ProviderAccountDao
{
private readonly ConcurrentDictionary<string, IProviderInfo> cache;
private readonly ICacheNotify<ProviderAccountCacheItem> cacheNotify;
private string _rootKey { get => TenantID.ToString(CultureInfo.InvariantCulture); }
public CachedProviderAccountDao(
IServiceProvider serviceProvider,
TenantUtil tenantUtil,
TenantManager tenantManager,
InstanceCrypto instanceCrypto,
SecurityContext securityContext,
ConsumerFactory consumerFactory,
DbContextManager<FilesDbContext> dbContextManager,
IOptionsMonitor<ILog> options,
CachedProviderAccountDaoNotify cachedProviderAccountDaoNotify)
: base(serviceProvider, tenantUtil, tenantManager, instanceCrypto, securityContext, consumerFactory, dbContextManager, options)
{
cache = cachedProviderAccountDaoNotify.Cache;
cacheNotify = cachedProviderAccountDaoNotify.CacheNotify;
}
public override IProviderInfo GetProviderInfo(int linkId)
{
var key = _rootKey + linkId.ToString(CultureInfo.InvariantCulture);
if (!cache.TryGetValue(key, out var value))
{
value = base.GetProviderInfo(linkId);
cache.TryAdd(key, value);
}
return value;
}
public override void RemoveProviderInfo(int linkId)
{
base.RemoveProviderInfo(linkId);
var key = _rootKey + linkId.ToString(CultureInfo.InvariantCulture);
cacheNotify.Publish(new ProviderAccountCacheItem { Key = key }, CacheNotifyAction.Any);
}
public override int UpdateProviderInfo(int linkId, string customerTitle, AuthData authData, FolderType folderType, Guid? userId = null)
{
var result = base.UpdateProviderInfo(linkId, customerTitle, authData, folderType, userId);
var key = _rootKey + linkId.ToString(CultureInfo.InvariantCulture);
cacheNotify.Publish(new ProviderAccountCacheItem { Key = key }, CacheNotifyAction.Any);
return result;
}
public override int UpdateProviderInfo(int linkId, AuthData authData)
{
var result = base.UpdateProviderInfo(linkId, authData);
var key = _rootKey + linkId.ToString(CultureInfo.InvariantCulture);
cacheNotify.Publish(new ProviderAccountCacheItem { Key = key }, CacheNotifyAction.Any);
return result;
}
}
}

View File

@ -48,7 +48,7 @@ namespace ASC.Files.Thirdparty.Dropbox
{
internal abstract class DropboxDaoBase : ThirdPartyProviderDao<DropboxProviderInfo>
{
public override string Id { get => "dropbox"; }
protected override string Id { get => "dropbox"; }
public DropboxDaoBase(IServiceProvider serviceProvider, UserManager userManager, TenantManager tenantManager, TenantUtil tenantUtil, DbContextManager<FilesDbContext> dbContextManager, SetupInfo setupInfo, IOptionsMonitor<ILog> monitor, FileUtility fileUtility) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
{

View File

@ -162,7 +162,7 @@ namespace ASC.Files.Thirdparty.Dropbox
public DropboxStorage CreateStorage(OAuth20Token token)
{
if (Storage != null) return Storage;
if (Storage != null && Storage.IsOpened) return Storage;
var dropboxStorage = new DropboxStorage();
dropboxStorage.Open(token);

View File

@ -49,7 +49,7 @@ namespace ASC.Files.Thirdparty.GoogleDrive
{
internal abstract class GoogleDriveDaoBase : ThirdPartyProviderDao<GoogleDriveProviderInfo>
{
public override string Id { get => "drive"; }
protected override string Id { get => "drive"; }
public GoogleDriveDaoBase(IServiceProvider serviceProvider, UserManager userManager, TenantManager tenantManager, TenantUtil tenantUtil, DbContextManager<FilesDbContext> dbContextManager, SetupInfo setupInfo, IOptionsMonitor<ILog> monitor, FileUtility fileUtility) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
{

View File

@ -196,7 +196,7 @@ namespace ASC.Files.Thirdparty.GoogleDrive
public GoogleDriveStorage CreateStorage(OAuth20Token token, int id)
{
if (Storage != null) return Storage;
if (Storage != null && Storage.IsOpened) return Storage;
var driveStorage = ServiceProvider.GetService<GoogleDriveStorage>();
@ -213,7 +213,7 @@ namespace ASC.Files.Thirdparty.GoogleDrive
{
token = OAuth20TokenHelper.RefreshToken<GoogleLoginProvider>(ConsumerFactory, token);
var dbDao = ServiceProvider.GetService<CachedProviderAccountDao>();
var dbDao = ServiceProvider.GetService<ProviderAccountDao>();
var authData = new AuthData(token: token.ToJson());
dbDao.UpdateProviderInfo(id, authData);
}

View File

@ -188,14 +188,14 @@ namespace ASC.Files.Thirdparty
protected TenantUtil TenantUtil { get; }
protected FilesDbContext FilesDbContext { get; }
protected SetupInfo SetupInfo { get; }
public ILog Log { get; }
protected ILog Log { get; }
protected FileUtility FileUtility { get; }
public RegexDaoSelectorBase<T> DaoSelector { get; set; }
public T ProviderInfo { get; set; }
public string PathPrefix { get; private set; }
protected RegexDaoSelectorBase<T> DaoSelector { get; set; }
protected T ProviderInfo { get; set; }
protected string PathPrefix { get; private set; }
public abstract string Id { get; }
protected abstract string Id { get; }
public ThirdPartyProviderDao(
IServiceProvider serviceProvider,

View File

@ -47,7 +47,7 @@ namespace ASC.Files.Thirdparty.OneDrive
{
internal abstract class OneDriveDaoBase : ThirdPartyProviderDao<OneDriveProviderInfo>
{
public override string Id { get => "onedrive"; }
protected override string Id { get => "onedrive"; }
public OneDriveDaoBase(IServiceProvider serviceProvider, UserManager userManager, TenantManager tenantManager, TenantUtil tenantUtil, DbContextManager<FilesDbContext> dbContextManager, SetupInfo setupInfo, IOptionsMonitor<ILog> monitor, FileUtility fileUtility) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
{

View File

@ -157,7 +157,7 @@ namespace ASC.Files.Thirdparty.OneDrive
public OneDriveStorage CreateStorage(OAuth20Token token, int id)
{
if (Storage != null) return Storage;
if (Storage != null && Storage.IsOpened) return Storage;
var onedriveStorage = ServiceProvider.GetService<OneDriveStorage>();
@ -174,7 +174,7 @@ namespace ASC.Files.Thirdparty.OneDrive
{
token = OAuth20TokenHelper.RefreshToken<OneDriveLoginProvider>(ConsumerFactory, token);
var dbDao = ServiceProvider.GetService<CachedProviderAccountDao>();
var dbDao = ServiceProvider.GetService<ProviderAccountDao>();
var authData = new AuthData(token: token.ToJson());
dbDao.UpdateProviderInfo(id, authData);
}

View File

@ -149,7 +149,7 @@ namespace ASC.Files.Thirdparty
public void RenameProvider(T provider, string newTitle)
{
var dbDao = ServiceProvider.GetService<CachedProviderAccountDao>();
var dbDao = ServiceProvider.GetService<ProviderAccountDao>();
dbDao.UpdateProviderInfo(provider.ID, newTitle, null, provider.RootFolderType);
provider.UpdateTitle(newTitle); //This will update cached version too
}

View File

@ -45,7 +45,7 @@ namespace ASC.Files.Thirdparty.SharePoint
{
internal class SharePointDaoBase : ThirdPartyProviderDao<SharePointProviderInfo>
{
public override string Id { get => "spoint"; }
protected override string Id { get => "spoint"; }
public SharePointDaoBase(IServiceProvider serviceProvider, UserManager userManager, TenantManager tenantManager, TenantUtil tenantUtil, DbContextManager<FilesDbContext> dbContextManager, SetupInfo setupInfo, IOptionsMonitor<ILog> monitor, FileUtility fileUtility) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
{

View File

@ -50,7 +50,7 @@ namespace ASC.Files.Thirdparty.Sharpbox
{
internal abstract class SharpBoxDaoBase : ThirdPartyProviderDao<SharpBoxProviderInfo>
{
public override string Id { get => "sbox"; }
protected override string Id { get => "sbox"; }
public SharpBoxDaoBase(IServiceProvider serviceProvider, UserManager userManager, TenantManager tenantManager, TenantUtil tenantUtil, DbContextManager<FilesDbContext> dbContextManager, SetupInfo setupInfo, IOptionsMonitor<ILog> monitor, FileUtility fileUtility) : base(serviceProvider, userManager, tenantManager, tenantUtil, dbContextManager, setupInfo, monitor, fileUtility)
{

View File

@ -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)))
);

View File

@ -864,21 +864,8 @@ namespace ASC.Employee.Core.Controllers
return new ThumbnailsDataWrapper(user.ID, UserPhotoManager);
}
[Create("{userid}/photo")]
public FileUploadResult UploadMemberPhotoFromBody(string userid, [FromBody]IFormCollection model)
{
return UploadMemberPhoto(userid, model);
}
[Create("{userid}/photo")]
[Consumes("application/x-www-form-urlencoded")]
public FileUploadResult UploadMemberPhotoFromForm(string userid, [FromForm] IFormCollection model)
{
return UploadMemberPhoto(userid, model);
}
private FileUploadResult UploadMemberPhoto(string userid, IFormCollection model)
public FileUploadResult UploadMemberPhoto(string userid, IFormCollection model)
{
var result = new People.Models.FileUploadResult();
var autosave = bool.Parse(model["Autosave"]);

View File

@ -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": [

View File

@ -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"
);
}
getFilterData() {
const _this = this;
};
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);
}
}
}
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",
""
);
}
updateFilter(inputFilterItems) {
const currentFilterItems =
inputFilterItems || cloneObjectsArray(this.state.filterValues);
};
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;
}
}
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),
});
} else if (filterWidth > fullWidth / 2) {
let newOpenFilterItems = cloneObjectsArray(currentFilterItems);
let newHideFilterItems = [];
let elementsWidth = 0;
Array.from(filterArr).forEach((element) => {
elementsWidth = elementsWidth + element.getBoundingClientRect().width;
});
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,
});
} else {
this.setState({
openFilterItems: currentFilterItems.slice(),
hideFilterItems: [],
openFilterItems: numberOfHiddenItems
? currentFilterItems.slice(
0,
currentFilterItems.length - numberOfHiddenItems
)
: currentFilterItems.slice(),
hiddenFilterItems: numberOfHiddenItems
? currentFilterItems.slice(-numberOfHiddenItems)
: [],
});
}
}
onDeleteFilterItem(key) {
};
getItemLabel = (item) => {
let label = "";
if (item.selectedItem) {
label = item.selectedItem.label
? item.selectedItem.label
: item.defaultSelectLabel;
} else {
label = item.label;
}
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) {
this.updateFilter();
};
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,37 +787,38 @@ 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>
<SortComboBox
options={getSortData()}
isDisabled={isDisabled}
onChangeSortId={this.onClickSortItem}
onChangeView={this.onClickViewSelector}
onChangeSortDirection={this.onChangeSortDirection}
selectedOption={
getSortData().length > 0
? getSortData().find((x) => x.key === sortId)
: {}
}
onButtonClick={this.onSortDirectionClick}
viewAs={viewAs}
sortDirection={+sortDirection}
directionAscLabel={directionAscLabel}
directionDescLabel={directionDescLabel}
/>
<div ref={this.rectComboBoxRef}>
<SortComboBox
options={getSortData()}
isDisabled={isDisabled}
onChangeSortId={this.onClickSortItem}
onChangeView={this.onClickViewSelector}
onChangeSortDirection={this.onChangeSortDirection}
selectedOption={
getSortData().length > 0
? getSortData().find((x) => x.key === sortId)
: {}
}
onButtonClick={this.onSortDirectionClick}
viewAs={viewAs}
sortDirection={+sortDirection}
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 = {

View File

@ -107,7 +107,7 @@ const StyledFilterInput = styled.div`
margin-left: 8px;
${(props) =>
props.isMobile &&
(props.isMobile || props.smallSectionWidth) &&
`
width: 50px;
.optionalBlock ~ div:first-child{

View File

@ -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,

View File

@ -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}

View File

@ -107,3 +107,5 @@ export function showLoader() {
document.body.classList.add("loading");
}, 1000);
}
export { withLayoutSize } from "./withLayoutSize";

View 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>
);
};
}