Web:Files:Rooms: update table view
This commit is contained in:
parent
1830b358f3
commit
d9e9e28803
@ -1,4 +1,5 @@
|
||||
import React from "react";
|
||||
import styled, { css } from "styled-components";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import elementResizeDetectorMaker from "element-resize-detector";
|
||||
|
||||
@ -9,6 +10,7 @@ import TableBody from "@appserver/components/table-container/TableBody";
|
||||
|
||||
import TableHeaderContent from "./sub-components/TableHeader";
|
||||
import Row from "./sub-components/TableRow";
|
||||
import { Base } from "@appserver/components/themes";
|
||||
|
||||
const TABLE_VERSION = "1";
|
||||
const TABLE_COLUMNS = `roomsTableColumns_ver-${TABLE_VERSION}`;
|
||||
@ -17,11 +19,76 @@ const COLUMNS_SIZE = `roomsColumnsSize_ver-${TABLE_VERSION}`;
|
||||
const tagMaxWidth = 100;
|
||||
const gridGap = 4;
|
||||
|
||||
const marginCss = css`
|
||||
margin-top: -1px;
|
||||
border-top: ${(props) =>
|
||||
`1px solid ${props.theme.filesSection.tableView.row.borderColor}`};
|
||||
`;
|
||||
|
||||
const fileNameCss = css`
|
||||
margin-left: -24px;
|
||||
padding-left: 24px;
|
||||
${marginCss}
|
||||
`;
|
||||
|
||||
const contextCss = css`
|
||||
margin-right: -20px;
|
||||
padding-right: 18px;
|
||||
${marginCss}
|
||||
`;
|
||||
|
||||
const StyledTableContainer = styled(TableContainer)`
|
||||
.table-row-selected {
|
||||
.room-name_cell {
|
||||
${fileNameCss}
|
||||
}
|
||||
|
||||
.table-container_row-context-menu-wrapper {
|
||||
${contextCss}
|
||||
}
|
||||
|
||||
.table-container_cell {
|
||||
cursor: pointer;
|
||||
background: ${(props) =>
|
||||
`${props.theme.filesSection.tableView.row.backgroundActive} !important`};
|
||||
|
||||
margin-top: -1px;
|
||||
border-top: ${(props) =>
|
||||
`1px solid ${props.theme.filesSection.tableView.row.borderColor}`};
|
||||
}
|
||||
}
|
||||
|
||||
.table-row-selected + .table-row-selected {
|
||||
.room-name_cell,
|
||||
.table-container_row-context-menu-wrapper {
|
||||
margin-top: -1px;
|
||||
border-image-slice: 1;
|
||||
border-top: 1px solid;
|
||||
}
|
||||
.room-name_cell {
|
||||
${fileNameCss}
|
||||
border-left: 0; //for Safari macOS
|
||||
border-right: 0; //for Safari macOS
|
||||
|
||||
border-image-source: ${(props) => `linear-gradient(to right,
|
||||
${props.theme.filesSection.tableView.row.borderColorTransition} 17px, ${props.theme.filesSection.tableView.row.borderColor} 31px)`};
|
||||
}
|
||||
.table-container_row-context-menu-wrapper {
|
||||
${contextCss}
|
||||
|
||||
border-image-source: ${(props) => `linear-gradient(to left,
|
||||
${props.theme.filesSection.tableView.row.borderColorTransition} 17px, ${props.theme.filesSection.tableView.row.borderColor} 31px)`};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
StyledTableContainer.defaultProps = { theme: Base };
|
||||
|
||||
const VirtualRoomsTable = ({
|
||||
viewAs,
|
||||
setViewAs,
|
||||
userId,
|
||||
data,
|
||||
rooms,
|
||||
sectionWidth,
|
||||
theme,
|
||||
getRoomsContextOptions,
|
||||
@ -58,7 +125,7 @@ const VirtualRoomsTable = ({
|
||||
|
||||
elementResizeDetector.uninstall(firstRowRef.current);
|
||||
};
|
||||
}, [firstRowRef, data]);
|
||||
}, [firstRowRef, rooms]);
|
||||
|
||||
const onResize = React.useCallback(() => {
|
||||
if (firstRowRef?.current) {
|
||||
@ -76,7 +143,7 @@ const VirtualRoomsTable = ({
|
||||
const columnStorageName = `${COLUMNS_SIZE}=${userId}`;
|
||||
|
||||
return (
|
||||
<TableContainer forwardedRef={containerRef}>
|
||||
<StyledTableContainer forwardedRef={containerRef}>
|
||||
<TableHeaderContent
|
||||
sectionWidth={sectionWidth}
|
||||
containerRef={containerRef}
|
||||
@ -84,10 +151,10 @@ const VirtualRoomsTable = ({
|
||||
columnStorageName={columnStorageName}
|
||||
/>
|
||||
<TableBody>
|
||||
{data.map((item, index) =>
|
||||
{rooms.map((item, index) =>
|
||||
index === 0 ? (
|
||||
<Row
|
||||
key={item.key}
|
||||
key={item.id}
|
||||
item={item}
|
||||
theme={theme}
|
||||
ref={firstRowRef}
|
||||
@ -96,7 +163,7 @@ const VirtualRoomsTable = ({
|
||||
/>
|
||||
) : (
|
||||
<Row
|
||||
key={item.key}
|
||||
key={item.id}
|
||||
item={item}
|
||||
theme={theme}
|
||||
tagCount={tagCount}
|
||||
@ -105,24 +172,29 @@ const VirtualRoomsTable = ({
|
||||
)
|
||||
)}
|
||||
</TableBody>
|
||||
</TableContainer>
|
||||
</StyledTableContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ auth, filesStore, contextOptionsStore }) => {
|
||||
const { settingsStore } = auth;
|
||||
export default inject(
|
||||
({ auth, filesStore, roomsStore, contextOptionsStore }) => {
|
||||
const { settingsStore } = auth;
|
||||
|
||||
const { theme } = settingsStore;
|
||||
const { theme } = settingsStore;
|
||||
|
||||
const { viewAs, setViewAs } = filesStore;
|
||||
const { viewAs, setViewAs } = filesStore;
|
||||
|
||||
const { getRoomsContextOptions } = contextOptionsStore;
|
||||
const { getRoomsContextOptions } = contextOptionsStore;
|
||||
|
||||
return {
|
||||
theme,
|
||||
viewAs,
|
||||
setViewAs,
|
||||
getRoomsContextOptions,
|
||||
userId: auth.userStore.user.id,
|
||||
};
|
||||
})(observer(VirtualRoomsTable));
|
||||
const { rooms } = roomsStore;
|
||||
|
||||
return {
|
||||
theme,
|
||||
viewAs,
|
||||
setViewAs,
|
||||
getRoomsContextOptions,
|
||||
userId: auth.userStore.user.id,
|
||||
rooms,
|
||||
};
|
||||
}
|
||||
)(observer(VirtualRoomsTable));
|
||||
|
@ -8,7 +8,13 @@ import Text from "@appserver/components/text";
|
||||
const DateCell = ({ sideColor }) => {
|
||||
return (
|
||||
<TableCell className="table-container_element-wrapper">
|
||||
<Text isBold={true} truncate={true} noSelect={true} color={sideColor}>
|
||||
<Text
|
||||
fontWeight={600}
|
||||
fontSize={"11px"}
|
||||
truncate={true}
|
||||
noSelect={true}
|
||||
color={sideColor}
|
||||
>
|
||||
05.06.2022
|
||||
</Text>
|
||||
</TableCell>
|
||||
|
@ -1,28 +0,0 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
import TableCell from "@appserver/components/table-container/TableCell";
|
||||
import RoomLogo from "@appserver/components/room-logo";
|
||||
import Text from "@appserver/components/text";
|
||||
|
||||
const StyledText = styled(Text)`
|
||||
margin-left: 8px;
|
||||
`;
|
||||
|
||||
const FileNameCell = ({ label, type, isPrivacy, theme }) => {
|
||||
return (
|
||||
<TableCell className="table-container_element-wrapper">
|
||||
<RoomLogo type={type} isPrivacy={isPrivacy} />
|
||||
<StyledText
|
||||
isBold={true}
|
||||
truncate={true}
|
||||
noSelect={true}
|
||||
color={theme.filesSection.tableView.fileName.linkColor}
|
||||
>
|
||||
{label}
|
||||
</StyledText>
|
||||
</TableCell>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(FileNameCell);
|
@ -18,13 +18,23 @@ const StyledOwnerCell = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
const OwnerCell = ({ sideColor }) => {
|
||||
const OwnerCell = ({ owner, isMe, sideColor }) => {
|
||||
return (
|
||||
<TableCell>
|
||||
<StyledOwnerCell>
|
||||
<Avatar className="author-avatar-cell" role="user" />
|
||||
<Text color={sideColor} fontSize="12px" fontWeight={400} truncate>
|
||||
Me
|
||||
<Avatar
|
||||
className="author-avatar-cell"
|
||||
role="user"
|
||||
source={owner.avatarSmall}
|
||||
/>
|
||||
<Text
|
||||
color={sideColor}
|
||||
fontWeight={600}
|
||||
fontSize={"11px"}
|
||||
noSelect={true}
|
||||
truncate
|
||||
>
|
||||
{isMe ? "Me" : owner.displayName}
|
||||
</Text>
|
||||
</StyledOwnerCell>
|
||||
</TableCell>
|
||||
|
@ -0,0 +1,77 @@
|
||||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import { ReactSVG } from "react-svg";
|
||||
|
||||
import TableCell from "@appserver/components/table-container/TableCell";
|
||||
import RoomLogo from "@appserver/components/room-logo";
|
||||
import Text from "@appserver/components/text";
|
||||
import Checkbox from "@appserver/components/checkbox";
|
||||
import Badge from "@appserver/components/badge";
|
||||
|
||||
const StyledText = styled(Text)`
|
||||
margin: 0 8px;
|
||||
`;
|
||||
|
||||
const StyledPinIcon = styled(ReactSVG)`
|
||||
margin-right: 8px;
|
||||
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
`;
|
||||
|
||||
const FileNameCell = ({
|
||||
label,
|
||||
type,
|
||||
isPrivacy,
|
||||
isChecked,
|
||||
theme,
|
||||
pinned,
|
||||
badgeLabel,
|
||||
onRoomSelect,
|
||||
onClickUnpinRoom,
|
||||
onBadgeClick,
|
||||
}) => {
|
||||
return (
|
||||
<TableCell className="table-container_element-wrapper room-name_cell">
|
||||
<div className="room-name__logo-container">
|
||||
<RoomLogo
|
||||
className={"room-name_logo"}
|
||||
type={type}
|
||||
isPrivacy={isPrivacy}
|
||||
/>
|
||||
|
||||
<Checkbox
|
||||
className={"room-name_checkbox checkbox"}
|
||||
isChecked={isChecked}
|
||||
isIndeterminate={false}
|
||||
onChange={onRoomSelect}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<StyledText
|
||||
isBold={true}
|
||||
truncate={true}
|
||||
noSelect={true}
|
||||
color={theme.filesSection.tableView.fileName.linkColor}
|
||||
>
|
||||
{label}
|
||||
</StyledText>
|
||||
{pinned && (
|
||||
<StyledPinIcon
|
||||
className="room-name_pin-icon"
|
||||
onClick={onClickUnpinRoom}
|
||||
src="images/unpin.react.svg"
|
||||
/>
|
||||
)}
|
||||
<Badge
|
||||
className="room-name_badge"
|
||||
label={badgeLabel}
|
||||
lineHeight={"12px"}
|
||||
fontSize={"9px"}
|
||||
onClick={onBadgeClick}
|
||||
/>
|
||||
</TableCell>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(FileNameCell);
|
@ -8,7 +8,13 @@ import Text from "@appserver/components/text";
|
||||
const DateCell = ({ sideColor }) => {
|
||||
return (
|
||||
<TableCell className="table-container_element-wrapper">
|
||||
<Text isBold={true} truncate={true} noSelect={true} color={sideColor}>
|
||||
<Text
|
||||
fontWeight={600}
|
||||
fontSize={"11px"}
|
||||
truncate={true}
|
||||
noSelect={true}
|
||||
color={sideColor}
|
||||
>
|
||||
50kb
|
||||
</Text>
|
||||
</TableCell>
|
||||
|
@ -1,41 +1,218 @@
|
||||
import React from "react";
|
||||
import styled, { css } from "styled-components";
|
||||
import { inject, observer } from "mobx-react";
|
||||
|
||||
import TableRow from "@appserver/components/table-container/TableRow";
|
||||
import TableCell from "@appserver/components/table-container/TableCell";
|
||||
|
||||
import FileNameCell from "./FileNameCell";
|
||||
import FileNameCell from "./RoomNameCell";
|
||||
import TypeCell from "./TypeCell";
|
||||
import OwnerCell from "./OwnerCell";
|
||||
import DateCell from "./DateCell";
|
||||
import SizeCell from "./SizeCell";
|
||||
import TagsCell from "./TagsCell";
|
||||
|
||||
const StyledTableRow = styled(TableRow)`
|
||||
.room-name_cell {
|
||||
.room-name__logo-container {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.room-name_logo {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.room-name_checkbox {
|
||||
display: none;
|
||||
|
||||
.checkbox {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table-container_cell {
|
||||
height: 48px;
|
||||
max-height: 48px;
|
||||
min-height: 48px;
|
||||
|
||||
background: ${(props) =>
|
||||
(props.isChecked || props.isHover) &&
|
||||
`${props.theme.filesSection.tableView.row.backgroundActive} !important`};
|
||||
cursor: ${(props) =>
|
||||
(props.isChecked || props.isHover) &&
|
||||
"url(/static/images/cursor.palm.react.svg), auto"};
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.room-name_cell {
|
||||
margin-left: -24px;
|
||||
padding-left: 24px;
|
||||
.room-name__logo-container {
|
||||
.room-name_logo {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.room-name_checkbox {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table-container_row-context-menu-wrapper {
|
||||
margin-right: -20px;
|
||||
padding-right: 18px;
|
||||
}
|
||||
|
||||
.table-container_cell {
|
||||
cursor: pointer;
|
||||
background: ${(props) =>
|
||||
`${props.theme.filesSection.tableView.row.backgroundActive} !important`};
|
||||
|
||||
margin-top: -1px;
|
||||
border-top: ${(props) =>
|
||||
`1px solid ${props.theme.filesSection.tableView.row.borderColor}`};
|
||||
}
|
||||
}
|
||||
|
||||
${(props) =>
|
||||
(props.isHover || props.isChecked) &&
|
||||
css`
|
||||
.room-name_cell {
|
||||
.room-name__logo-container {
|
||||
.room-name_logo {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.room-name_checkbox {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
const Row = React.forwardRef(
|
||||
({ item, tagCount, theme, getContextModel }, ref) => {
|
||||
(
|
||||
{
|
||||
item,
|
||||
tagCount,
|
||||
theme,
|
||||
|
||||
isChecked,
|
||||
isHover,
|
||||
isMe,
|
||||
|
||||
getRoomsContextOptions,
|
||||
selectRoom,
|
||||
openContextMenu,
|
||||
closeContextMenu,
|
||||
unpinRoom,
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
const onContextMenu = React.useCallback(
|
||||
(e) => {
|
||||
openContextMenu && openContextMenu(item);
|
||||
},
|
||||
[openContextMenu, item]
|
||||
);
|
||||
|
||||
const onCloseContextMenu = React.useCallback(() => {
|
||||
closeContextMenu && closeContextMenu(item);
|
||||
}, [item, closeContextMenu]);
|
||||
|
||||
const onRoomSelect = React.useCallback(
|
||||
(e) => {
|
||||
selectRoom && selectRoom(e.target.checked, item);
|
||||
},
|
||||
[selectRoom, item]
|
||||
);
|
||||
|
||||
const getRoomsContextOptionsActions = React.useCallback(() => {
|
||||
return getRoomsContextOptions && getRoomsContextOptions(item);
|
||||
}, [getRoomsContextOptions, item]);
|
||||
|
||||
const onClickUnpinRoomAction = React.useCallback(() => {
|
||||
unpinRoom && unpinRoom(item);
|
||||
}, [item, unpinRoom]);
|
||||
|
||||
const onBadgeClick = React.useCallback(() => {
|
||||
console.log("on badge click");
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<TableRow
|
||||
className="table-row"
|
||||
key={item.key}
|
||||
contextOptions={getContextModel()}
|
||||
getContextModel={getContextModel}
|
||||
<StyledTableRow
|
||||
className={`table-row${
|
||||
isHover || isChecked ? " table-row-selected" : ""
|
||||
}`}
|
||||
key={item.id}
|
||||
contextOptions={getRoomsContextOptionsActions()}
|
||||
getContextModel={getRoomsContextOptionsActions}
|
||||
fileContextClick={onContextMenu}
|
||||
onHideContextMenu={onCloseContextMenu}
|
||||
isChecked={isChecked}
|
||||
isHover={isHover}
|
||||
>
|
||||
<FileNameCell
|
||||
theme={theme}
|
||||
label={item.label}
|
||||
type={item.type}
|
||||
label={item.title}
|
||||
type={item.roomType}
|
||||
isPrivacy={item.isPrivacy}
|
||||
isChecked={isChecked}
|
||||
pinned={item.pinned}
|
||||
badgeLabel={item.new}
|
||||
onRoomSelect={onRoomSelect}
|
||||
onClickUnpinRoom={onClickUnpinRoomAction}
|
||||
onBadgeClick={onBadgeClick}
|
||||
/>
|
||||
<TypeCell
|
||||
type={item.type}
|
||||
type={item.roomType}
|
||||
sideColor={theme.filesSection.tableView.row.sideColor}
|
||||
/>
|
||||
<TagsCell ref={ref} tags={item.tags} tagCount={tagCount} />
|
||||
<OwnerCell sideColor={theme.filesSection.tableView.row.sideColor} />
|
||||
<OwnerCell
|
||||
owner={item.createdBy}
|
||||
isMe={isMe}
|
||||
sideColor={theme.filesSection.tableView.row.sideColor}
|
||||
/>
|
||||
<DateCell sideColor={theme.filesSection.tableView.row.sideColor} />
|
||||
<SizeCell sideColor={theme.filesSection.tableView.row.sideColor} />
|
||||
</TableRow>
|
||||
</StyledTableRow>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default Row;
|
||||
export default inject(({ auth, contextOptionsStore, roomsStore }, { item }) => {
|
||||
const { getRoomsContextOptions } = contextOptionsStore;
|
||||
|
||||
const {
|
||||
selection,
|
||||
bufferSelection,
|
||||
selectRoom,
|
||||
openContextMenu,
|
||||
closeContextMenu,
|
||||
unpinRoom,
|
||||
} = roomsStore;
|
||||
|
||||
const isChecked = !!selection.find((room) => room.id === item.id);
|
||||
const isHover = !isChecked && bufferSelection?.id === item.id;
|
||||
const isMe = item.createdBy.id === auth.userStore.user.id;
|
||||
|
||||
return {
|
||||
isChecked,
|
||||
isHover,
|
||||
isMe,
|
||||
|
||||
getRoomsContextOptions,
|
||||
selectRoom,
|
||||
openContextMenu,
|
||||
closeContextMenu,
|
||||
unpinRoom,
|
||||
};
|
||||
})(observer(Row));
|
||||
|
@ -5,11 +5,44 @@ import TableCell from "@appserver/components/table-container/TableCell";
|
||||
|
||||
import Text from "@appserver/components/text";
|
||||
|
||||
import { RoomsType } from "@appserver/common/constants";
|
||||
|
||||
const TypeCell = ({ type, sideColor }) => {
|
||||
const [typeName, setTypeName] = React.useState("");
|
||||
|
||||
React.useEffect(() => {
|
||||
let title = "";
|
||||
switch (type) {
|
||||
case RoomsType.FillingFormsRoom:
|
||||
title = "Filling form";
|
||||
break;
|
||||
case RoomsType.EditingRoom:
|
||||
title = "Collaboration";
|
||||
break;
|
||||
case RoomsType.ReviewRoom:
|
||||
title = "Review";
|
||||
break;
|
||||
case RoomsType.ReadOnlyRoom:
|
||||
title = "View-only";
|
||||
break;
|
||||
case RoomsType.CustomRoom:
|
||||
title = "Custom";
|
||||
break;
|
||||
}
|
||||
|
||||
setTypeName(title);
|
||||
}, [type]);
|
||||
|
||||
return (
|
||||
<TableCell className="table-container_element-wrapper">
|
||||
<Text isBold={true} truncate={true} noSelect={true} color={sideColor}>
|
||||
{type}
|
||||
<Text
|
||||
fontWeight={600}
|
||||
fontSize={"11px"}
|
||||
truncate={true}
|
||||
noSelect={true}
|
||||
color={sideColor}
|
||||
>
|
||||
{typeName}
|
||||
</Text>
|
||||
</TableCell>
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user