diff --git a/frontend/app/components/DataManagement/Activity/ColumnsModal.tsx b/frontend/app/components/DataManagement/Activity/ColumnsModal.tsx
new file mode 100644
index 000000000..7048aed55
--- /dev/null
+++ b/frontend/app/components/DataManagement/Activity/ColumnsModal.tsx
@@ -0,0 +1,56 @@
+import React from 'react';
+import { Input, Checkbox, Button } from 'antd';
+
+function ColumnsModal({
+ columns,
+ onSelect,
+ hiddenCols,
+}: {
+ columns: { title: string; key: string }[];
+ onSelect: (col: string[]) => void;
+ hiddenCols: string[];
+}) {
+ const [query, setQuery] = React.useState('');
+ const [selected, setSelected] = React.useState(
+ columns.map((col) => col.key).filter((col) => !hiddenCols.includes(col))
+ );
+
+ const onConfirm = () => {
+ onSelect(selected);
+ };
+ const onToggle = (col: string, isSelected: boolean) => {
+ const newList = isSelected
+ ? [...selected, col]
+ : selected.filter((c) => c !== col);
+ setSelected(newList);
+ };
+
+ const searchRe = new RegExp(query, 'ig');
+ const filteredList = columns.filter((col) => searchRe.test(col.title));
+ return (
+
+
Show/Hide Columns
+
+ Select columns to display. Rearrange them in the table view.
+
+
setQuery(e.target.value)}
+ />
+ {filteredList.map((col) => (
+ onToggle(col.key, e.target.checked)}
+ checked={selected.includes(col.key)}
+ >
+ {col.title}
+
+ ))}
+
+
+ );
+}
+
+export default ColumnsModal;
diff --git a/frontend/app/components/DataManagement/Activity/Page.tsx b/frontend/app/components/DataManagement/Activity/Page.tsx
index 5260fd43b..b96516edf 100644
--- a/frontend/app/components/DataManagement/Activity/Page.tsx
+++ b/frontend/app/components/DataManagement/Activity/Page.tsx
@@ -4,37 +4,49 @@ import { Table, Dropdown } from 'antd';
import { MoreOutlined } from '@ant-design/icons';
import { numberWithCommas } from 'App/utils';
import { Pagination } from 'UI';
+import OutsideClickDetectingDiv from '../../shared/OutsideClickDetectingDiv';
+import ColumnsModal from './ColumnsModal';
import Event from './data/Event';
import { useModal } from 'App/components/Modal';
-import EventDetailsModal from "./EventDetailsModal";
+import EventDetailsModal from './EventDetailsModal';
import { useQuery } from '@tanstack/react-query';
const limit = 100;
-const fetcher = async (page: number): Promise<{ list: any[], total: number }> => {
+const fetcher = async (
+ page: number
+): Promise<{ list: any[]; total: number }> => {
const total = 3000;
return new Promise((resolve) => {
const testEv = new Event({
- name: 'test ev',
+ name: 'test ev #' + page,
time: Date.now(),
- defaultFields: { userId: '123', userCity: 'NY', userEnvironment: 'Mac OS' },
+ defaultFields: {
+ userId: '123',
+ userCity: 'NY',
+ userEnvironment: 'Mac OS',
+ },
customFields: {},
isAutoCapture: false,
- sessionId: '123123'
+ sessionId: '123123',
});
const testAutoEv = new Event({
name: 'auto test ev',
time: Date.now(),
- defaultFields: { userId: '123', userCity: 'NY', userEnvironment: 'Mac OS' },
+ defaultFields: {
+ userId: '123',
+ userCity: 'NY',
+ userEnvironment: 'Mac OS',
+ },
customFields: {},
isAutoCapture: true,
- sessionId: '123123'
+ sessionId: '123123',
});
const list = [testEv.toData(), testAutoEv.toData()];
resolve({ list, total });
- })
-}
+ });
+};
function ActivityPage() {
const [page, setPage] = React.useState(1);
@@ -59,9 +71,9 @@ function ActivityPage() {
{
label: 'Show/Hide Columns',
key: 'edit-columns',
- onClick: () => setEditCols(true),
- }
- ]
+ onClick: () => setTimeout(() => setEditCols(true), 1),
+ },
+ ];
const columns = [
{
@@ -92,7 +104,16 @@ function ActivityPage() {
key: 'userId',
showSorterTooltip: { target: 'full-header' },
sorter: (a, b) => a.userId.localeCompare(b.userId),
- render: (text) => {text}
,
+ render: (text) => (
+ {
+ e.stopPropagation();
+ }}
+ >
+ {text}
+
+ ),
},
{
title: 'City',
@@ -110,11 +131,15 @@ function ActivityPage() {
},
{
title: (
-
-
-
-
-
+
+
+
+
+
),
dataIndex: '$__opts__$',
key: '$__opts__$',
@@ -132,8 +157,22 @@ function ActivityPage() {
};
const onItemClick = (ev: Event) => {
- showModal(, { width: 420, right: true });
- }
+ showModal(, {
+ width: 420,
+ right: true,
+ });
+ };
+
+ const onUpdateVisibleCols = (cols: string[]) => {
+ setHiddenCols((_) => {
+ return columns
+ .map((col) =>
+ cols.includes(col.key) || col.key === '$__opts__$' ? null : col.key
+ )
+ .filter(Boolean);
+ });
+ setEditCols(false);
+ };
return (
-
-
- All users activity
-
-
({
- onClick: (event) => onItemClick(record)
- })}
- dataSource={list}
- pagination={false}
- columns={shownCols}
- />
-
-
- {'Showing '}
-
{(page - 1) * limit + 1}
- {' to '}
-
- {(page - 1) * limit + list.length}
-
- {' of '}
-
{numberWithCommas(total)}
- {' events.'}
+
+ {editCols ? (
+
setEditCols(false)}>
+ col.key !== '$__opts__$')}
+ onSelect={onUpdateVisibleCols}
+ hiddenCols={hiddenCols}
+ />
+
+ ) : null}
+
+
+
+ All users activity
-
({
+ onClick: () => onItemClick(record),
+ })}
+ dataSource={list}
+ pagination={false}
+ columns={shownCols}
/>
+
+
+ {'Showing '}
+ {(page - 1) * limit + 1}
+ {' to '}
+
+ {(page - 1) * limit + list.length}
+
+ {' of '}
+ {numberWithCommas(total)}
+ {' events.'}
+
+
+
diff --git a/frontend/app/routes.ts b/frontend/app/routes.ts
index a3b399e35..25eb70c14 100644
--- a/frontend/app/routes.ts
+++ b/frontend/app/routes.ts
@@ -53,7 +53,6 @@ export const setQueryParams = (location: Location, params: Record
):
};
export const login = (): string => '/login';
-export const spotLogin = (): string => '/spot-login';
export const signup = (): string => '/signup';
export const forgotPassword = (): string => '/reset-password';
@@ -196,6 +195,8 @@ const REQUIRED_SITE_ID_ROUTES = [
usabilityTestingView(''),
highlights(),
+
+ dataManagement.activity(),
];
const routeNeedsSiteId = (path: string): boolean => REQUIRED_SITE_ID_ROUTES.some(r => path.startsWith(r));
const siteIdToUrl = (siteId = ':siteId'): string => {
diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json
index aab188729..a4ffea2c7 100644
--- a/frontend/tsconfig.json
+++ b/frontend/tsconfig.json
@@ -2,7 +2,7 @@
"compilerOptions": {
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
- "noImplicitAny": true,
+ "noImplicitAny": false,
"alwaysStrict": true,
"strictNullChecks": true,
"skipLibCheck": true,