From b6f122d0b8141f8b1a5268d7673d7b2d06b1a20d Mon Sep 17 00:00:00 2001 From: Aleksandr Lushkin Date: Tue, 13 Feb 2024 20:45:39 +0100 Subject: [PATCH] Web: Client: Add GroupsStore --- packages/client/src/store/GroupsStore.js | 52 ---- packages/client/src/store/GroupsStore.ts | 333 +++++++++++++++++++++++ 2 files changed, 333 insertions(+), 52 deletions(-) delete mode 100644 packages/client/src/store/GroupsStore.js create mode 100644 packages/client/src/store/GroupsStore.ts diff --git a/packages/client/src/store/GroupsStore.js b/packages/client/src/store/GroupsStore.js deleted file mode 100644 index 580cc35126..0000000000 --- a/packages/client/src/store/GroupsStore.js +++ /dev/null @@ -1,52 +0,0 @@ -import { action, makeObservable, observable } from "mobx"; -import api from "@docspace/shared/api"; - -class GroupsStore { - groups = []; - - constructor(peopleStore) { - this.peopleStore = peopleStore; - makeObservable(this, { - groups: observable, - getGroupList: action, - deleteGroup: action, - createGroup: action, - updateGroup: action, - }); - } - - getGroupList = async () => { - const res = await api.groups.getGroupList(); //TODO: replace with getGroupListFull() after fixing problems on the server - this.groups = res; - }; - - deleteGroup = async (id) => { - const { filter } = this.peopleStore.filterStore; - await api.groups.deleteGroup(id); - const newData = this.groups.filter((g) => g.id !== id); - this.groups = newData; - await this.peopleStore.usersStore.getUsersList(filter); - }; - - createGroup = async (groupName, groupManager, members) => { - const res = await api.groups.createGroup(groupName, groupManager, members); - this.peopleStore.selectedGroupStore.resetGroup(); - this.groups.push(res); - this.groups.sort((a, b) => a.name.localeCompare(b.name)); - return Promise.resolve(res); - }; - - updateGroup = async (id, groupName, groupManager, members) => { - const res = await api.groups.updateGroup( - id, - groupName, - groupManager, - members - ); - this.peopleStore.selectedGroupStore.resetGroup(); - await this.getGroupList(); - return Promise.resolve(res); - }; -} - -export default GroupsStore; diff --git a/packages/client/src/store/GroupsStore.ts b/packages/client/src/store/GroupsStore.ts new file mode 100644 index 0000000000..18827d910c --- /dev/null +++ b/packages/client/src/store/GroupsStore.ts @@ -0,0 +1,333 @@ +import { makeAutoObservable, runInAction } from "mobx"; +import * as groupsApi from "@docspace/shared/api/groups"; +import { Events } from "@docspace/shared/enums"; +import { toastr } from "@docspace/shared/components/toast"; +import Filter from "@docspace/shared/api/groups/filter"; +import InsideGroupFilter from "@docspace/shared/api/people/filter"; +import GroupsFilter from "@docspace/shared/api/groups/filter"; +import PencilReactSvgUrl from "PUBLIC_DIR/images/pencil.react.svg?url"; +import TrashReactSvgUrl from "PUBLIC_DIR/images/trash.react.svg?url"; +import InfoReactSvgUrl from "PUBLIC_DIR/images/info.outline.react.svg?url"; +import config from "PACKAGE_FILE"; +import { combineUrl } from "@docspace/shared/utils/combineUrl"; +import AccountsFilter from "@docspace/shared/api/people/filter"; +import api from "@docspace/shared/api"; + +class GroupsStore { + authStore; + peopleStore; + infoPanelStore; + + groups = []; + selection = []; + bufferSelection = null; + + groupsFilter = GroupsFilter.getDefault(); + groupsIsIsLoading = false; + + currentGroup = null; + + insideGroupFilter = InsideGroupFilter.getDefault(); + insideGroupBackUrl = null; + + constructor(authStore: any, peopleStore: any, infoPanelStore: any) { + this.authStore = authStore; + this.peopleStore = peopleStore; + this.infoPanelStore = infoPanelStore; + makeAutoObservable(this); + } + + // Groups Filter + + setGroupsFilter = (filter = GroupsFilter.getDefault()) => { + const key = `GroupsFilter=${this.peopleStore.userStore.user.id}`; + const value = `${filter.sortBy},${filter.pageCount},${filter.sortOrder}`; + localStorage.setItem(key, value); + + this.groupsFilter = filter; + }; + + setGroupsFilterUrl = (filter = GroupsFilter.getDefault()) => { + const urlFilter = filter.toUrlParams(); + + const newPath = combineUrl(`/accounts/groups/filter?${urlFilter}`); + const currentPath = window.location.pathname + window.location.search; + + if (currentPath === newPath) return; + + window.history.replaceState( + "", + "", + combineUrl(window.DocSpaceConfig?.proxy?.url, config.homepage, newPath), + ); + }; + + setFilterParams = (filter = GroupsFilter.getDefault()) => { + this.setGroupsFilterUrl(filter); + this.setGroupsFilter(filter); + }; + + resetGroupsFilter = () => { + this.setFilterParams(GroupsFilter.getDefault()); + }; + + get groupsFilterTotal() { + return this.groupsFilter.total; + } + + get hasMoreGroups() { + return this.groups.length < this.groupsFilterTotal; + } + + get groupsIsFiltered() { + if (this.groupsFilter.search !== "") return true; + if (this.groupsFilter.userId !== null) return true; + return false; + } + + // Inside Group Filter + + setInsideGroupFilter = (filter) => { + const key = `InsideGroupFilter=${this.peopleStore.userStore.user.id}`; + const value = `${filter.sortBy},${filter.pageCount},${filter.sortOrder}`; + localStorage.setItem(key, value); + + this.insideGroupFilter = filter; + }; + + setInsideGroupFilterUrl = (filter = InsideGroupFilter.getDefault()) => { + if (!filter.group) return; + const urlFilter = filter.toUrlParams(); + + const newPath = combineUrl( + `/accounts/groups/${filter.group}/filter?${urlFilter}`, + ); + const currentPath = window.location.pathname + window.location.search; + + if (currentPath === newPath) return; + + window.history.replaceState( + "", + "", + combineUrl(window.DocSpaceConfig?.proxy?.url, config.homepage, newPath), + ); + }; + + setInsideGroupFilterParams = (filter = InsideGroupFilter.getDefault()) => { + this.setInsideGroupFilter(filter); + this.setInsideGroupFilterUrl(filter); + }; + + setCurrentGroup = (currentGroup = null) => { + this.currentGroup = currentGroup; + }; + + setInsideGroupBackUrl = (url: string) => { + this.insideGroupBackUrl = url; + }; + + getGroups = async ( + filter = GroupsFilter.getDefault(), + updateFilter = false, + withFilterLocalStorage = false, + ) => { + const filterData = filter ? filter.clone() : Filter.getDefault(); + + const filterStorageItem = localStorage.getItem( + `GroupsFilter=${this.peopleStore.userStore.user?.id}`, + ); + + if (filterStorageItem && withFilterLocalStorage) { + const splitFilter = filterStorageItem.split(","); + filterData.sortBy = splitFilter[0]; + filterData.pageCount = +splitFilter[1]; + filterData.sortOrder = splitFilter[2]; + } + + const res = await groupsApi.getGroups(filterData); + filterData.total = res.total; + + if (updateFilter) this.setFilterParams(filterData); + + this.groups = res.items || []; + }; + + fetchMoreGroups = async () => { + if (!this.hasMoreAccounts || this.groupsIsIsLoading) return; + this.groupsIsIsLoading = true; + + const newFilter = this.groupsFilter.clone(); + newFilter.page += 1; + this.setFilterParams(newFilter); + + const res = await groupsApi.getGroups(newFilter); + + runInAction(() => { + this.groups = [...this.groups, ...res.items]; + this.groupsFilter = newFilter; + this.groupsIsIsLoading = false; + }); + }; + + get hasMoreAccounts() { + return this.groups.length < this.groupsFilter.total; + } + + getGroupById = async (groupId) => { + const res = await groupsApi.getGroupById(groupId); + return res; + }; + + fetchGroup = async ( + groupId, + filter, + updateFilter = false, + withFilterLocalStorage = false, + ) => { + const filterData = filter ? filter.clone() : AccountsFilter.getDefault(); + filterData.group = groupId; + + if (!this.authStore.settingsStore.withPaging) { + filterData.page = 0; + filterData.pageCount = 100; + } + + const filterStorageItem = localStorage.getItem( + `InsideGroupFilter=${this.peopleStore.userStore.user?.id}`, + ); + + if (filterStorageItem && withFilterLocalStorage) { + const splitFilter = filterStorageItem.split(","); + + filterData.sortBy = splitFilter[0]; + filterData.pageCount = +splitFilter[1]; + filterData.sortOrder = splitFilter[2]; + } + + const requests = []; + + requests.push(api.people.getUserList(filterData)); + + if (groupId !== this.currentGroup?.id) { + requests.push(groupsApi.getGroupById(groupId)); + } + + const [filteredMembersRes, group] = await Promise.all(requests); + filterData.total = filteredMembersRes.total; + + group && this.setCurrentGroup(group); + this.peopleStore.usersStore.setUsers(filteredMembersRes.items); + + if (updateFilter) { + this.setInsideGroupFilterParams(filterData); + } + + return Promise.resolve(filteredMembersRes.items); + }; + + setSelection = (selection) => (this.selection = selection); + + setBufferSelection = (bufferSelection) => + (this.bufferSelection = bufferSelection); + + setSelections = (added, removed, clear = false) => { + if (clear) this.selection = []; + + let newSelections = [...this.selection]; + + for (let row of added) { + if (!row) return; + + const [element] = row.getElementsByClassName("group-item"); + const groupId = element?.getAttribute("value"); + if (!groupId) return; + + const isNotSelected = + this.selection.findIndex((g) => g.id === groupId) === -1; + if (isNotSelected) { + const group = this.groups.find((g) => g.id === groupId); + newSelections.push(group); + } + } + + for (let row of removed) { + if (!row) return; + + const [element] = row.getElementsByClassName("group-item"); + const groupId = element?.getAttribute("value"); + if (!groupId) return; + + const isSelected = + newSelections.findIndex((g) => g.id === groupId) !== -1; + if (isSelected) { + newSelections = newSelections.filter((g) => g.id !== groupId); + } + } + + this.setSelection(newSelections); + }; + + getGroupContextOptions = (t, item) => { + return [ + { + id: "edit-group", + key: "edit-group", + className: "group-menu_drop-down", + label: t("Edit department"), + title: t("Edit department"), + icon: PencilReactSvgUrl, + onClick: () => { + const event = new Event(Events.GROUP_EDIT); + event.item = item; + window.dispatchEvent(event); + }, + }, + { + id: "info", + key: "group-info", + className: "group-menu_drop-down", + label: t("Info"), + title: t("Info"), + icon: InfoReactSvgUrl, + onClick: () => { + const { setIsVisible } = this.infoPanelStore; + this.selection = [item]; + setIsVisible(true); + }, + }, + { + key: "separator", + isSeparator: true, + }, + { + id: "delete-group", + key: "delete-group", + className: "group-menu_drop-down", + label: t("Delete"), + title: t("Delete"), + icon: TrashReactSvgUrl, + onClick: async () => { + const groupId = item.id; + groupsApi + .deleteGroup(groupId)! + .then(() => { + toastr.success(t("Group was deleted successfully")); + this.getGroups(); + }) + .catch((err) => { + toastr.error(err.message); + console.error(err); + }); + }, + }, + ]; + }; + + clearInsideGroup = () => { + this.currentGroup = null; + this.insideGroupBackUrl = null; + this.peopleStore.usersStore.setUsers([]); + }; +} + +export default GroupsStore;