Web: Client: Profile. rewrited table view active sessions
This commit is contained in:
parent
579ab4130d
commit
89e29076e5
@ -1,5 +1,6 @@
|
||||
{
|
||||
"ActiveSessions": "Active Sessions",
|
||||
"AutoDeleteTitle": "All the sessions older than 60 days will be automatically deleted.",
|
||||
"ChangeEmailSuccess": "Email has been changed successfully",
|
||||
"ChangePasswordAfterLoggingOut": "Change password after logging out",
|
||||
"ConnectSocialNetworks": "Connect your social networks",
|
||||
@ -28,5 +29,6 @@
|
||||
"SuccessLogout": "The active connection was logged out: {{platform}}, {{browser}}",
|
||||
"SystemTheme": "Use system theme",
|
||||
"SystemThemeDescription": "Automatically switch between light and dark themes when your system does.",
|
||||
"TerminateAllSessions": "Terminate all sessions except the current one",
|
||||
"TwoFactorDescription": "Two-factor authentication via a code-generating app was enabled for all users by the admin."
|
||||
}
|
||||
|
@ -24,8 +24,7 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useState } from "react";
|
||||
import { ModalDialog } from "@docspace/shared/components/modal-dialog";
|
||||
import { Checkbox } from "@docspace/shared/components/checkbox";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
@ -34,20 +33,24 @@ import { Text } from "@docspace/shared/components/text";
|
||||
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
|
||||
const LogoutAllConnectionDialog = ({
|
||||
const LogoutAllSessionDialog = ({
|
||||
t,
|
||||
visible,
|
||||
onClose,
|
||||
isLoading,
|
||||
onRemoveAllSessions,
|
||||
loading,
|
||||
onRemoveAllExceptThis,
|
||||
}) => {
|
||||
const { t } = useTranslation(["Profile", "Common"]);
|
||||
const [isChecked, setIsChecked] = useState(false);
|
||||
|
||||
const onChangeCheckbox = () => {
|
||||
setIsChecked((prev) => !prev);
|
||||
};
|
||||
|
||||
const onClickLogout = () => {
|
||||
isChecked ? onRemoveAllSessions() : onRemoveAllExceptThis();
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalDialogContainer
|
||||
visible={visible}
|
||||
@ -58,8 +61,8 @@ const LogoutAllConnectionDialog = ({
|
||||
{t("Profile:LogoutAllActiveConnections")}
|
||||
</ModalDialog.Header>
|
||||
<ModalDialog.Body>
|
||||
<Text as="p">{t("Profile:LogoutDescription")}</Text>
|
||||
<Text as="p" style={{ margin: "15px 0" }}>
|
||||
<Text>{t("Profile:LogoutDescription")}</Text>
|
||||
<Text style={{ margin: "15px 0" }}>
|
||||
{t("Profile:DescriptionForSecurity")}
|
||||
</Text>
|
||||
<Box displayProp="flex" alignItems="center">
|
||||
@ -79,10 +82,8 @@ const LogoutAllConnectionDialog = ({
|
||||
size="normal"
|
||||
scale
|
||||
primary={true}
|
||||
onClick={() =>
|
||||
isChecked ? onRemoveAllSessions() : onRemoveAllExceptThis()
|
||||
}
|
||||
isLoading={loading}
|
||||
onClick={onClickLogout}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
<Button
|
||||
className="cancel-button"
|
||||
@ -91,11 +92,11 @@ const LogoutAllConnectionDialog = ({
|
||||
size="normal"
|
||||
scale
|
||||
onClick={onClose}
|
||||
isDisabled={loading}
|
||||
isDisabled={isLoading}
|
||||
/>
|
||||
</ModalDialog.Footer>
|
||||
</ModalDialogContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default LogoutAllConnectionDialog;
|
||||
export default LogoutAllSessionDialog;
|
@ -24,21 +24,22 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Button } from "@docspace/shared/components/button";
|
||||
import { ModalDialog } from "@docspace/shared/components/modal-dialog";
|
||||
|
||||
import ModalDialogContainer from "../ModalDialogContainer";
|
||||
|
||||
const LogoutConnectionDialog = ({
|
||||
const LogoutSessionDialog = ({
|
||||
t,
|
||||
data,
|
||||
visible,
|
||||
onClose,
|
||||
onRemoveSession,
|
||||
data,
|
||||
loading,
|
||||
isLoading,
|
||||
}) => {
|
||||
const { t } = useTranslation(["Profile", "Common"]);
|
||||
const onClick = () => {
|
||||
onRemoveSession(data.id);
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalDialogContainer
|
||||
@ -62,8 +63,8 @@ const LogoutConnectionDialog = ({
|
||||
size="normal"
|
||||
scale
|
||||
primary={true}
|
||||
onClick={() => onRemoveSession(data.id)}
|
||||
isLoading={loading}
|
||||
onClick={onClick}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
<Button
|
||||
key="CloseBtn"
|
||||
@ -71,11 +72,11 @@ const LogoutConnectionDialog = ({
|
||||
size="normal"
|
||||
scale
|
||||
onClick={onClose}
|
||||
isDisabled={loading}
|
||||
isDisabled={isLoading}
|
||||
/>
|
||||
</ModalDialog.Footer>
|
||||
</ModalDialogContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default LogoutConnectionDialog;
|
||||
export default LogoutSessionDialog;
|
@ -50,8 +50,8 @@ import ChangeNameDialog from "./ChangeNameDialog";
|
||||
import AvatarEditorDialog from "./AvatarEditorDialog";
|
||||
import DeletePortalDialog from "./DeletePortalDialog";
|
||||
import InviteUsersWarningDialog from "./InviteUsersWarningDialog";
|
||||
import LogoutConnectionDialog from "./LogoutConnectionDialog";
|
||||
import LogoutAllConnectionDialog from "./LogoutAllConnectionDialog";
|
||||
import LogoutSessionDialog from "./LogoutSessionDialog";
|
||||
import LogoutAllSessionDialog from "./LogoutAllSessionDialog";
|
||||
import CreateRoomConfirmDialog from "./CreateRoomConfirmDialog";
|
||||
import PortalRenamingDialog from "./PortalRenamingDialog";
|
||||
import DataReassignmentDialog from "./DataReassignmentDialog";
|
||||
@ -97,9 +97,9 @@ export {
|
||||
ChangeNameDialog,
|
||||
AvatarEditorDialog,
|
||||
DeletePortalDialog,
|
||||
LogoutConnectionDialog,
|
||||
LogoutSessionDialog,
|
||||
InviteUsersWarningDialog,
|
||||
LogoutAllConnectionDialog,
|
||||
LogoutAllSessionDialog,
|
||||
PortalRenamingDialog,
|
||||
DataReassignmentDialog,
|
||||
SubmitToFormGallery,
|
||||
|
@ -0,0 +1,129 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { TableHeader } from "@docspace/shared/components/table";
|
||||
|
||||
const TABLE_VERSION = "5";
|
||||
const TABLE_COLUMNS = `SessionsColumns_ver-${TABLE_VERSION}`;
|
||||
|
||||
const getColumns = (defaultColumns, userId) => {
|
||||
const storageColumns = localStorage.getItem(`${TABLE_COLUMNS}=${userId}`);
|
||||
const columns = [];
|
||||
|
||||
if (storageColumns) {
|
||||
const splitColumns = storageColumns.split(",");
|
||||
|
||||
for (let col of defaultColumns) {
|
||||
const column = splitColumns.find((key) => key === col.key);
|
||||
column ? (col.enable = true) : (col.enable = false);
|
||||
|
||||
columns.push(col);
|
||||
}
|
||||
return columns;
|
||||
} else {
|
||||
return defaultColumns;
|
||||
}
|
||||
};
|
||||
|
||||
const SessionsTableHeader = (props) => {
|
||||
const {
|
||||
t,
|
||||
userId,
|
||||
sectionWidth,
|
||||
setHideColumns,
|
||||
containerRef,
|
||||
columnStorageName,
|
||||
columnInfoPanelStorageName,
|
||||
} = props;
|
||||
|
||||
const defaultColumns = [
|
||||
{
|
||||
key: "Sessions",
|
||||
title: t("Common:Sessions"),
|
||||
resizable: true,
|
||||
enable: true,
|
||||
default: true,
|
||||
active: true,
|
||||
minWidth: 180,
|
||||
isDisabled: true,
|
||||
onChange: onColumnChange,
|
||||
},
|
||||
{
|
||||
key: "Date",
|
||||
title: t("Common:Date"),
|
||||
enable: true,
|
||||
resizable: true,
|
||||
onChange: onColumnChange,
|
||||
},
|
||||
{
|
||||
key: "Location",
|
||||
title: t("Common:Location"),
|
||||
enable: true,
|
||||
resizable: true,
|
||||
onChange: onColumnChange,
|
||||
},
|
||||
];
|
||||
|
||||
const [columns, setColumns] = useState(getColumns(defaultColumns, userId));
|
||||
|
||||
useEffect(() => {
|
||||
setColumns(getColumns(defaultColumns));
|
||||
}, []);
|
||||
|
||||
function onColumnChange(key, e) {
|
||||
const columnIndex = columns.findIndex((c) => c.key === key);
|
||||
|
||||
if (columnIndex === -1) return;
|
||||
|
||||
setColumns((prevColumns) =>
|
||||
prevColumns.map((item, index) =>
|
||||
index === columnIndex ? { ...item, enable: !item.enable } : item,
|
||||
),
|
||||
);
|
||||
|
||||
const tableColumns = columns.map((c) => c.enable && c.key);
|
||||
localStorage.setItem(`${TABLE_COLUMNS}=${userId}`, tableColumns);
|
||||
}
|
||||
|
||||
return (
|
||||
<TableHeader
|
||||
checkboxSize="48px"
|
||||
containerRef={containerRef}
|
||||
columns={columns}
|
||||
columnStorageName={columnStorageName}
|
||||
columnInfoPanelStorageName={columnInfoPanelStorageName}
|
||||
sectionWidth={sectionWidth}
|
||||
checkboxMargin="12px"
|
||||
showSettings={false}
|
||||
useReactWindow
|
||||
setHideColumns={setHideColumns}
|
||||
infoPanelVisible={false}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default SessionsTableHeader;
|
@ -0,0 +1,152 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { ReactSVG } from "react-svg";
|
||||
import { Base } from "@docspace/shared/themes";
|
||||
import styled, { css } from "styled-components";
|
||||
|
||||
import { TableRow } from "@docspace/shared/components/table";
|
||||
import { TableCell } from "@docspace/shared/components/table";
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { Box } from "@docspace/shared/components/box";
|
||||
import { IconButton } from "@docspace/shared/components/icon-button";
|
||||
import { convertTime } from "@docspace/shared/utils/convertTime";
|
||||
import RemoveSessionSvgUrl from "PUBLIC_DIR/images/remove.session.svg?url";
|
||||
import TickSvgUrl from "PUBLIC_DIR/images/tick.svg?url";
|
||||
|
||||
const StyledTableRow = styled(TableRow)`
|
||||
.session-platform {
|
||||
font-weight: 600;
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-left: 5px;
|
||||
`
|
||||
: css`
|
||||
margin-right: 5px;
|
||||
`}
|
||||
}
|
||||
|
||||
.session-info {
|
||||
font-weight: 600;
|
||||
color: ${(props) => props.theme.profile.activeSessions.tableCellColor};
|
||||
}
|
||||
|
||||
.divider {
|
||||
display: inline-block;
|
||||
height: 12px;
|
||||
width: 2px;
|
||||
background-color: ${(props) =>
|
||||
props.theme.profile.activeSessions.dividerColor};
|
||||
margin: -2px 5px;
|
||||
}
|
||||
|
||||
.tick-icon {
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-right: 8px;
|
||||
`
|
||||
: css`
|
||||
margin-left: 8px;
|
||||
`}
|
||||
}
|
||||
`;
|
||||
|
||||
StyledTableRow.defaultProps = { theme: Base };
|
||||
|
||||
const SessionsTableRow = (props) => {
|
||||
const {
|
||||
item,
|
||||
hideColumns,
|
||||
currentSession,
|
||||
setPlatformModalData,
|
||||
setLogoutDialogVisible,
|
||||
} = props;
|
||||
|
||||
const { platform, browser, date, country, city, ip } = item;
|
||||
|
||||
const showRemoveIcon = currentSession !== item.id;
|
||||
const showTickIcon = currentSession === item.id;
|
||||
|
||||
const onRemoveClick = () => {
|
||||
setLogoutDialogVisible(true);
|
||||
setPlatformModalData({
|
||||
id: item?.id,
|
||||
platform: item?.platform,
|
||||
browser: item?.browser,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledTableRow key={item.id} hideColumns={hideColumns}>
|
||||
<TableCell>
|
||||
<Text className="session-platform">{platform}</Text>
|
||||
<Text className="session-info">{`(${browser})`}</Text>
|
||||
{showTickIcon && <ReactSVG className="tick-icon" src={TickSvgUrl} />}
|
||||
</TableCell>
|
||||
|
||||
<TableCell>
|
||||
<Text className="session-info" truncate>
|
||||
{convertTime(date)}
|
||||
</Text>
|
||||
</TableCell>
|
||||
|
||||
<TableCell>
|
||||
<Text className="session-info" truncate>
|
||||
{country}, {city}
|
||||
<Text as="span" className="divider" />
|
||||
{ip}
|
||||
</Text>
|
||||
</TableCell>
|
||||
|
||||
{showRemoveIcon && (
|
||||
<TableCell>
|
||||
<Box>
|
||||
<IconButton
|
||||
size={20}
|
||||
iconName={RemoveSessionSvgUrl}
|
||||
isClickable
|
||||
onClick={onRemoveClick}
|
||||
/>
|
||||
</Box>
|
||||
</TableCell>
|
||||
)}
|
||||
</StyledTableRow>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ setup }) => {
|
||||
const { currentSession, setLogoutDialogVisible, setPlatformModalData } =
|
||||
setup;
|
||||
|
||||
return {
|
||||
currentSession,
|
||||
setLogoutDialogVisible,
|
||||
setPlatformModalData,
|
||||
};
|
||||
})(observer(SessionsTableRow));
|
@ -0,0 +1,102 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import { useState, useRef } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { Base } from "@docspace/shared/themes";
|
||||
import styled from "styled-components";
|
||||
|
||||
import SessionsTableHeader from "./SessionsTableHeader";
|
||||
import SessionsTableRow from "./SessionsTableRow";
|
||||
|
||||
import { TableContainer } from "@docspace/shared/components/table";
|
||||
import { TableBody } from "@docspace/shared/components/table";
|
||||
|
||||
const TABLE_VERSION = "5";
|
||||
const COLUMNS_SIZE = `sessionsColumnsSize_ver-${TABLE_VERSION}`;
|
||||
const INFO_PANEL_COLUMNS_SIZE = `infoPanelSessionsColumnsSize_ver-${TABLE_VERSION}`;
|
||||
|
||||
const StyledTableContainer = styled(TableContainer)`
|
||||
margin: 0 0 20px;
|
||||
|
||||
.header-container-text {
|
||||
color: ${(props) => props.theme.tableContainer.header.textColor};
|
||||
font-size: ${(props) => props.theme.getCorrectFontSize("12px")};
|
||||
}
|
||||
`;
|
||||
|
||||
StyledTableContainer.defaultProps = { theme: Base };
|
||||
|
||||
const TableView = ({ t, sectionWidth, userId, sessionsData }) => {
|
||||
const [hideColumns, setHideColumns] = useState(false);
|
||||
const ref = useRef(null);
|
||||
|
||||
const columnStorageName = `${COLUMNS_SIZE}=${userId}`;
|
||||
const columnInfoPanelStorageName = `${INFO_PANEL_COLUMNS_SIZE}=${userId}`;
|
||||
|
||||
return (
|
||||
<StyledTableContainer forwardedRef={ref} useReactWindow>
|
||||
<SessionsTableHeader
|
||||
t={t}
|
||||
userId={userId}
|
||||
sectionWidth={sectionWidth}
|
||||
setHideColumns={setHideColumns}
|
||||
containerRef={ref}
|
||||
columnStorageName={columnStorageName}
|
||||
columnInfoPanelStorageName={columnInfoPanelStorageName}
|
||||
/>
|
||||
<TableBody
|
||||
itemHeight={49}
|
||||
useReactWindow
|
||||
infoPanelVisible={false}
|
||||
columnStorageName={columnStorageName}
|
||||
columnInfoPanelStorageName={columnInfoPanelStorageName}
|
||||
filesLength={sessionsData.length}
|
||||
hasMoreFiles={false}
|
||||
itemCount={sessionsData.length}
|
||||
fetchMoreFiles={() => {}}
|
||||
>
|
||||
{sessionsData.map((item) => (
|
||||
<SessionsTableRow
|
||||
t={t}
|
||||
key={item.id}
|
||||
hideColumns={hideColumns}
|
||||
userId={userId}
|
||||
item={item}
|
||||
/>
|
||||
))}
|
||||
</TableBody>
|
||||
</StyledTableContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ userStore }) => {
|
||||
const { id: userId } = userStore.user;
|
||||
|
||||
return {
|
||||
userId,
|
||||
};
|
||||
})(observer(TableView));
|
@ -0,0 +1,61 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { Consumer } from "@docspace/shared/utils/context";
|
||||
|
||||
import TableView from "./TableView";
|
||||
import RowView from "./RowView";
|
||||
|
||||
const SessionsTable = ({ t, viewAs, sessionsData }) => {
|
||||
return (
|
||||
<Consumer>
|
||||
{(context) =>
|
||||
viewAs === "table" ? (
|
||||
<TableView
|
||||
t={t}
|
||||
sectionWidth={context.sectionWidth}
|
||||
sessionsData={sessionsData}
|
||||
/>
|
||||
) : (
|
||||
<RowView
|
||||
t={t}
|
||||
sectionWidth={context.sectionWidth}
|
||||
sessionsData={sessionsData}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</Consumer>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ setup }) => {
|
||||
const { viewAs } = setup;
|
||||
|
||||
return {
|
||||
viewAs,
|
||||
};
|
||||
})(observer(SessionsTable));
|
@ -24,71 +24,73 @@
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import RemoveSessionSvgUrl from "PUBLIC_DIR/images/remove.session.svg?url";
|
||||
import TickSvgUrl from "PUBLIC_DIR/images/tick.svg?url";
|
||||
import InfoReactSvgUrl from "PUBLIC_DIR/images/info.react.svg?url";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { inject, observer } from "mobx-react";
|
||||
import { withTranslation } from "react-i18next";
|
||||
import { ReactSVG } from "react-svg";
|
||||
import styled, { css } from "styled-components";
|
||||
|
||||
import { Text } from "@docspace/shared/components/text";
|
||||
import { Link } from "@docspace/shared/components/link";
|
||||
import { Box } from "@docspace/shared/components/box";
|
||||
import { HelpButton } from "@docspace/shared/components/help-button";
|
||||
import { toastr } from "@docspace/shared/components/toast";
|
||||
import { useTheme } from "styled-components";
|
||||
import { convertTime } from "@docspace/shared/utils/convertTime";
|
||||
|
||||
import { HelpButton } from "@docspace/shared/components/help-button";
|
||||
import { ProfileFooterLoader } from "@docspace/shared/skeletons/profile";
|
||||
import InfoReactSvgUrl from "PUBLIC_DIR/images/info.react.svg?url";
|
||||
|
||||
import SessionsTable from "./SessionsTable";
|
||||
|
||||
import {
|
||||
LogoutConnectionDialog,
|
||||
LogoutAllConnectionDialog,
|
||||
LogoutSessionDialog,
|
||||
LogoutAllSessionDialog,
|
||||
} from "SRC_DIR/components/dialogs";
|
||||
|
||||
import {
|
||||
StyledFooter,
|
||||
Table,
|
||||
TableHead,
|
||||
TableRow,
|
||||
TableHeaderCell,
|
||||
TableBody,
|
||||
TableDataCell,
|
||||
} from "./styled-active-sessions";
|
||||
import { DeviceType } from "@docspace/shared/enums";
|
||||
import moment from "moment-timezone";
|
||||
|
||||
const removeIcon = (
|
||||
<ReactSVG className="remove-icon" src={RemoveSessionSvgUrl} />
|
||||
);
|
||||
const tickIcon = (
|
||||
<ReactSVG className="tick-icon" wrapper="span" src={TickSvgUrl} />
|
||||
);
|
||||
const StyledWrapper = styled.div`
|
||||
.auto-delete-title {
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
margin-top: 8px;
|
||||
color: ${(props) => props.theme.profile.activeSessions.tableCellColor};
|
||||
}
|
||||
.terminate-session-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
margin: 10px 0 0;
|
||||
}
|
||||
.terminate-all-sessions {
|
||||
font-size: ${(props) => props.theme.getCorrectFontSize("13px")};
|
||||
font-weight: 600;
|
||||
}
|
||||
.icon-button {
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-right: 5px;
|
||||
`
|
||||
: css`
|
||||
margin-left: 5px;
|
||||
`}
|
||||
}
|
||||
`;
|
||||
|
||||
const ActiveSessions = ({
|
||||
t,
|
||||
locale,
|
||||
getAllSessions,
|
||||
removeAllSessions,
|
||||
removeSession,
|
||||
logoutVisible,
|
||||
setLogoutVisible,
|
||||
logoutAllVisible,
|
||||
setLogoutAllVisible,
|
||||
logoutDialogVisible,
|
||||
setLogoutDialogVisible,
|
||||
logoutAllDialogVisible,
|
||||
setLogoutAllDialogVisible,
|
||||
removeAllExecptThis,
|
||||
sessionsIsInit,
|
||||
getSessions,
|
||||
sessions,
|
||||
currentSession,
|
||||
setSessions,
|
||||
currentDeviceType,
|
||||
platformModalData,
|
||||
}) => {
|
||||
const isDesktop = currentDeviceType === DeviceType.desktop;
|
||||
const isMobile = currentDeviceType === DeviceType.mobile;
|
||||
|
||||
const [modalData, setModalData] = useState({});
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { interfaceDirection } = useTheme();
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
getSessions();
|
||||
@ -96,34 +98,34 @@ const ActiveSessions = ({
|
||||
|
||||
const onClickRemoveAllSessions = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setIsLoading(true);
|
||||
await removeAllSessions().then((res) => window.location.replace(res));
|
||||
} catch (error) {
|
||||
toastr.error(error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
setLogoutAllVisible(false);
|
||||
setIsLoading(false);
|
||||
setLogoutAllDialogVisible(false);
|
||||
}
|
||||
};
|
||||
|
||||
const onClickRemoveAllExceptThis = async () => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setIsLoading(true);
|
||||
await removeAllExecptThis().then(() =>
|
||||
getAllSessions().then((res) => setSessions(res.items)),
|
||||
);
|
||||
} catch (error) {
|
||||
toastr.error(error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
setLogoutAllVisible(false);
|
||||
setIsLoading(false);
|
||||
setLogoutAllDialogVisible(false);
|
||||
}
|
||||
};
|
||||
|
||||
const onClickRemoveSession = async (id) => {
|
||||
const foundSession = sessions.find((s) => s.id === id);
|
||||
try {
|
||||
setLoading(true);
|
||||
setIsLoading(true);
|
||||
await removeSession(foundSession.id).then(() =>
|
||||
getAllSessions().then((res) => setSessions(res.items)),
|
||||
);
|
||||
@ -136,184 +138,97 @@ const ActiveSessions = ({
|
||||
} catch (error) {
|
||||
toastr.error(error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
setLogoutVisible(false);
|
||||
setIsLoading(false);
|
||||
setLogoutDialogVisible(false);
|
||||
}
|
||||
};
|
||||
|
||||
const convertTime = (date) => {
|
||||
return moment(date).tz(window.timezone).locale(locale).format("L, LTS");
|
||||
};
|
||||
const tableCell = (platform, browser) =>
|
||||
interfaceDirection === "rtl" && !isMobile ? (
|
||||
<>
|
||||
<span className="session-browser">
|
||||
<span>{browser}</span>
|
||||
</span>
|
||||
{platform}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{platform}
|
||||
<span className="session-browser">
|
||||
<span>{browser}</span>
|
||||
</span>
|
||||
</>
|
||||
);
|
||||
const tooltipContent = (
|
||||
<Text fontSize="12px">
|
||||
{t("Profile:LogoutAllActiveSessionsDescription")}
|
||||
</Text>
|
||||
);
|
||||
|
||||
if (!sessionsIsInit) return <ProfileFooterLoader isProfileFooter />;
|
||||
|
||||
return (
|
||||
<StyledFooter>
|
||||
<StyledWrapper>
|
||||
<Text fontSize="16px" fontWeight={700} lineHeight="22px">
|
||||
{t("Profile:ActiveSessions")}
|
||||
</Text>
|
||||
<Box
|
||||
displayProp="flex"
|
||||
alignItems="center"
|
||||
justifyContent="flex-start"
|
||||
marginProp="10px 0 0"
|
||||
>
|
||||
|
||||
<Text className="auto-delete-title">{t("Profile:AutoDeleteTitle")}</Text>
|
||||
|
||||
<Box className="terminate-session-container">
|
||||
<Link
|
||||
className="session-logout"
|
||||
className="terminate-all-sessions"
|
||||
type="action"
|
||||
isHovered
|
||||
onClick={() => setLogoutAllVisible(true)}
|
||||
onClick={() => setLogoutAllDialogVisible(true)}
|
||||
>
|
||||
{t("Profile:LogoutAllActiveSessions")}
|
||||
{t("Profile:TerminateAllSessions")}
|
||||
</Link>
|
||||
<HelpButton
|
||||
offsetRight={0}
|
||||
iconName={InfoReactSvgUrl}
|
||||
tooltipContent={
|
||||
<Text fontSize="12px">
|
||||
{t("Profile:LogoutAllActiveSessionsDescription")}
|
||||
</Text>
|
||||
}
|
||||
tooltipContent={tooltipContent}
|
||||
/>
|
||||
</Box>
|
||||
{!isDesktop ? (
|
||||
<Table>
|
||||
<TableBody>
|
||||
{sessions.map((session) => (
|
||||
<TableRow key={session.id}>
|
||||
<TableDataCell style={{ borderTop: "0" }}>
|
||||
{tableCell(session.platform, session.browser)}
|
||||
{currentSession === session.id ? tickIcon : null}
|
||||
|
||||
<Box flexDirection="column" alignItems="center">
|
||||
<span className="session-date">
|
||||
{convertTime(session.date)}
|
||||
</span>
|
||||
<span className="session-ip" dir="ltr">
|
||||
{session.ip}
|
||||
</span>
|
||||
</Box>
|
||||
</TableDataCell>
|
||||
<SessionsTable t={t} sessionsData={sessions} />
|
||||
|
||||
<TableDataCell
|
||||
style={{ borderTop: "0" }}
|
||||
onClick={() => {
|
||||
setLogoutVisible(true);
|
||||
setModalData({
|
||||
id: session.id,
|
||||
platform: session.platform,
|
||||
browser: session.browser,
|
||||
});
|
||||
}}
|
||||
>
|
||||
{currentSession !== session.id ? removeIcon : null}
|
||||
</TableDataCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
) : (
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableHeaderCell>{t("Common:Sessions")}</TableHeaderCell>
|
||||
<TableHeaderCell>{t("Common:Date")}</TableHeaderCell>
|
||||
<TableHeaderCell>{t("Common:IpAddress")}</TableHeaderCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{sessions.map((session) => (
|
||||
<TableRow key={session.id}>
|
||||
<TableDataCell>
|
||||
{tableCell(session.platform, session.browser)}
|
||||
{currentSession === session.id ? tickIcon : null}
|
||||
</TableDataCell>
|
||||
<TableDataCell>{convertTime(session.date)}</TableDataCell>
|
||||
<TableDataCell>{session.ip}</TableDataCell>
|
||||
<TableDataCell
|
||||
onClick={() => {
|
||||
setLogoutVisible(true);
|
||||
setModalData({
|
||||
id: session.id,
|
||||
platform: session.platform,
|
||||
browser: session.browser,
|
||||
});
|
||||
}}
|
||||
>
|
||||
{currentSession !== session.id ? removeIcon : null}
|
||||
</TableDataCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
)}
|
||||
|
||||
{logoutVisible && (
|
||||
<LogoutConnectionDialog
|
||||
visible={logoutVisible}
|
||||
data={modalData}
|
||||
loading={loading}
|
||||
onClose={() => setLogoutVisible(false)}
|
||||
{logoutDialogVisible && (
|
||||
<LogoutSessionDialog
|
||||
t={t}
|
||||
visible={logoutDialogVisible}
|
||||
data={platformModalData}
|
||||
isLoading={isLoading}
|
||||
onClose={() => setLogoutDialogVisible(false)}
|
||||
onRemoveSession={onClickRemoveSession}
|
||||
/>
|
||||
)}
|
||||
|
||||
{logoutAllVisible && (
|
||||
<LogoutAllConnectionDialog
|
||||
visible={logoutAllVisible}
|
||||
loading={loading}
|
||||
onClose={() => setLogoutAllVisible(false)}
|
||||
{logoutAllDialogVisible && (
|
||||
<LogoutAllSessionDialog
|
||||
t={t}
|
||||
visible={logoutAllDialogVisible}
|
||||
isLoading={isLoading}
|
||||
onClose={() => setLogoutAllDialogVisible(false)}
|
||||
onRemoveAllSessions={onClickRemoveAllSessions}
|
||||
onRemoveAllExceptThis={onClickRemoveAllExceptThis}
|
||||
/>
|
||||
)}
|
||||
</StyledFooter>
|
||||
</StyledWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default inject(({ settingsStore, userStore, setup }) => {
|
||||
const { culture, currentDeviceType } = settingsStore;
|
||||
const { user } = userStore;
|
||||
const locale = (user && user.cultureName) || culture || "en";
|
||||
export default inject(({ settingsStore, setup }) => {
|
||||
const { currentDeviceType } = settingsStore;
|
||||
|
||||
const {
|
||||
getAllSessions,
|
||||
removeAllSessions,
|
||||
removeSession,
|
||||
logoutVisible,
|
||||
setLogoutVisible,
|
||||
logoutAllVisible,
|
||||
setLogoutAllVisible,
|
||||
logoutDialogVisible,
|
||||
setLogoutDialogVisible,
|
||||
logoutAllDialogVisible,
|
||||
setLogoutAllDialogVisible,
|
||||
removeAllExecptThis,
|
||||
sessionsIsInit,
|
||||
sessions,
|
||||
currentSession,
|
||||
getSessions,
|
||||
setSessions,
|
||||
platformModalData,
|
||||
} = setup;
|
||||
return {
|
||||
locale,
|
||||
getAllSessions,
|
||||
removeAllSessions,
|
||||
removeSession,
|
||||
logoutVisible,
|
||||
setLogoutVisible,
|
||||
logoutAllVisible,
|
||||
setLogoutAllVisible,
|
||||
logoutDialogVisible,
|
||||
setLogoutDialogVisible,
|
||||
logoutAllDialogVisible,
|
||||
setLogoutAllDialogVisible,
|
||||
removeAllExecptThis,
|
||||
sessionsIsInit,
|
||||
sessions,
|
||||
@ -321,5 +236,6 @@ export default inject(({ settingsStore, userStore, setup }) => {
|
||||
getSessions,
|
||||
setSessions,
|
||||
currentDeviceType,
|
||||
platformModalData,
|
||||
};
|
||||
})(observer(withTranslation(["Profile", "Common"])(ActiveSessions)));
|
||||
|
@ -1,219 +0,0 @@
|
||||
// (c) Copyright Ascensio System SIA 2009-2024
|
||||
//
|
||||
// This program is a free software product.
|
||||
// You can redistribute it and/or modify it under the terms
|
||||
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
|
||||
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
|
||||
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
|
||||
// any third-party rights.
|
||||
//
|
||||
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
|
||||
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
|
||||
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||||
//
|
||||
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
|
||||
//
|
||||
// The interactive user interfaces in modified source and object code versions of the Program must
|
||||
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
|
||||
//
|
||||
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
|
||||
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
|
||||
// trademark law for use of our trademarks.
|
||||
//
|
||||
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
|
||||
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
|
||||
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||||
|
||||
import styled, { css } from "styled-components";
|
||||
import { mobile } from "@docspace/shared/utils";
|
||||
|
||||
export const StyledFooter = styled.div`
|
||||
.session-logout {
|
||||
font-size: ${(props) => props.theme.getCorrectFontSize("13px")};
|
||||
font-weight: 600;
|
||||
}
|
||||
.icon-button {
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-right: 4px;
|
||||
`
|
||||
: css`
|
||||
margin-left: 4px;
|
||||
`}
|
||||
}
|
||||
`;
|
||||
|
||||
export const Table = styled.table`
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 2px;
|
||||
`;
|
||||
|
||||
export const TableHead = styled.thead`
|
||||
font-size: ${(props) => props.theme.getCorrectFontSize("12px")};
|
||||
line-height: 16px;
|
||||
`;
|
||||
|
||||
export const TableRow = styled.tr`
|
||||
display: table-row;
|
||||
`;
|
||||
|
||||
export const TableHeaderCell = styled.th`
|
||||
border-top: 1px solid ${(props) => props.theme.activeSessions.borderColor};
|
||||
border-bottom: 1px solid ${(props) => props.theme.activeSessions.borderColor};
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
text-align: right;
|
||||
`
|
||||
: css`
|
||||
text-align: left;
|
||||
`}
|
||||
font-weight: 600;
|
||||
padding: 12px 0;
|
||||
color: #a3a9ae;
|
||||
position: relative;
|
||||
border-top: 0;
|
||||
|
||||
:not(:first-child):before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 17px;
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
right: -8px;
|
||||
`
|
||||
: css`
|
||||
left: -8px;
|
||||
`}
|
||||
width: 1px;
|
||||
height: 10px;
|
||||
background: ${(props) => props.theme.activeSessions.sortHeaderColor};
|
||||
}
|
||||
`;
|
||||
|
||||
export const TableBody = styled.tbody`
|
||||
font-size: ${(props) => props.theme.getCorrectFontSize("11px")};
|
||||
`;
|
||||
|
||||
export const TableDataCell = styled.td`
|
||||
border-top: 1px solid ${(props) => props.theme.activeSessions.borderColor};
|
||||
border-bottom: 1px solid ${(props) => props.theme.activeSessions.borderColor};
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
text-align: right;
|
||||
`
|
||||
: css`
|
||||
text-align: left;
|
||||
`}
|
||||
font-weight: 600;
|
||||
padding: 14px 0;
|
||||
color: #a3a9ae;
|
||||
|
||||
.tick-icon {
|
||||
svg {
|
||||
path {
|
||||
fill: ${(props) => props.theme.activeSessions.tickIconColor};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.remove-icon {
|
||||
svg {
|
||||
path {
|
||||
fill: ${(props) => props.theme.activeSessions.removeIconColor};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media ${mobile} {
|
||||
.session-browser {
|
||||
position: relative;
|
||||
top: 4px;
|
||||
max-width: 150px;
|
||||
display: inline-block;
|
||||
margin-left: 0 !important;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
span {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:first-child {
|
||||
font-size: ${(props) => props.theme.getCorrectFontSize("13px")};
|
||||
color: ${(props) => props.theme.activeSessions.color};
|
||||
span {
|
||||
color: #a3a9ae;
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl"
|
||||
? css`
|
||||
margin-right: 5px;
|
||||
`
|
||||
: css`
|
||||
margin-left: 5px;
|
||||
`}
|
||||
}
|
||||
}
|
||||
|
||||
.session-date {
|
||||
position: relative;
|
||||
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "ltr"
|
||||
? css`
|
||||
margin-right: 8px;
|
||||
margin-left: 0 !important;
|
||||
:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: -8px;
|
||||
width: 1px;
|
||||
height: 12px;
|
||||
background: ${(props) =>
|
||||
props.theme.activeSessions.sortHeaderColor};
|
||||
}
|
||||
`
|
||||
: css`
|
||||
margin-left: 8px;
|
||||
margin-right: 0 !important;
|
||||
`}
|
||||
}
|
||||
|
||||
.session-ip {
|
||||
position: relative;
|
||||
${(props) =>
|
||||
props.theme.interfaceDirection === "rtl" &&
|
||||
css`
|
||||
:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: -8px;
|
||||
width: 1px;
|
||||
height: 12px;
|
||||
background: ${(props) => props.theme.activeSessions.sortHeaderColor};
|
||||
}
|
||||
`}
|
||||
}
|
||||
|
||||
:last-child {
|
||||
text-align: end;
|
||||
}
|
||||
.remove-icon {
|
||||
svg {
|
||||
cursor: pointer;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
path {
|
||||
fill: #a3a9ae;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
@ -47,8 +47,8 @@ class SettingsSetupStore {
|
||||
tfaStore = null;
|
||||
thirdPartyStore = null;
|
||||
isInit = false;
|
||||
logoutVisible = false;
|
||||
logoutAllVisible = false;
|
||||
logoutDialogVisible = false;
|
||||
logoutAllDialogVisible = false;
|
||||
viewAs = isDesktop() ? "table" : "row";
|
||||
|
||||
isLoadingDownloadReport = false;
|
||||
@ -109,6 +109,7 @@ class SettingsSetupStore {
|
||||
sessionsIsInit = false;
|
||||
sessions = [];
|
||||
currentSession = [];
|
||||
platformModalData = {};
|
||||
|
||||
constructor(tfaStore, authStore, settingsStore, thirdPartyStore) {
|
||||
this.selectionStore = new SelectionStore(this);
|
||||
@ -554,9 +555,13 @@ class SettingsSetupStore {
|
||||
return api.settings.removeActiveSession(id);
|
||||
};
|
||||
|
||||
setLogoutVisible = (visible) => (this.logoutVisible = visible);
|
||||
setLogoutDialogVisible = (visible) => {
|
||||
this.logoutDialogVisible = visible;
|
||||
};
|
||||
|
||||
setLogoutAllVisible = (visible) => (this.logoutAllVisible = visible);
|
||||
setLogoutAllDialogVisible = (visible) => {
|
||||
this.logoutAllDialogVisible = visible;
|
||||
};
|
||||
|
||||
getSessions = () => {
|
||||
if (this.sessionsIsInit) return;
|
||||
@ -570,6 +575,14 @@ class SettingsSetupStore {
|
||||
setSessions = (sessions) => {
|
||||
this.sessions = sessions;
|
||||
};
|
||||
|
||||
setPlatformModalData = (data) => {
|
||||
this.platformModalData = {
|
||||
id: data.id,
|
||||
platform: data.platform,
|
||||
browser: data.browser,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export default SettingsSetupStore;
|
||||
|
@ -3225,14 +3225,15 @@ export const getBaseTheme = () => {
|
||||
notifications: {
|
||||
textDescriptionColor: "#A3A9AE",
|
||||
},
|
||||
},
|
||||
|
||||
activeSessions: {
|
||||
color: "#333",
|
||||
borderColor: "#eceef1",
|
||||
tickIconColor: "#35AD17",
|
||||
removeIconColor: "#A3A9AE",
|
||||
sortHeaderColor: "#d0d5da",
|
||||
activeSessions: {
|
||||
color: "#333",
|
||||
borderColor: "#eceef1",
|
||||
tickIconColor: "#35AD17",
|
||||
removeIconColor: "#A3A9AE",
|
||||
sortHeaderColor: "#d0d5da",
|
||||
tableCellColor: "#a3a9ae",
|
||||
dividerColor: "#D0D5DA",
|
||||
},
|
||||
},
|
||||
|
||||
formWrapper: {
|
||||
|
@ -3202,14 +3202,15 @@ const Dark: TTheme = {
|
||||
notifications: {
|
||||
textDescriptionColor: "#858585",
|
||||
},
|
||||
},
|
||||
|
||||
activeSessions: {
|
||||
color: "#eeeeee",
|
||||
borderColor: "#474747",
|
||||
tickIconColor: "#3BA420",
|
||||
removeIconColor: "#A3A9AE",
|
||||
sortHeaderColor: "#474747",
|
||||
activeSessions: {
|
||||
color: "#eeeeee",
|
||||
borderColor: "#474747",
|
||||
tickIconColor: "#3BA420",
|
||||
removeIconColor: "#A3A9AE",
|
||||
sortHeaderColor: "#474747",
|
||||
tableCellColor: "#858585",
|
||||
dividerColor: "#474747",
|
||||
},
|
||||
},
|
||||
|
||||
formWrapper: {
|
||||
|
Loading…
Reference in New Issue
Block a user