diff --git a/packages/app/constants/settings/components/sessionItem/icons/chrome.jsx b/packages/app/constants/settings/components/sessionItem/icons/chrome.jsx
new file mode 100644
index 00000000..c7a2a846
--- /dev/null
+++ b/packages/app/constants/settings/components/sessionItem/icons/chrome.jsx
@@ -0,0 +1,26 @@
+export default () =>
\ No newline at end of file
diff --git a/packages/app/constants/settings/components/sessionItem/icons/firefox.jsx b/packages/app/constants/settings/components/sessionItem/icons/firefox.jsx
new file mode 100644
index 00000000..0c94a240
--- /dev/null
+++ b/packages/app/constants/settings/components/sessionItem/icons/firefox.jsx
@@ -0,0 +1,3 @@
+export default () =>
\ No newline at end of file
diff --git a/packages/app/constants/settings/components/sessionItem/icons/mobile.jsx b/packages/app/constants/settings/components/sessionItem/icons/mobile.jsx
new file mode 100644
index 00000000..43732704
--- /dev/null
+++ b/packages/app/constants/settings/components/sessionItem/icons/mobile.jsx
@@ -0,0 +1,34 @@
+export default () => {
+ return
+}
\ No newline at end of file
diff --git a/packages/app/constants/settings/components/sessionItem/index.jsx b/packages/app/constants/settings/components/sessionItem/index.jsx
new file mode 100644
index 00000000..6d719daa
--- /dev/null
+++ b/packages/app/constants/settings/components/sessionItem/index.jsx
@@ -0,0 +1,145 @@
+import React from "react"
+import * as antd from "antd"
+import SessionModel from "models/session"
+import classnames from "classnames"
+
+import moment from "moment"
+import UAParser from "ua-parser-js"
+
+import { Icons } from "components/Icons"
+
+import ChromeIcon from "./icons/chrome"
+import MobileIcon from "./icons/mobile"
+import FirefoxIcon from "./icons/firefox"
+
+import "./index.less"
+
+const DeviceIcon = (props) => {
+ if (!props.ua) {
+ return null
+ }
+
+ if (props.ua.ua === "capacitor") {
+ return
+ }
+
+ switch (props.ua.browser.name) {
+ case "Chrome": {
+ return
+ }
+ case "Firefox": {
+ return
+ }
+ default: {
+ return
+ }
+ }
+}
+
+const SessionItem = (props) => {
+ const { session } = props
+
+ const [collapsed, setCollapsed] = React.useState(true)
+
+ const onClickCollapse = () => {
+ setCollapsed((prev) => {
+ return !prev
+ })
+ }
+
+ const onClickRevoke = () => {
+ // if (typeof props.onClickRevoke === "function") {
+ // props.onClickRevoke(session)
+ // }
+ }
+
+ const isCurrentSession = React.useMemo(() => {
+ const currentUUID = SessionModel.session_uuid
+ return session.session_uuid === currentUUID
+ })
+
+ const ua = React.useMemo(() => {
+ return UAParser(session.client)
+ })
+
+ console.log(session, ua)
+
+ return
+
+
+
+
+
+
+
+
+
{session.session_uuid}
+
+
+
+
+
+
+
+ {moment(session.date).format("DD/MM/YYYY HH:mm")}
+
+
+
+
+
+
+ {session.ip_address}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {session.location}
+
+
+
+ {
+ ua.device.vendor &&
+
+
+
+ {ua.device.vendor} | {ua.device.model}
+
+
+ }
+
+
+}
+
+export default SessionItem
\ No newline at end of file
diff --git a/packages/app/constants/settings/components/sessionItem/index.less b/packages/app/constants/settings/components/sessionItem/index.less
new file mode 100644
index 00000000..b11fab3a
--- /dev/null
+++ b/packages/app/constants/settings/components/sessionItem/index.less
@@ -0,0 +1,167 @@
+@item_border_radius: 12px;
+
+.security_sessions_list_item_wrapper {
+ display: flex;
+ flex-direction: column;
+
+ &.collapsed {
+ .security_sessions_list_item_extra-body {
+ height: 0;
+ transform: translateY(-100%);
+ padding-top: 0;
+ padding-bottom: 0;
+ }
+
+ .security_sessions_list_item {
+ border-radius: @item_border_radius;
+ border-bottom-color: transparent;
+ }
+ }
+}
+
+
+.security_sessions_list_item {
+ position: relative;
+
+ z-index: 100;
+
+ display: flex;
+ flex-direction: row;
+
+ align-items: center;
+
+ border-radius: @item_border_radius @item_border_radius 0 0;
+
+ border-bottom: 1px var(--border-color) solid;
+
+ background-color: var(--background-color-primary);
+
+ transition: all 150ms ease-in-out;
+
+ padding: 5px;
+
+ width: 100%;
+
+ overflow: hidden;
+
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ span {
+ margin: 0 !important;
+ }
+
+ svg {
+ margin: 0 !important;
+ }
+
+ gap: 10px;
+
+ .security_sessions_list_item_icon {
+ display: inline-flex;
+ flex-direction: row;
+
+ align-items: center;
+ justify-content: center;
+
+ width: 50px;
+ height: 50px;
+
+ padding: 10px;
+
+ background-color: var(--background-color-accent);
+
+ border-radius: 12px;
+
+ svg {
+ width: 30px;
+ height: 30px;
+ }
+
+ }
+
+ .security_sessions_list_item_info {
+ display: flex;
+ flex-direction: column;
+
+ gap: 5px;
+
+ span {
+ user-select: text;
+ }
+
+ .security_sessions_list_item_title {
+ display: inline-flex;
+ align-items: center;
+
+ justify-content: space-between;
+
+ font-size: 0.7rem;
+ font-weight: 600;
+
+ gap: 20px;
+ }
+
+ .security_sessions_list_item_info_details {
+ display: inline-flex;
+ flex-direction: row;
+
+ align-items: center;
+
+ gap: 7px;
+ }
+ }
+
+ .security_sessions_list_item_actions {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+
+ gap: 10px;
+ }
+}
+
+.security_sessions_list_item_extra-body {
+ position: relative;
+
+ z-index: 99;
+
+ display: inline-flex;
+ flex-direction: row;
+
+ align-items: center;
+
+ width: 100%;
+ gap: 10px;
+
+ background-color: var(--background-color-primary);
+
+ transform: translateY(calc(-1 * calc(@item_border_radius / 2)));
+
+ padding: 5px 10px;
+ padding-top: calc(calc(@item_border_radius / 2) + 5px);
+
+ transition: all 150ms ease-in-out;
+
+ border-radius: 0 0 @item_border_radius @item_border_radius;
+
+ overflow: hidden;
+}
+
+.security_sessions_list_item_info_details_item {
+ display: flex;
+ flex-direction: row;
+
+ align-items: center;
+
+ gap: 5px;
+
+ font-size: 0.8rem;
+ font-weight: 400;
+
+ svg {
+ margin: 0 !important;
+ }
+}
\ No newline at end of file
diff --git a/packages/app/constants/settings/components/sessions/index.jsx b/packages/app/constants/settings/components/sessions/index.jsx
index 54e20b4c..c7c0312d 100755
--- a/packages/app/constants/settings/components/sessions/index.jsx
+++ b/packages/app/constants/settings/components/sessions/index.jsx
@@ -1,13 +1,79 @@
import React from "react"
-import { Button } from "antd"
+import * as antd from "antd"
+import SessionModel from "models/session"
-export default (props) => {
- return
+import SessionItem from "../sessionItem"
+
+import "./index.less"
+
+export default () => {
+ const [loading, setLoading] = React.useState(true)
+ const [sessions, setSessions] = React.useState([])
+ const [sessionsPage, setSessionsPage] = React.useState(1)
+ const [itemsPerPage, setItemsPerPage] = React.useState(3)
+
+ const loadSessions = async () => {
+ setLoading(true)
+
+ const response = await SessionModel.getAllSessions().catch((err) => {
+ console.error(err)
+ app.message.error("Failed to load sessions")
+ return null
+ })
+
+ console.log(response)
+
+ if (response) {
+ setSessions(response)
+ }
+
+ setLoading(false)
+ }
+
+ const onClickRevoke = async (session) => {
+ console.log(session)
+
+ app.message.warning("Not implemented yet")
+ }
+
+ const onClickRevokeAll = async () => {
+ app.message.warning("Not implemented yet")
+ }
+
+ React.useEffect(() => {
+ loadSessions()
+ }, [])
+
+ if (loading) {
+ return
+ }
+
+ const offset = (sessionsPage - 1) * itemsPerPage
+ const slicedItems = sessions.slice(offset, offset + itemsPerPage)
+
+ return
+
+ {
+ slicedItems.map((session) => {
+ return
+ })
+ }
+
+
{
+ setSessionsPage(page)
+ }}
+ total={sessions.length}
+ showTotal={(total) => {
+ return `${total} Sessions`
+ }}
+ simple
+
+ />
+
+
}
\ No newline at end of file
diff --git a/packages/app/constants/settings/components/sessions/index.less b/packages/app/constants/settings/components/sessions/index.less
new file mode 100755
index 00000000..e123fe98
--- /dev/null
+++ b/packages/app/constants/settings/components/sessions/index.less
@@ -0,0 +1,40 @@
+.security_sessions {
+ display: flex;
+ flex-direction: column;
+
+ width: 100%;
+
+ .security_sessions_list {
+ display: flex;
+ flex-direction: column;
+
+ justify-content: center;
+
+ width: 100%;
+
+ gap: 5px;
+
+ .ant-pagination {
+ display: flex;
+ flex-direction: row;
+
+ align-items: center;
+
+ li {
+ display: flex;
+ flex-direction: row;
+
+ align-items: center;
+ justify-content: center;
+ }
+
+ button {
+ width: 24px!important;
+
+ svg {
+ margin: 0 !important;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/app/constants/settings/security/index.jsx b/packages/app/constants/settings/security/index.jsx
index 66e6e0d9..16c713e1 100755
--- a/packages/app/constants/settings/security/index.jsx
+++ b/packages/app/constants/settings/security/index.jsx
@@ -1,8 +1,4 @@
-import React from "react"
import loadable from "@loadable/component"
-import AuthModel from "models/auth"
-
-// TODO: Make logout button require a valid session to be not disabled
export default {
id: "security",
@@ -33,7 +29,6 @@ export default {
"description": "Manage your active sessions",
"icon": "Monitor",
"component": loadable(() => import("../components/sessions")),
- "storaged": false
}
]
}
\ No newline at end of file
diff --git a/packages/app/src/pages/security/sessions/index.jsx b/packages/app/src/pages/security/sessions/index.jsx
deleted file mode 100755
index 1c986d4a..00000000
--- a/packages/app/src/pages/security/sessions/index.jsx
+++ /dev/null
@@ -1,128 +0,0 @@
-import React from "react"
-import * as antd from "antd"
-import SessionModel from "models/session"
-import moment from "moment"
-
-import { Icons } from "components/Icons"
-
-import "./index.less"
-
-const SessionItem = (props) => {
- const { session } = props
-
- const [isCurrent, setIsCurrent] = React.useState(false)
-
- const onClickRevoke = () => {
- if (typeof props.onClickRevoke === "function") {
- props.onClickRevoke(session)
- }
- }
-
- React.useEffect(() => {
- const currentUUID = SessionModel.session_uuid
-
- if (currentUUID === session.session_uuid) {
- setIsCurrent(true)
- }
- }, [])
-
- return
-
-
-
{session.session_uuid}
- {
- isCurrent &&
- Current
-
- }
-
-
-
- {session.location}
-
-
-
-
-
- {moment(session.date).format("DD/MM/YYYY HH:mm")}
-
-
-
-
-
-
-}
-
-export default () => {
- const [loading, setLoading] = React.useState(true)
- const [sessions, setSessions] = React.useState([])
-
- const loadSessions = async () => {
- setLoading(true)
-
- const response = await SessionModel.getAllSessions().catch((err) => {
- console.error(err)
- app.message.error("Failed to load sessions")
- return null
- })
-
- console.log(response)
-
- if (response) {
- setSessions(response)
- }
-
- setLoading(false)
- }
-
- const onClickRevoke = async (session) => {
- console.log(session)
-
- app.message.warning("Not implemented yet")
- }
-
- const onClickRevokeAll = async () => {
- app.message.warning("Not implemented yet")
- }
-
- React.useEffect(() => {
- loadSessions()
- }, [])
-
- if (loading) {
- return
- }
-
- return
-
-
Generated Sessions
-
- Revoke all sessions
-
-
-
-
- {sessions.map((session, index) => {
- return
- })}
-
-
-}
\ No newline at end of file
diff --git a/packages/app/src/pages/security/sessions/index.less b/packages/app/src/pages/security/sessions/index.less
deleted file mode 100755
index 3e8baff4..00000000
--- a/packages/app/src/pages/security/sessions/index.less
+++ /dev/null
@@ -1,96 +0,0 @@
-.sessions {
- display: flex;
- flex-direction: column;
-
- .sessions_header {
- display: flex;
- flex-direction: row;
- justify-content: space-between;
-
- align-items: center;
-
- margin-bottom: 20px;
-
- h1 {
- font-size: 1.5rem;
- }
- }
-
- .sessions_list {
- display: flex;
- flex-direction: column;
-
- align-items: center;
- justify-content: center;
-
- width: 100%;
-
- .sessionItem {
- display: flex;
- flex-direction: column;
-
- padding: 10px;
-
- border-radius: 12px;
-
- background-color: var(--background-color-accent);
-
- margin-bottom: 10px;
-
- width: 35vw;
-
- h1,
- h2,
- h3,
- h4,
- h5,
- span {
- margin: 0 !important;
- }
-
- .sessionItem_info {
- display: flex;
- flex-direction: column;
-
- gap: 10px;
-
- .sessionItem_info_title {
- display: inline-flex;
- align-items: center;
-
- justify-content: space-between;
-
- font-size: 1rem;
- font-weight: 600;
- }
-
- .sessionItem_info_details {
- display: inline-flex;
- flex-direction: row;
-
- align-items: center;
-
- font-size: 0.8rem;
- font-weight: 400;
-
- .sessionItem_info_details_detail {
- display: flex;
- flex-direction: row;
-
- align-items: center;
-
- margin-right: 10px;
- }
- }
- }
-
- .sessionItem_actions {
- display: flex;
- flex-direction: row;
- justify-content: flex-end;
-
- gap: 10px;
- }
- }
- }
-}
\ No newline at end of file