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";
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 (
<Consumer>
{(context) =>
@ -34,9 +64,9 @@ const SectionBodyContent = ({ isEmpty, viewAs }) => {
export default inject(({ filesStore, roomsStore }) => {
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))()));

View File

@ -1,60 +1,213 @@
import React from "react";
import styled from "styled-components";
import styled, { css } from "styled-components";
import { inject, observer } from "mobx-react";
import { withTranslation } from "react-i18next";
import { isMobile } from "react-device-detect";
import { tablet } from "@appserver/components/utils/device";
import Headline from "@appserver/common/components/Headline";
import IconButton from "@appserver/components/icon-button";
import withLoader from "../../../../HOCs/withLoader";
import Navigation from "@appserver/common/components/Navigation";
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`
width: 100%;
height: 53px;
display: flex;
align-items: center;
`;
.table-container_group-menu {
${(props) =>
props.viewAs === "table"
? css`
margin: 0px -20px;
width: calc(100% + 40px);
`
: css`
margin: 0px -20px;
width: calc(100% + 40px);
`}
const StyledHeadline = styled(Headline)`
font-weight: 700;
font-size: ${isMobile ? "21px !important" : "18px"};
line-height: ${isMobile ? "28px !important" : "24px"};
@media ${tablet} {
margin: 0 -16px;
width: calc(100% + 32px);
}
margin-right: 16px;
@media ${tablet} {
font-size: 21px;
line-height: 28px;
${isMobile &&
css`
margin: 0 -16px;
width: calc(100% + 32px);
`}
}
`;
const SectionHeaderContent = ({ createRoom, title }) => {
return (
<StyledContainer>
<StyledHeadline>{title}</StyledHeadline>
<IconButton
zIndex={402}
className="create-button"
directionX="right"
iconName="images/plus.svg"
size={15}
isFill
onClick={createRoom}
isDisabled={false}
const SectionHeaderContent = ({
t,
createRoom,
viewAs,
title,
showText,
isArchive,
isDesktop,
isTabletView,
tReady,
navigationPath,
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 }) => {
const { createRoom } = roomsStore;
export default inject(
({
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([])(
withLoader(observer(SectionHeaderContent))(<Loaders.SectionHeader />)
)

View File

@ -1,5 +1,5 @@
import { makeAutoObservable, runInAction } from "mobx";
import { AppServerConfig } from "@appserver/common/constants";
import { AppServerConfig, FolderType } from "@appserver/common/constants";
import toastr from "studio/toastr";
@ -62,8 +62,60 @@ class RoomsActionsStore {
}
};
onSelectRoom = (id) => {
console.log(id);
getHeaderMenu = (t) => {
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) => {

View File

@ -87,6 +87,10 @@ class RoomsStore {
this.bufferSelection = item;
};
setHeaderVisible = (isHeaderVisible) => {
this.isHeaderVisible = isHeaderVisible;
};
sortRooms = (sortBy, sortOrder) => {
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) => {
if (this.selection.length > 0) return;
@ -256,6 +276,88 @@ class RoomsStore {
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;