Web:Files:VirtualRooms: add group menu for virtual room pages

This commit is contained in:
TimofeyBoyko 2022-07-12 14:05:51 +03:00
parent 1bee56d3aa
commit 9bfb54bcc3
4 changed files with 382 additions and 45 deletions

View File

@ -13,7 +13,37 @@ import VirtualRoomsTable from "./TableView";
import withLoader from "../../../../HOCs/withLoader"; import withLoader from "../../../../HOCs/withLoader";
const SectionBodyContent = ({ isEmpty, viewAs }) => { const SectionBodyContent = ({
isEmpty,
viewAs,
setSelection,
setBufferSelection,
}) => {
React.useEffect(() => {
window.addEventListener("mousedown", onMouseDown);
return () => {
window.removeEventListener("mousedown", onMouseDown);
};
}, []);
const onMouseDown = React.useCallback((e) => {
if (
(e.target.closest(".scroll-body") &&
!e.target.closest(".rooms-item") &&
!e.target.closest(".not-selectable") &&
!e.target.closest(".info-panel") &&
!e.target.closest(".table-container_group-menu")) ||
e.target.closest(".files-main-button") ||
e.target.closest(".add-button") ||
e.target.closest(".search-input-block")
) {
setSelection([]);
setBufferSelection(null);
}
}, []);
return ( return (
<Consumer> <Consumer>
{(context) => {(context) =>
@ -34,9 +64,9 @@ const SectionBodyContent = ({ isEmpty, viewAs }) => {
export default inject(({ filesStore, roomsStore }) => { export default inject(({ filesStore, roomsStore }) => {
const { viewAs } = filesStore; const { viewAs } = filesStore;
const { rooms } = roomsStore; const { rooms, setSelection, setBufferSelection } = roomsStore;
const isEmpty = rooms.length < 1; const isEmpty = rooms.length === 0;
return { viewAs, isEmpty }; return { viewAs, isEmpty, setSelection, setBufferSelection };
})(withTranslation([])(withLoader(observer(SectionBodyContent))())); })(withTranslation([])(withLoader(observer(SectionBodyContent))()));

View File

@ -1,60 +1,213 @@
import React from "react"; import React from "react";
import styled from "styled-components"; import styled, { css } from "styled-components";
import { inject, observer } from "mobx-react"; import { inject, observer } from "mobx-react";
import { withTranslation } from "react-i18next"; import { withTranslation } from "react-i18next";
import { isMobile } from "react-device-detect"; import { isMobile } from "react-device-detect";
import { tablet } from "@appserver/components/utils/device"; import { tablet } from "@appserver/components/utils/device";
import Headline from "@appserver/common/components/Headline"; import Navigation from "@appserver/common/components/Navigation";
import IconButton from "@appserver/components/icon-button";
import withLoader from "../../../../HOCs/withLoader";
import Loaders from "@appserver/common/components/Loaders"; import Loaders from "@appserver/common/components/Loaders";
import TableGroupMenu from "@appserver/components/table-container/TableGroupMenu";
import withLoader from "../../../../HOCs/withLoader";
import { Consumer } from "@appserver/components/utils/context";
import { FolderType } from "@appserver/common/constants";
import DropDownItem from "@appserver/components/drop-down-item";
const StyledContainer = styled.div` const StyledContainer = styled.div`
width: 100%; .table-container_group-menu {
height: 53px; ${(props) =>
display: flex; props.viewAs === "table"
align-items: center; ? css`
`; margin: 0px -20px;
width: calc(100% + 40px);
`
: css`
margin: 0px -20px;
width: calc(100% + 40px);
`}
const StyledHeadline = styled(Headline)` @media ${tablet} {
font-weight: 700; margin: 0 -16px;
font-size: ${isMobile ? "21px !important" : "18px"}; width: calc(100% + 32px);
line-height: ${isMobile ? "28px !important" : "24px"}; }
margin-right: 16px; ${isMobile &&
css`
@media ${tablet} { margin: 0 -16px;
font-size: 21px; width: calc(100% + 32px);
line-height: 28px; `}
} }
`; `;
const SectionHeaderContent = ({ createRoom, title }) => { const SectionHeaderContent = ({
return ( t,
<StyledContainer>
<StyledHeadline>{title}</StyledHeadline> createRoom,
<IconButton viewAs,
zIndex={402} title,
className="create-button" showText,
directionX="right" isArchive,
iconName="images/plus.svg" isDesktop,
size={15} isTabletView,
isFill tReady,
onClick={createRoom} navigationPath,
isDisabled={false}
isHeaderVisible,
isHeaderChecked,
isHeaderIndeterminate,
checkboxMenuItems,
getRoomCheckboxTitle,
setSelected,
getHeaderMenu,
toggleInfoPanel,
isInfoPanelVisible,
}) => {
const getContextOptionsPlus = () => {
return [];
};
const getContextOptionsFolder = () => {
return [];
};
const renderGroupMenu = React.useCallback(() => {
const onSelected = (e) => {
setSelected && setSelected(e.target.dataset.key);
};
const onChange = (checked) => {
setSelected && setSelected(checked ? "all" : "none");
};
const menuItems = (
<>
{checkboxMenuItems.map((key) => {
const label = getRoomCheckboxTitle(t, key);
return (
<DropDownItem
key={key}
label={label}
data-key={key}
onClick={onSelected}
/>
);
})}
</>
);
const headerMenu = getHeaderMenu(t);
return (
<TableGroupMenu
checkboxOptions={menuItems}
onChange={onChange}
isChecked={isHeaderChecked}
isIndeterminate={isHeaderIndeterminate}
headerMenu={headerMenu}
isInfoPanelVisible={isInfoPanelVisible}
toggleInfoPanel={toggleInfoPanel}
/> />
</StyledContainer> );
}, [
t,
isHeaderChecked,
isHeaderIndeterminate,
checkboxMenuItems,
getRoomCheckboxTitle,
getHeaderMenu,
setSelected,
toggleInfoPanel,
isInfoPanelVisible,
]);
return (
<Consumer>
{(context) => (
<StyledContainer width={context.sectionWidth} viewAs={viewAs}>
{isHeaderVisible ? (
renderGroupMenu()
) : (
<div className="header-container">
<Navigation
sectionWidth={context.sectionWidth}
showText={showText}
isRootFolder={true}
canCreate={!isArchive}
title={title}
isDesktop={isDesktop}
isTabletView={isTabletView}
personal={false}
tReady={tReady}
navigationItems={navigationPath}
getContextOptionsPlus={getContextOptionsPlus}
getContextOptionsFolder={getContextOptionsFolder}
// toggleInfoPanel={toggleInfoPanel} TODO: return after adding info-panel for rooms
isInfoPanelVisible={isInfoPanelVisible}
/>
</div>
)}
</StyledContainer>
)}
</Consumer>
); );
}; };
export default inject(({ roomsStore, selectedFolderStore }) => { export default inject(
const { createRoom } = roomsStore; ({
auth,
roomsStore,
roomsActionsStore,
filesStore,
selectedFolderStore,
}) => {
const {
isHeaderVisible,
isHeaderChecked,
isHeaderIndeterminate,
checkboxMenuItems,
getRoomCheckboxTitle,
setSelected,
} = roomsStore;
return { createRoom, title: selectedFolderStore.title }; const { getHeaderMenu } = roomsActionsStore;
})(
const { viewAs } = filesStore;
const { toggleIsVisible, isVisible } = auth.infoPanelStore;
const { title, rootFolderType, navigationPath } = selectedFolderStore;
const isArchive = rootFolderType === FolderType.Archive;
return {
showText: auth.settingsStore.showText,
isDesktop: auth.settingsStore.isDesktopClient,
isTabletView: auth.settingsStore.isTabletView,
viewAs,
title,
isArchive,
navigationPath,
isHeaderVisible,
isHeaderChecked,
isHeaderIndeterminate,
checkboxMenuItems,
getRoomCheckboxTitle,
setSelected,
getHeaderMenu,
toggleInfoPanel: toggleIsVisible,
isInfoPanelVisible: isVisible,
};
}
)(
withTranslation([])( withTranslation([])(
withLoader(observer(SectionHeaderContent))(<Loaders.SectionHeader />) withLoader(observer(SectionHeaderContent))(<Loaders.SectionHeader />)
) )

View File

@ -1,5 +1,5 @@
import { makeAutoObservable, runInAction } from "mobx"; import { makeAutoObservable, runInAction } from "mobx";
import { AppServerConfig } from "@appserver/common/constants"; import { AppServerConfig, FolderType } from "@appserver/common/constants";
import toastr from "studio/toastr"; import toastr from "studio/toastr";
@ -62,8 +62,60 @@ class RoomsActionsStore {
} }
}; };
onSelectRoom = (id) => { getHeaderMenu = (t) => {
console.log(id); const { selection } = this.roomsStore;
if (selection.length === 0) return;
const pinOption =
selection.findIndex((room) => !room.pinned) > -1
? this.getOption("pin", t)
: this.getOption("unpin", t);
const archiveOption =
selection.findIndex((room) => room.rootFolderType === FolderType.Rooms) >
-1
? this.getOption("archive", t)
: this.getOption("unarchive", t);
return [pinOption, archiveOption];
};
getOption = (option, t) => {
switch (option) {
case "pin":
return {
key: "pin",
label: "Pin to top",
iconUrl: "/static/images/pin.react.svg",
onClick: () => console.log("pin"),
disabled: false,
};
case "unpin":
return {
key: "unpin",
label: "Unpin",
iconUrl: "/static/images/unpin.react.svg",
onClick: () => console.log("unpin"),
disabled: false,
};
case "archive":
return {
key: "archive",
label: "Move to archive",
iconUrl: "/static/images/room.archive.svg",
onClick: () => console.log("to archive"),
disabled: false,
};
case "unarchive":
return {
key: "unarchive",
label: "Move from archive",
iconUrl: "/static/images/room.archive.svg",
onClick: () => console.log("from archive"),
disabled: false,
};
}
}; };
onSelectTag = (tag) => { onSelectTag = (tag) => {

View File

@ -87,6 +87,10 @@ class RoomsStore {
this.bufferSelection = item; this.bufferSelection = item;
}; };
setHeaderVisible = (isHeaderVisible) => {
this.isHeaderVisible = isHeaderVisible;
};
sortRooms = (sortBy, sortOrder) => { sortRooms = (sortBy, sortOrder) => {
const newFilter = this.filter.clone(); const newFilter = this.filter.clone();
@ -181,6 +185,22 @@ class RoomsStore {
} }
}; };
setSelected = (selected) => {
if (selected === "none") {
this.setBufferSelection(null);
}
const newSelection = [];
this.rooms.forEach((room) => {
const checked = this.getRoomChecked(room, selected);
if (checked) newSelection.push(room);
});
this.selection = newSelection;
};
openContextMenu = (item) => { openContextMenu = (item) => {
if (this.selection.length > 0) return; if (this.selection.length > 0) return;
@ -256,6 +276,88 @@ class RoomsStore {
return request(); return request();
}; };
getRoomCheckboxTitle = (t, key) => {
switch (key) {
case "all":
return t("All");
case RoomsType.FillingFormsRoom:
return "Filling form rooms";
case RoomsType.CustomRoom:
return "Custom rooms";
case RoomsType.EditingRoom:
return "Editing rooms";
case RoomsType.ReviewRoom:
return "Review rooms";
case RoomsType.ReadOnlyRoom:
return "Read-only rooms";
default:
return "";
}
};
getRoomChecked = (room, selected) => {
const type = room.roomType;
switch (selected) {
case "all":
return true;
case RoomsType.FillingFormsRoom:
return type === RoomsType.FillingFormsRoom;
case RoomsType.CustomRoom:
return type === RoomsType.CustomRoom;
case RoomsType.EditingRoom:
return type === RoomsType.EditingRoom;
case RoomsType.ReviewRoom:
return type === RoomsType.ReviewRoom;
case RoomsType.ReadOnlyRoom:
return type === RoomsType.ReadOnlyRoom;
default:
return false;
}
};
get isHeaderVisible() {
return this.selection.length > 0;
}
get isHeaderIndeterminate() {
return this.isHeaderVisible && this.selection.length
? this.selection.length < this.rooms.length
: false;
}
get isHeaderChecked() {
return this.isHeaderVisible && this.selection.length === this.rooms.length;
}
get checkboxMenuItems() {
let cbMenu = ["all"];
for (const item of this.rooms) {
switch (item.roomType) {
case RoomsType.FillingFormsRoom:
cbMenu.push(RoomsType.FillingFormsRoom);
break;
case RoomsType.CustomRoom:
cbMenu.push(RoomsType.CustomRoom);
break;
case RoomsType.EditingRoom:
cbMenu.push(RoomsType.EditingRoom);
break;
case RoomsType.ReviewRoom:
cbMenu.push(RoomsType.ReviewRoom);
break;
case RoomsType.ReadOnlyRoom:
cbMenu.push(RoomsType.ReadOnlyRoom);
break;
}
}
cbMenu = cbMenu.filter((item, index) => cbMenu.indexOf(item) === index);
return cbMenu;
}
} }
export default RoomsStore; export default RoomsStore;