Web:Files:Rooms: update table view

This commit is contained in:
TimofeyBoyko 2022-06-28 13:25:05 +03:00
parent 1830b358f3
commit d9e9e28803
8 changed files with 422 additions and 69 deletions

View File

@ -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));

View File

@ -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>

View File

@ -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);

View File

@ -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>

View File

@ -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);

View File

@ -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>

View File

@ -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));

View File

@ -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>
);