added table group menu for tablet view

This commit is contained in:
Elyor Djalilov 2024-01-05 17:25:14 +05:00
parent 5204c566cd
commit 9f4f4e08ab
6 changed files with 238 additions and 136 deletions

View File

@ -4,7 +4,7 @@ import { inject, observer } from "mobx-react";
import TableHeader from "@docspace/components/table-container/TableHeader";
const TABLE_VERSION = "5";
const TABLE_COLUMNS = `GoogleWorkspaceColumns_ver-${TABLE_VERSION}`;
const TABLE_COLUMNS = `SessionsColumns_ver-${TABLE_VERSION}`;
const getColumns = (defaultColumns, userId) => {
const storageColumns = localStorage.getItem(`${TABLE_COLUMNS}=${userId}`);
@ -30,10 +30,10 @@ const SessionsTableHeader = (props) => {
t,
userId,
sectionWidth,
setHideColumns,
tableRef,
columnStorageName,
columnInfoPanelStorageName,
setHideColumns,
} = props;
const defaultColumns = [
@ -45,11 +45,6 @@ const SessionsTableHeader = (props) => {
default: true,
active: true,
minWidth: 180,
// checkbox: {
// value: isChecked,
// isIndeterminate,
// onChange: toggleAll,
// },
onChange: onColumnChange,
},
{
@ -76,7 +71,7 @@ const SessionsTableHeader = (props) => {
{
key: "IpAddress",
title: t("Common:IpAddress"),
enable: true,
enable: false,
resizable: true,
onChange: onColumnChange,
},
@ -84,6 +79,10 @@ const SessionsTableHeader = (props) => {
const [columns, setColumns] = useState(getColumns(defaultColumns, userId));
useEffect(() => {
setColumns(getColumns(defaultColumns));
}, []);
function onColumnChange(key, e) {
const columnIndex = columns.findIndex((c) => c.key === key);
@ -99,10 +98,6 @@ const SessionsTableHeader = (props) => {
localStorage.setItem(`${TABLE_COLUMNS}=${userId}`, tableColumns);
}
useEffect(() => {
setColumns(getColumns(defaultColumns));
}, []);
return (
<TableHeader
checkboxSize="48px"
@ -120,8 +115,4 @@ const SessionsTableHeader = (props) => {
);
};
export default inject(({ auth }) => {
return {
userId: auth.userStore.user.id,
};
})(observer(SessionsTableHeader));
export default SessionsTableHeader;

View File

@ -1,25 +1,45 @@
import { useRef } from "react";
import styled, { css } from "styled-components";
import TableRow from "@docspace/components/table-container/TableRow";
import TableCell from "@docspace/components/table-container/TableCell";
import Text from "@docspace/components/text";
import Avatar from "@docspace/components/avatar";
import Checkbox from "@docspace/components/checkbox";
import HistoryFinalizedReactSvgUrl from "PUBLIC_DIR/images/history-finalized.react.svg?url";
import RemoveSvgUrl from "PUBLIC_DIR/images/remove.session.svg?url";
import TrashReactSvgUrl from "PUBLIC_DIR/images/trash.react.svg?url";
import styled, { css } from "styled-components";
const StyledTableRow = styled(TableRow)`
.table-container_cell {
text-overflow: ellipsis;
}
.table-container_row-checkbox {
padding: 16px 8px 16px 12px;
}
.avatar {
${(props) =>
props.theme.interfaceDirection === "rtl"
? css`
margin-left: 6px;
margin-left: 8px;
`
: css`
margin-right: 6px;
margin-right: 8px;
`}
}
.session-info {
font-weight: 600;
color: #a3a9ae;
}
.session-online {
font-weight: 600;
color: #35ad17;
}
`;
const SessionsTableRow = ({
@ -33,9 +53,12 @@ const SessionsTableRow = ({
country,
city,
ip,
userId,
hideColumns,
isChecked,
toggleSession,
}) => {
const tableRef = useRef();
const contextOptions = [
{
key: "ViewSessions",
@ -61,39 +84,69 @@ const SessionsTableRow = ({
},
];
const handleSessionToggle = (e) => {
e.preventDefault();
e.stopPropagation();
tableRef.current?.contains(e.target) || toggleSession(e);
};
const isOnline = status === "Online";
return (
<StyledTableRow
onClick={() => console.log("selected row")}
contextOptions={contextOptions}
hideColumns={hideColumns}
contextOptions={contextOptions}
checked={isChecked}
onClick={handleSessionToggle}
>
<TableCell>
<Avatar
className="avatar"
userName={displayName}
role={role}
source={avatar}
size={"small"}
<TableCell hasAccess={true}>
<div className="table-container_element">
<Avatar
className="avatar"
userName={displayName}
role={role}
source={avatar}
size={"small"}
/>
</div>
<Checkbox
className="table-container_row-checkbox"
isChecked={isChecked}
onChange={handleSessionToggle}
/>
<Text>{displayName}</Text>
<Text fontWeight="600">{displayName}</Text>
</TableCell>
<TableCell>
<Text>{status}</Text>
<Text className={isOnline ? "session-online" : "session-info"} truncate>
{status}
</Text>
</TableCell>
<TableCell>
<Text>{platform},&nbsp;</Text>
<Text>{browser}</Text>
<Text className="session-info" truncate>
{platform},&nbsp;
</Text>
<Text className="session-info" truncate>
{browser}
</Text>
</TableCell>
<TableCell>
<Text>{country},&nbsp;</Text>
<Text>{city}</Text>
<Text className="session-info" truncate>
{country},&nbsp;
</Text>
<Text className="session-info" truncate>
{city}
</Text>
</TableCell>
<TableCell>
<Text>{ip}</Text>
<Text className="session-info" truncate>
{ip}
</Text>
</TableCell>
</StyledTableRow>
);

View File

@ -5,13 +5,47 @@ import styled, { css } from "styled-components";
import SessionsTableHeader from "./SessionsTableHeader";
import SessionsTableRow from "./SessionsTableRow";
import HistoryFinalizedReactSvgUrl from "PUBLIC_DIR/images/history-finalized.react.svg?url";
import RemoveSvgUrl from "PUBLIC_DIR/images/remove.session.svg?url";
import TrashReactSvgUrl from "PUBLIC_DIR/images/trash.react.svg?url";
import TableContainer from "@docspace/components/table-container/TableContainer";
import TableGroupMenu from "@docspace/components/table-container/TableGroupMenu";
import TableBody from "@docspace/components/table-container/TableBody";
const StyledTableContainer = styled(TableContainer)`
margin: 0 0 24px;
.table-group-menu {
height: 69px;
position: absolute;
z-index: 201;
top: 0;
left: 0px;
width: 100%;
.table-container_group-menu {
border-image-slice: 0;
border-image-source: none;
border-bottom: ${(props) =>
props.theme.filesSection.tableView.row.borderColor};
box-shadow: rgba(4, 15, 27, 0.07) 0px 15px 20px;
padding: 0px;
}
.table-container_group-menu-separator {
margin: 0 16px;
}
}
.table-container_header {
position: absolute;
padding: 0px 20px;
}
.header-container-text {
color: #a3a9ae;
font-size: ${(props) => props.theme.getCorrectFontSize("12px")};
}
@ -59,30 +93,91 @@ const StyledTableContainer = styled(TableContainer)`
StyledTableContainer.defaultProps = { theme: Base };
const TABLE_VERSION = "6";
const TABLE_VERSION = "5";
const COLUMNS_SIZE = `sessionsColumnsSize_ver-${TABLE_VERSION}`;
const INFO_PANEL_COLUMNS_SIZE = `infoPanelSessionsColumnsSize_ver-${TABLE_VERSION}`;
const TableView = ({ t, sectionWidth, userId, sessionsData }) => {
const TableView = ({
t,
sectionWidth,
userId,
sessionsData,
allSessions,
checkedSessions,
toggleSession,
toggleAllSessions,
isSessionChecked,
}) => {
const [hideColumns, setHideColumns] = useState(false);
const tableRef = useRef(null);
const handleToggle = (e, id) => {
e.stopPropagation();
toggleSession(id);
};
const handleAllToggles = (checked) => {
toggleAllSessions(checked, allSessions);
};
const columnStorageName = `${COLUMNS_SIZE}=${userId}`;
const columnInfoPanelStorageName = `${INFO_PANEL_COLUMNS_SIZE}=${userId}`;
const headerMenu = [
{
id: "sessions",
key: "Sessions",
label: t("Common:Sessions"),
onClick: () => console.log("Sessions"),
iconUrl: HistoryFinalizedReactSvgUrl,
},
{
id: "logout",
key: "Logout",
label: t("Common:Logout"),
onClick: () => console.log("Logout"),
iconUrl: RemoveSvgUrl,
},
{
id: "Disable",
key: "Disable",
label: t("Common:DisableUserButton"),
onClick: () => console.log("Disable"),
iconUrl: TrashReactSvgUrl,
},
];
const isChecked = checkedSessions.length === allSessions.length;
const isIndeterminate =
checkedSessions.length > 0 && checkedSessions.length !== allSessions.length;
return (
<StyledTableContainer forwardedRef={tableRef} useReactWindow>
{checkedSessions.length > 0 && (
<div className="table-group-menu">
<TableGroupMenu
sectionWidth={sectionWidth}
headerMenu={headerMenu}
withoutInfoPanelToggler
withComboBox={false}
checkboxOptions={[]}
isChecked={isChecked}
isIndeterminate={isIndeterminate}
onChange={handleAllToggles}
/>
</div>
)}
<SessionsTableHeader
t={t}
sectionWidth={sectionWidth}
tableRef={tableRef}
setHideColumns={setHideColumns}
userId={userId}
tableRef={tableRef}
columnStorageName={columnStorageName}
columnInfoPanelStorageName={columnInfoPanelStorageName}
setHideColumns={setHideColumns}
// isIndeterminate={isIndeterminate}
// isChecked={checkedUsers.withEmail.length === withEmailUsers.length}
// toggleAll={toggleAll}
isChecked={isChecked}
isIndeterminate={isIndeterminate}
/>
<TableBody
itemHeight={49}
@ -98,7 +193,7 @@ const TableView = ({ t, sectionWidth, userId, sessionsData }) => {
{sessionsData.map((session) => (
<SessionsTableRow
t={t}
key={session.id}
key={session.userId}
avatar={session.avatar}
displayName={session.displayName}
status={session.status}
@ -107,10 +202,9 @@ const TableView = ({ t, sectionWidth, userId, sessionsData }) => {
country={session.country}
city={session.city}
ip={session.ip}
userId={session.userId}
hideColumns={hideColumns}
// isChecked={isAccountChecked(data.key, checkedAccountType)}
// toggleAccount={(e) => handleToggle(e, data)}
isChecked={isSessionChecked(session.userId)}
toggleSession={(e) => handleToggle(e, session.userId)}
/>
))}
</TableBody>
@ -118,10 +212,22 @@ const TableView = ({ t, sectionWidth, userId, sessionsData }) => {
);
};
export default inject(({ auth }) => {
export default inject(({ auth, setup }) => {
const { id: userId } = auth.userStore.user;
const {
allSessions,
checkedSessions,
toggleSession,
toggleAllSessions,
isSessionChecked,
} = setup;
return {
userId,
allSessions,
checkedSessions,
toggleSession,
toggleAllSessions,
isSessionChecked,
};
})(observer(TableView));

View File

@ -1,82 +0,0 @@
const allSessionsData = [
{
id: 1,
avatar: "",
displayName: "Ilya Genkin",
status: "Online",
platform: "Windows 10",
browser: "Chrome 120",
country: "Russia",
city: "Kstovo",
date: "2023-12-26T17:13:28+00:00",
ip: "172.18.0.1",
mobile: false,
page: "http://192.168.0.239/wizard",
tenantId: 1,
userId: "66faa6e4-f133-11ea-b126-00ffeec8b4ef",
},
{
id: 2,
avatar: "",
displayName: "Timur Aliev",
status: "Online",
platform: "Mac OS 14.1.2",
browser: "Safari 17",
country: "Uzbekistan",
city: "Tashkent",
date: "2023-12-26T17:13:28+00:00",
ip: "172.19.0.1",
mobile: false,
page: "http://192.168.0.239/wizard",
tenantId: 1,
userId: "66faa6e4-f133-11ea-b126-00ffeec8b4ea",
},
{
id: 3,
avatar: "",
displayName: "Aleksei Safronov",
status: "8 minutes ago",
platform: "Windows 10",
browser: "Chrome 119",
country: "Armenia",
city: "Yerevan",
date: "2023-12-26T17:13:28+00:00",
ip: "172.20.0.1",
mobile: false,
page: "http://192.168.0.239/wizard",
tenantId: 1,
userId: "66faa6e4-f133-11ea-b126-00ffeec8b4eb",
},
{
id: 4,
displayName: "Dmitry Vanyukov",
status: "3 hours ago",
platform: "Mac OS 14.1.2",
browser: "Safari 15",
country: "Russia",
city: "Kuznechikha",
date: "2023-12-26T17:13:28+00:00",
ip: "172.21.0.1",
mobile: false,
page: "http://192.168.0.239/wizard",
tenantId: 1,
userId: "66faa6e4-f133-11ea-b126-00ffeec8b4ec",
},
{
id: 5,
displayName: "Elizabeth Rayen",
status: "Yesterday, 5:12 PM",
platform: "Mac OS X 10",
browser: "Chrome 119",
country: "Germany",
city: " Frankfurt",
date: "2023-12-26T17:13:28+00:00",
ip: "172.22.0.1",
mobile: false,
page: "http://192.168.0.239/wizard",
tenantId: 1,
userId: "66faa6e4-f133-11ea-b126-00ffeec8b4ed",
},
];
export default allSessionsData;

View File

@ -1,11 +1,13 @@
import { useEffect } from "react";
import { withTranslation } from "react-i18next";
import { inject, observer } from "mobx-react";
import { mobile, tablet } from "@docspace/components/utils/device";
import styled from "styled-components";
import { MainContainer } from "../StyledSecurity";
import useViewEffect from "SRC_DIR/Hooks/useViewEffect";
import SessionsTable from "./SessionsTable";
import allSessionsData from "./allSessionsData";
import styled from "styled-components";
import mockData from "./mockData";
import Text from "@docspace/components/text";
import Button from "@docspace/components/button";
@ -69,8 +71,14 @@ const Sessions = ({
viewAs,
setViewAs,
currentDeviceType,
allSessions,
setAllSessions,
isLoadingDownloadReport,
}) => {
useEffect(() => {
setAllSessions(mockData);
}, []);
useViewEffect({
view: viewAs,
setView: setViewAs,
@ -81,7 +89,7 @@ const Sessions = ({
<MainContainer>
<Text className="subtitle">{t("SessionsSubtitle")}</Text>
<SessionsTable t={t} sessionsData={allSessionsData} />
<SessionsTable t={t} sessionsData={allSessions} />
<DownLoadWrapper>
<Button
@ -104,14 +112,22 @@ const Sessions = ({
export default inject(({ auth, setup }) => {
const { culture, currentDeviceType } = auth.settingsStore;
const { user } = auth.userStore;
const { viewAs, setViewAs, isLoadingDownloadReport } = setup;
const locale = (user && user.cultureName) || culture || "en";
const {
viewAs,
setViewAs,
allSessions,
setAllSessions,
isLoadingDownloadReport,
} = setup;
return {
locale,
viewAs,
setViewAs,
currentDeviceType,
allSessions,
setAllSessions,
isLoadingDownloadReport,
};
})(withTranslation(["Settings", "Common"])(observer(Sessions)));

View File

@ -78,6 +78,8 @@ class SettingsSetupStore {
securityLifetime = [];
sessionsIsInit = false;
allSessions = [];
checkedSessions = [];
sessions = [];
currentSession = [];
@ -182,6 +184,22 @@ class SettingsSetupStore {
this.integration.consumers = consumers;
};
setAllSessions = (sessions) => {
this.allSessions = sessions;
};
toggleSession = (id) => {
this.checkedSessions = this.checkedSessions.includes(id)
? this.checkedSessions.filter((itemId) => itemId !== id)
: [...this.checkedSessions, id];
};
toggleAllSessions = (checked, sessions) => {
this.checkedSessions = checked ? sessions.map((data) => data.userId) : [];
};
isSessionChecked = (userId) => this.checkedSessions.includes(userId);
get isSMTPInitialSettings() {
const settings = this.integration.smtpSettings.settings;
const initialSettings = this.integration.smtpSettings.initialSettings;