diff --git a/packages/asc-web-common/api/people/filter.js b/packages/asc-web-common/api/people/filter.js index 96d0f9e788..d117f9e296 100644 --- a/packages/asc-web-common/api/people/filter.js +++ b/packages/asc-web-common/api/people/filter.js @@ -53,7 +53,7 @@ class Filter { return this.page > 0; }; - toDto = () => { + toDto = (forUrl = false) => { const { pageCount, sortBy, @@ -67,15 +67,12 @@ class Filter { let dtoFilter = { StartIndex: this.getStartIndex(), - Count: pageCount, sortby: sortBy, sortorder: sortOrder, employeestatus: employeeStatus, activationstatus: activationStatus, filtervalue: (search ?? "").trim(), groupId: group, - fields: - "id,status,isAdmin,isOwner,isVisitor,activationStatus,userName,email,mobilePhone,displayName,avatar,listAdminModules,birthday,title,location,isLDAP,isSSO,groups", }; switch (role) { @@ -92,11 +89,22 @@ class Filter { break; } + if (!forUrl) { + dtoFilter.fields = + "id,status,isAdmin,isOwner,isVisitor,activationStatus,userName,email,mobilePhone,displayName,avatar,listAdminModules,birthday,title,location,isLDAP,isSSO,groups"; + dtoFilter.Count = pageCount; + } else { + if (pageCount !== DEFAULT_PAGE_COUNT) { + dtoFilter.Count = pageCount; + } + } + return dtoFilter; }; toUrlParams = () => { - const dtoFilter = this.toDto(); + const dtoFilter = this.toDto(true); + const str = toUrlParams(dtoFilter, true); return str; }; diff --git a/products/ASC.People/Client/src/components/Article/Body/index.js b/products/ASC.People/Client/src/components/Article/Body/index.js index 6280518ba8..7537fa365e 100644 --- a/products/ASC.People/Client/src/components/Article/Body/index.js +++ b/products/ASC.People/Client/src/components/Article/Body/index.js @@ -1,24 +1,21 @@ import React from "react"; import styled, { css } from "styled-components"; -import { withTranslation, I18nextProvider } from "react-i18next"; - -import { isArrayEqual } from "@appserver/components/utils/array"; +import { withTranslation } from "react-i18next"; +import Filter from "@appserver/common/api/people/filter"; import TreeMenu from "@appserver/components/tree-menu"; import TreeNode from "@appserver/components/tree-menu/sub-components/tree-node"; import Link from "@appserver/components/link"; -// import { withTranslation } from "react-i18next"; -import history from "@appserver/common/history"; + import Loaders from "@appserver/common/components/Loaders"; import CatalogFolderIcon from "../../../../../../../public/images/catalog.folder.react.svg"; import DepartmentsGroupIcon from "../../../../public/images/departments.group.react.svg"; import ExpanderDownIcon from "../../../../../../../public/images/expander-down.react.svg"; import ExpanderRightIcon from "../../../../../../../public/images/expander-right.react.svg"; -// import { createI18N } from "../../../helpers/i18n"; - -// import styled, { css } from "styled-components"; import { inject, observer } from "mobx-react"; import { getSelectedGroup } from "../../../helpers/people-helpers"; import commonIconsStyles from "@appserver/components/utils/common-icons-style"; +import { withRouter } from "react-router"; +import config from "../../../../package.json"; const StyledTreeMenu = styled(TreeMenu)` ${(props) => @@ -96,51 +93,96 @@ class ArticleBodyContent extends React.Component { this.changeTitleDocument(); } + getTreeGroups = (groups, departments) => { + const linkProps = { fontSize: "14px", fontWeight: 600, noHover: true }; + const { history } = this.props; + const link = history.location.search.slice(1); + let newLink = link.split("&"); + const index = newLink.findIndex((x) => x.includes("group")); + index && newLink.splice(1, 1); + newLink = newLink.join("&"); + + const treeData = [ + { + key: "root", + title: ( + + {departments} + + ), + root: true, + children: + (groups && + groups.map((g) => { + return { + key: g.id, + title: ( + + {g.name} + + ), + root: false, + }; + })) || + [], + }, + ]; + + return treeData; + }; + componentDidUpdate(prevProps) { if (prevProps.selectedKeys[0] !== this.props.selectedKeys[0]) { this.changeTitleDocument(); } } - changeTitleDocument(data = null) { + changeTitleDocument(id) { const { groups, selectedKeys, setDocumentTitle } = this.props; const currentGroup = getSelectedGroup( groups, - data ? data[0] : selectedKeys[0] + id === "root" ? selectedKeys[0] : id ); currentGroup ? setDocumentTitle(currentGroup.name) : setDocumentTitle(); } - shouldComponentUpdate(nextProps) { - if (!isArrayEqual(nextProps.selectedKeys, this.props.selectedKeys)) { - return true; - } - if (!isArrayEqual(nextProps.data, this.props.data)) { - return true; - } - - return false; - } onSelectHandler = (data) => { const { isEdit, setIsVisibleDataLossDialog } = this.props; if (isEdit) { - setIsVisibleDataLossDialog(true, this.onSelect(data)); + setIsVisibleDataLossDialog(true, () => this.onSelect(data)); } else { - this.onSelect(data)(); + this.onSelect(data); } }; onSelect = (data) => { - return () => { - const { selectGroup } = this.props; - const groupId = - data && data.length === 1 && data[0] !== "root" ? data[0] : null; + //const { selectGroup } = this.props; + const groupId = data[0]; + const isRoot = groupId === "root"; + //data && data.length === 1 && data[0] !== "root" ? data[0] : null; - this.changeTitleDocument(data); + const { history, selectGroup } = this.props; + + this.changeTitleDocument(groupId); + + if (history.location.pathname.indexOf("/people/filter") > 0) { selectGroup(groupId); - }; + } else { + const { filter } = this.props; + const newFilter = isRoot ? Filter.getDefault() : filter.clone(); + + if (!isRoot) newFilter.group = groupId; + + const urlFilter = newFilter.toUrlParams(); + history.push(`${config.homepage}/filter?${urlFilter}`); + } }; + switcherIcon = (obj) => { if (obj.isLeaf) { return null; @@ -153,7 +195,16 @@ class ArticleBodyContent extends React.Component { }; render() { - const { isLoaded, data, selectedKeys, isAdmin, isVisitor } = this.props; + const { + isLoaded, + groups, + groupsCaption, + selectedKeys, + isAdmin, + isVisitor, + } = this.props; + + const data = this.getTreeGroups(groups, groupsCaption); //console.log("PeopleTreeMenu", this.props); return ( @@ -185,76 +236,39 @@ class ArticleBodyContent extends React.Component { } } -const getTreeGroups = (groups, departments) => { - const linkProps = { fontSize: "14px", fontWeight: 600, noHover: true }; - const link = history.location.search.slice(1); - let newLink = link.split("&"); - const index = newLink.findIndex((x) => x.includes("group")); - index && newLink.splice(1, 1); - newLink = newLink.join("&"); - - const onTitleClick = () => { - history.push("/products/people/"); - }; - - const treeData = [ - { - key: "root", - title: ( - - {departments} - - ), - root: true, - children: - (groups && - groups.map((g) => { - return { - key: g.id, - title: ( - - {g.name} - - ), - root: false, - }; - })) || - [], - }, - ]; - - return treeData; -}; - -const BodyContent = withTranslation("Article")(ArticleBodyContent); +const BodyContent = withTranslation("Article")(withRouter(ArticleBodyContent)); export default inject(({ auth, peopleStore }) => { - const groups = peopleStore.groupsStore.groups; - const { groupsCaption } = auth.settingsStore.customNames; - const data = getTreeGroups(groups, groupsCaption); - const selectedKeys = peopleStore.selectedGroupStore.selectedGroup - ? [peopleStore.selectedGroupStore.selectedGroup] - : ["root"]; + const { settingsStore, isLoaded, setDocumentTitle, isAdmin } = auth; + const { customNames } = settingsStore; + const { + groupsStore, + selectedGroupStore, + editingFormStore, + setIsLoading, + isLoading, + filterStore, + } = peopleStore; + const { filter } = filterStore; + const { groups } = groupsStore; + const { groupsCaption } = customNames; + const { isEdit, setIsVisibleDataLossDialog } = editingFormStore; + const { selectedGroup, selectGroup } = selectedGroupStore; + const selectedKeys = selectedGroup ? [selectedGroup] : ["root"]; return { - setDocumentTitle: auth.setDocumentTitle, - isLoaded: auth.isLoaded, + setDocumentTitle, + isLoaded, isVisitor: auth.userStore.user.isVisitor, - isAdmin: auth.isAdmin, + isAdmin, groups, - data, + groups, + groupsCaption, selectedKeys, - selectGroup: peopleStore.selectedGroupStore.selectGroup, - isEdit: peopleStore.editingFormStore.isEdit, - setIsVisibleDataLossDialog: - peopleStore.editingFormStore.setIsVisibleDataLossDialog, - setIsLoading: peopleStore.setIsLoading, - isLoading: peopleStore.isLoading, + selectGroup, + isEdit, + setIsVisibleDataLossDialog, + setIsLoading, + isLoading, + filter, }; })(observer(BodyContent)); diff --git a/products/ASC.People/Client/src/helpers/constants.js b/products/ASC.People/Client/src/helpers/constants.js index cebcd9528c..1fca475129 100644 --- a/products/ASC.People/Client/src/helpers/constants.js +++ b/products/ASC.People/Client/src/helpers/constants.js @@ -2,7 +2,7 @@ export const GUID_EMPTY = "00000000-0000-0000-0000-000000000000"; export const EMPLOYEE_STATUS = "employeestatus"; export const ACTIVATION_STATUS = "activationstatus"; export const ROLE = "role"; -export const GROUP = "group"; +export const GROUP = "groupId"; export const SEARCH = "search"; export const SORT_BY = "sortby"; export const SORT_ORDER = "sortorder"; diff --git a/products/ASC.People/Client/src/pages/Home/Section/Body/index.js b/products/ASC.People/Client/src/pages/Home/Section/Body/index.js index 4b755a7837..71b4c9d7ca 100644 --- a/products/ASC.People/Client/src/pages/Home/Section/Body/index.js +++ b/products/ASC.People/Client/src/pages/Home/Section/Body/index.js @@ -1,7 +1,7 @@ import React from "react"; import RowContainer from "@appserver/components/row-container"; import { Consumer } from "@appserver/components/utils/context"; -import toastr from "studio/toastr"; +//import toastr from "studio/toastr"; import Loaders from "@appserver/common/components/Loaders"; import EmptyScreen from "./EmptyScreen"; @@ -10,68 +10,35 @@ import SimpleUserRow from "./SimpleUserRow"; import Dialogs from "./Dialogs"; import { isMobile } from "react-device-detect"; -class SectionBodyContent extends React.PureComponent { - constructor(props) { - super(props); - - this.state = { - isLoadedSection: true, - }; - } - - componentDidMount() { - const { isLoaded, fetchPeople, filter, peopleList } = this.props; - if (!isLoaded || peopleList.length > 0) return; - - this.setState({ isLoadedSection: false }); - - fetchPeople(filter) - .catch((error) => { - toastr.error(error); - }) - .finally(() => this.setState({ isLoadedSection: isLoaded })); - } - - render() { - // console.log("Home SectionBodyContent render()"); - const { isLoaded, peopleList, isLoading } = this.props; - - const { isLoadedSection } = this.state; - - return !isLoaded || (isMobile && isLoading) || !isLoadedSection ? ( - - ) : peopleList.length > 0 ? ( - <> - - {(context) => ( - - {peopleList.map((person) => ( - - ))} - - )} - - - - ) : ( - - ); - } -} +const SectionBodyContent = ({ isLoaded, peopleList, isLoading, isRefresh }) => { + return !isLoaded || (isMobile && isLoading) || isRefresh ? ( + + ) : peopleList.length > 0 ? ( + <> + + {(context) => ( + + {peopleList.map((person) => ( + + ))} + + )} + + + + ) : ( + + ); +}; export default inject(({ auth, peopleStore }) => ({ isLoaded: auth.isLoaded, - fetchPeople: peopleStore.usersStore.getUsersList, + isRefresh: peopleStore.isRefresh, peopleList: peopleStore.usersStore.peopleList, - - filter: peopleStore.filterStore.filter, isLoading: peopleStore.isLoading, }))(observer(SectionBodyContent)); diff --git a/products/ASC.People/Client/src/pages/Home/index.js b/products/ASC.People/Client/src/pages/Home/index.js index 368801aa70..d607925c9d 100644 --- a/products/ASC.People/Client/src/pages/Home/index.js +++ b/products/ASC.People/Client/src/pages/Home/index.js @@ -17,9 +17,31 @@ import { } from "./Section"; import { inject, observer } from "mobx-react"; import { isMobile } from "react-device-detect"; +import { getFilterByLocation } from "../../helpers/converters"; -const Home = ({ isLoading }) => { - //console.log("People Home render"); +const Home = ({ + isLoading, + history, + getUsersList, + setIsLoading, + setIsRefresh, +}) => { + const { location } = history; + const { pathname } = location; + console.log("People Home render"); + + useEffect(() => { + if (pathname.indexOf("/people/filter") > -1) { + setIsLoading(true); + setIsRefresh(true); + const newFilter = getFilterByLocation(location); + console.log("PEOPLE URL changed", pathname, newFilter); + getUsersList(newFilter).finally(() => { + setIsLoading(false); + setIsRefresh(false); + }); + } + }, [pathname, location]); useEffect(() => { isLoading ? showLoader() : hideLoader(); @@ -62,8 +84,9 @@ Home.propTypes = { isLoading: PropTypes.bool, }; -export default withRouter( - inject(({ peopleStore }) => ({ - isLoading: peopleStore.isLoading, - }))(observer(Home)) -); +export default inject(({ peopleStore }) => ({ + isLoading: peopleStore.isLoading, + getUsersList: peopleStore.usersStore.getUsersList, + setIsLoading: peopleStore.setIsLoading, + setIsRefresh: peopleStore.setIsRefresh, +}))(observer(withRouter(Home))); diff --git a/products/ASC.People/Client/src/store/FilterStore.js b/products/ASC.People/Client/src/store/FilterStore.js index cbd3e15cb9..8abf93b0bb 100644 --- a/products/ASC.People/Client/src/store/FilterStore.js +++ b/products/ASC.People/Client/src/store/FilterStore.js @@ -29,41 +29,12 @@ class FilterStore { } setFilterUrl = (filter) => { - const defaultFilter = Filter.getDefault(); - const params = []; - - if (filter.employeeStatus) { - params.push(`${EMPLOYEE_STATUS}=${filter.employeeStatus}`); - } - - if (filter.activationStatus) { - params.push(`${ACTIVATION_STATUS}=${filter.activationStatus}`); - } - - if (filter.role) { - params.push(`${ROLE}=${filter.role}`); - } - - if (filter.group) { - params.push(`${GROUP}=${filter.group}`); - } - - if (filter.search) { - params.push(`${SEARCH}=${filter.search.trim()}`); - } - - if (filter.pageCount !== defaultFilter.pageCount) { - params.push(`${PAGE_COUNT}=${filter.pageCount}`); - } - - params.push(`${PAGE}=${filter.page + 1}`); - params.push(`${SORT_BY}=${filter.sortBy}`); - params.push(`${SORT_ORDER}=${filter.sortOrder}`); - - //const isProfileView = history.location.pathname.includes('/people/view') || history.location.pathname.includes('/people/edit'); - //if (params.length > 0 && !isProfileView) { - history.push(`${config.homepage}/filter?${params.join("&")}`); - //} + const urlFilter = filter.toUrlParams(); + window.history.replaceState( + "", + "", + `${config.homepage}/filter?${urlFilter}` + ); }; setFilterParams = (data) => { diff --git a/products/ASC.People/Client/src/store/PeopleStore.js b/products/ASC.People/Client/src/store/PeopleStore.js index a47d8736e7..4c50eb940f 100644 --- a/products/ASC.People/Client/src/store/PeopleStore.js +++ b/products/ASC.People/Client/src/store/PeopleStore.js @@ -30,6 +30,7 @@ class PeopleStore { isLoading = false; isLoaded = false; + isRefresh = false; isInit = false; constructor() { @@ -48,6 +49,8 @@ class PeopleStore { makeObservable(this, { isLoading: observable, isLoaded: observable, + isRefresh: observable, + setIsRefresh: action, setIsLoading: action, setIsLoaded: action, init: action, @@ -67,19 +70,11 @@ class PeopleStore { if (this.isInit) return; this.isInit = true; - const re = new RegExp(`${config.homepage}((/?)$|/filter)`, "gm"); - const match = window.location.pathname.match(re); - authStore.settingsStore.setModuleInfo( config.homepage, "f4d98afd-d336-4332-8778-3c6945c81ea0" ); - if (match && match.length > 0) { - const newFilter = getFilterByLocation(window.location); - await this.usersStore.getUsersList(newFilter); - } - await this.groupsStore.getGroupList(); await authStore.settingsStore.getPortalPasswordSettings(); @@ -94,6 +89,10 @@ class PeopleStore { this.isLoaded = isLoaded; }; + setIsRefresh = (isRefresh) => { + this.isRefresh = isRefresh; + }; + resetFilter = (withoutGroup = false) => { const { filter } = this.filterStore; const { getUsersList } = this.usersStore; diff --git a/products/ASC.People/Client/src/store/SelectedGroupStore.js b/products/ASC.People/Client/src/store/SelectedGroupStore.js index ead5486467..ae9bb99d55 100644 --- a/products/ASC.People/Client/src/store/SelectedGroupStore.js +++ b/products/ASC.People/Client/src/store/SelectedGroupStore.js @@ -26,8 +26,10 @@ class SelectedGroupStore { const { setIsLoading } = this.peopleStore; setIsLoading(true); + let newFilter = filter.clone(); newFilter.group = groupId; + clearSelection(); getUsersList(newFilter).finally(() => setIsLoading(false)); }; diff --git a/products/ASC.People/Client/src/store/UsersStore.js b/products/ASC.People/Client/src/store/UsersStore.js index 8cef3f4b1c..d40ad5b239 100644 --- a/products/ASC.People/Client/src/store/UsersStore.js +++ b/products/ASC.People/Client/src/store/UsersStore.js @@ -34,13 +34,18 @@ class UsersStore { filterData.employeeStatus = EmployeeStatus.Active; } + if (filterData.group && filterData.group === "root") + filterData.group = undefined; + const res = await api.people.getUserList(filterData); filterData.total = res.total; this.peopleStore.filterStore.setFilterParams(filterData); - this.peopleStore.selectedGroupStore.setSelectedGroup(filterData.group); + this.peopleStore.selectedGroupStore.setSelectedGroup( + filterData.group || "root" + ); - this.users = res.items; + this.setUsers(res.items); }; setUsers = (users) => {