diff --git a/frontend/components/basic/Layout.tsx b/frontend/components/basic/Layout.tsx
index 56a16cb3d..91f257ff9 100644
--- a/frontend/components/basic/Layout.tsx
+++ b/frontend/components/basic/Layout.tsx
@@ -4,6 +4,7 @@ import { useEffect, useState } from 'react';
import Link from 'next/link';
import { useRouter } from 'next/router';
import {
+ faBook,
faBookOpen,
faGear,
faKey,
@@ -150,6 +151,11 @@ export default function Layout({ children }: LayoutProps) {
title: 'Integrations',
emoji:
},
+ {
+ href: '/activity/' + workspaceMapping[workspaceSelected as any],
+ title: 'Activity',
+ emoji:
+ },
{
href: '/settings/project/' + workspaceMapping[workspaceSelected as any],
title: 'Project Settings',
diff --git a/frontend/components/basic/table/ActivityTable.tsx b/frontend/components/basic/table/ActivityTable.tsx
new file mode 100644
index 000000000..fe98277e7
--- /dev/null
+++ b/frontend/components/basic/table/ActivityTable.tsx
@@ -0,0 +1,144 @@
+import React, { useEffect, useState } from 'react';
+import { useRouter } from 'next/router';
+import {
+ faAngleDown,
+ faAngleRight,
+ faX
+} from '@fortawesome/free-solid-svg-icons';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+
+import guidGenerator from '../../utilities/randomId';
+
+interface ActivityTableProps {
+ eventName: string;
+ user: string;
+ source: string;
+ time: Date;
+}
+
+function timeSince(date: Date) {
+ const seconds = Math.floor(
+ ((new Date() as any) - (date as any)) / 1000
+ ) as number;
+
+ let interval = seconds / 31536000;
+
+ if (interval > 1) {
+ return Math.floor(interval) + ' years ago';
+ }
+ interval = seconds / 2592000;
+ if (interval > 1) {
+ return Math.floor(interval) + ' months ago';
+ }
+ interval = seconds / 86400;
+ if (interval > 1) {
+ return Math.floor(interval) + ' days ago';
+ }
+ interval = seconds / 3600;
+ if (interval > 1) {
+ return Math.floor(interval) + ' hours ago';
+ }
+ interval = seconds / 60;
+ if (interval > 1) {
+ return Math.floor(interval) + ' minutes ago';
+ }
+ return Math.floor(seconds) + ' seconds ago';
+}
+
+const ActivityLogsRow = ({ row }: { row: ActivityTableProps }): JSX.Element => {
+ const [payloadOpened, setPayloadOpened] = useState(false);
+ return (
+ <>
+
+ setPayloadOpened(!payloadOpened)}
+ className="border-mineshaft-700 border-t text-gray-300 flex items-center"
+ >
+
+
+
+ {row.eventName}
+ |
+
+ {row.user}
+ |
+
+ {row.source}
+ |
+
+ {timeSince(row.time)}
+ |
+ {/*
+
+
+ | */}
+
+ {payloadOpened && (
+
+
+
+ Timestamp
+ 2022-12-16T04:02:44.517Z
+
+
+ Number of Secrets
+ 32
+
+
+ IP Address
+ 159.223.164.24
+
+ |
+
+ )}
+ >
+ );
+};
+
+/**
+ * This is the table for activity logs (one of the tabs)
+ * @param {*} props
+ * @returns
+ */
+const ActivityTable = ({ data }: { data: ActivityTableProps[] }) => {
+ return (
+
+
+
+
+
+
+ |
+ Event |
+ User |
+ Source |
+ Time |
+ |
+
+
+
+ {data.map((row, index) => {
+ return ;
+ })}
+
+
+
+
+ );
+};
+
+export default ActivityTable;
diff --git a/frontend/pages/activity/[id].tsx b/frontend/pages/activity/[id].tsx
new file mode 100644
index 000000000..5ffba0328
--- /dev/null
+++ b/frontend/pages/activity/[id].tsx
@@ -0,0 +1,62 @@
+import React, { useEffect, useState } from 'react';
+import { useRouter } from 'next/router';
+
+import ActivityTable from '~/components/basic/table/ActivityTable';
+import NavHeader from '~/components/navigation/NavHeader';
+import onboardingCheck from '~/components/utilities/checks/OnboardingCheck';
+
+const data = [
+ {
+ eventName: 'Secrets Pulled',
+ user: 'matsiiako@gmail.com',
+ source: 'CLI',
+ time: new Date()
+ },
+ {
+ eventName: 'Secrets Pushed',
+ user: 'matsiiako@gmail.com',
+ source: 'Web',
+ time: new Date()
+ }
+];
+
+/**
+ * This tab is called Home because in the future it will include some company news,
+ * updates, roadmap, relavant blogs, etc. Currently it only has the setup instruction
+ * for the new users
+ */
+export default function Activity() {
+ const router = useRouter();
+ const [hasUserClickedSlack, setHasUserClickedSlack] = useState(false);
+ const [hasUserClickedIntro, setHasUserClickedIntro] = useState(false);
+ const [hasUserStarred, setHasUserStarred] = useState(false);
+ const [hasUserPushedSecrets, setHasUserPushedSecrets] = useState(false);
+ const [usersInOrg, setUsersInOrg] = useState(false);
+
+ useEffect(() => {
+ onboardingCheck({
+ setHasUserClickedIntro,
+ setHasUserClickedSlack,
+ setHasUserPushedSecrets,
+ setHasUserStarred,
+ setUsersInOrg
+ });
+ }, []);
+
+ return (
+
+
+
+
+
+ Manage your integrations of Infisical with third-party services.
+
+
+
+
+ );
+}
+
+Activity.requireAuth = true;