Web:Files:VirtualRooms: add group menu for virtual room pages
This commit is contained in:
parent
1bee56d3aa
commit
9bfb54bcc3
@ -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))()));
|
||||
|
@ -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 />)
|
||||
)
|
||||
|
@ -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) => {
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user