TP-46224 | houston clickstream impl (#87)

* TP-46224 | initial setup done

* TP-46224 | one event added

* TP-46224 | more events added

* TP-46224 | landding page events added

* TP-46224 | review comments resolved

* TP-46224 | testing

* TP-46224 | useRef removed

* TP-46224 | janus link added

* TP-46224 | comment resolved
This commit is contained in:
Ayush Ranjan
2023-11-09 13:41:50 +05:30
committed by GitHub
parent 87306b8712
commit ad7ee95df8
17 changed files with 252 additions and 10 deletions

View File

@@ -7,6 +7,6 @@ sed -i "s~<BASE_API_URL>~${BASE_API_URL}~g" /usr/share/nginx/html/config.js
sed -i "s~<DISABLE_UNIVERSAL_AUTH>~${DISABLE_UNIVERSAL_AUTH}~g" /usr/share/nginx/html/config.js
sed -i "s~CSP_HEADER~${CSP_HEADER}~g" /etc/nginx/conf.d/nginx.conf
sed -i "s~<TABLEAU_SERVER_URL>~${TABLEAU_SERVER_URL}~g" /usr/share/nginx/html/config.js
sed -i "s~<JANUS_API_URL>~${JANUS_API_URL}~g" /usr/share/nginx/html/config.js
exec "$@"

View File

@@ -6,4 +6,5 @@ window.config = {
CSP_HEADER: '<CSP_HEADER>',
DISABLE_UNIVERSAL_AUTH: '<DISABLE_UNIVERSAL_AUTH>',
TABLEAU_SERVER_URL: '<TABLEAU_SERVER_URL>',
JANUS_API_URL: '<JANUS_API_URL>',
};

View File

@@ -4,6 +4,8 @@ import { toast } from '@navi/web-ui/lib/primitives/Toast/index';
import FallbackComponent from '@src/components/Fallback';
import { ApiService } from '@src/services/api';
import useClickStream from '@src/services/clickStream';
import { CLICK_STREAM_EVENT_FACTORY } from '@src/services/clickStream/constants/values';
import { FETCH_INCIDENTS_DATA } from './constants';
import SearchResultsTable from './partials/SearchResultsTable';
import DashboardHeader from './partials/DashboardHeader';
@@ -26,6 +28,9 @@ const Dashboard: FC = () => {
);
const searchParamRef = useRef('');
const { fireEvent } = useClickStream();
const { EVENT_NAME, SCREEN_NAME } = CLICK_STREAM_EVENT_FACTORY;
const startIncidentSearch = (param = pageNumberRef.current): void => {
const endPoint = FETCH_INCIDENTS_DATA(param);
setIsLoading(true);
@@ -48,6 +53,12 @@ const Dashboard: FC = () => {
});
};
useEffect(() => {
fireEvent(EVENT_NAME.Houston_dashboard_Land, {
screen_name: SCREEN_NAME.DASHBOARD_PAGE,
});
}, []);
useEffect(() => {
startIncidentSearch();
return () => {

View File

@@ -5,6 +5,8 @@ import { Dayjs } from 'dayjs';
import dayjs from 'dayjs';
import styles from './DashboardHeader.module.scss';
import { Button } from '@navi/web-ui/lib/primitives';
import useClickStream from '@src/services/clickStream';
import { CLICK_STREAM_EVENT_FACTORY } from '@src/services/clickStream/constants/values';
export interface DateProps {
setSelectedDate: (param: Array<string>) => void;
@@ -16,6 +18,10 @@ const Date: React.FC<DateProps> = (props: DateProps) => {
const { fetchIncidentData } = props;
const [date, setDate] = useState<string[]>([]);
const [open, setOpen] = useState(false);
const { fireEvent } = useClickStream();
const { EVENT_NAME, SCREEN_NAME } = CLICK_STREAM_EVENT_FACTORY;
const disabledDate = (current: Dayjs) => {
if (current != null) {
return current && current > dayjs().endOf('day');
@@ -73,6 +79,9 @@ const Date: React.FC<DateProps> = (props: DateProps) => {
};
const handleApplyClick = () => {
fireEvent(EVENT_NAME.Houston_Check_DateFilter, {
screen_name: SCREEN_NAME.DASHBOARD_PAGE,
});
if (date.length === 2) {
const start_date = date[0];
const end_date = date[1];

View File

@@ -4,6 +4,8 @@ import { AgTable, Pagination } from '@navi/web-ui/lib/components';
import { Tag, Drawer } from '@navi/web-ui/lib/primitives';
import { returnFormattedDate } from '@src/services/globalUtils';
import DrawerMode from '@src/Pages/Incidents/DrawerMode/index';
import useClickStream from '@src/services/clickStream';
import { CLICK_STREAM_EVENT_FACTORY } from '@src/services/clickStream/constants/values';
import styles from '../SearchResultsTable.module.scss';
import { getSeverityColor } from '../constants';
import cx from 'classnames';
@@ -35,6 +37,8 @@ const SearchResultsTable: FC<SearchResultTableProps> = ({
const [drawerState, setDrawerState] = useState<boolean>(false);
const incidentData = useRef<any>({});
const navigate = useNavigate();
const { fireEvent } = useClickStream();
const { EVENT_NAME, SCREEN_NAME } = CLICK_STREAM_EVENT_FACTORY;
const cellStyle = {
'text-overflow': 'ellipsis',
@@ -132,6 +136,9 @@ const SearchResultsTable: FC<SearchResultTableProps> = ({
};
const handleRowClick = (event: any) => {
fireEvent(EVENT_NAME.Houston_Check_Incident, {
screen_name: SCREEN_NAME.DASHBOARD_PAGE,
});
if (event?.data) {
navigate(`/incident/${event.data?.id}`);
}

View File

@@ -1,10 +1,21 @@
import { FC } from 'react';
import { FC, useRef, useEffect } from 'react';
import Typography from '@navi/web-ui/lib/primitives/Typography';
import { TableauEmbed } from '@stoddabr/react-tableau-embed-live';
import useClickStream from '@src/services/clickStream';
import { CLICK_STREAM_EVENT_FACTORY } from '@src/services/clickStream/constants/values';
import { TABLEAU_SDK_VERSION, TABLEAU_URL } from './constants';
import styles from './Tableau.module.scss';
const Tableau: FC = () => {
const { fireEvent } = useClickStream();
const { EVENT_NAME, SCREEN_NAME } = CLICK_STREAM_EVENT_FACTORY;
useEffect(() => {
fireEvent(EVENT_NAME.Houston_Metric_Land, {
screen_name: SCREEN_NAME.METRIC_PAGE,
});
}, []);
return (
<div className={styles['incident-body']}>
<div className={styles['tableau-wrapper']}>

View File

@@ -1,8 +1,10 @@
import { FC, useEffect, useState } from 'react';
import { FC, useEffect, useState, useRef } from 'react';
import Typography from '@navi/web-ui/lib/primitives/Typography';
import { toast } from '@navi/web-ui/lib/primitives/Toast';
import FallbackComponent from '@src/components/Fallback';
import { ApiService } from '@src/services/api';
import useClickStream from '@src/services/clickStream';
import { CLICK_STREAM_EVENT_FACTORY } from '@src/services/clickStream/constants/values';
import { FETCH_TEAM_DATA } from './constants';
import TeamResultsTable from './partials/TeamResultsTable';
import CreateTeam from './partials/CreateTeam';
@@ -26,6 +28,9 @@ const Team: FC = () => {
);
const Role = useAuthData();
const { fireEvent } = useClickStream();
const { EVENT_NAME, SCREEN_NAME } = CLICK_STREAM_EVENT_FACTORY;
const startTeamSearch = (createdTeamId?: number): void => {
const endPoint = FETCH_TEAM_DATA;
dispatch(setIsLoading(true));
@@ -62,6 +67,12 @@ const Team: FC = () => {
fetchAllBots();
}, []);
useEffect(() => {
fireEvent(EVENT_NAME.Houston_Team_Land, {
screen_name: SCREEN_NAME.TEAM_PAGE,
});
}, []);
const createHandler = () => {
dispatch(setModalOpen(true));
};

View File

@@ -9,13 +9,8 @@ import {
Typography,
} from '@navi/web-ui/lib/primitives';
import { InfoIcon } from '@navi/web-ui/lib/icons';
import {
FETCH_SINGLE_TEAM_DATA,
TeamFormProps,
UPDATE_TEAM_DATA,
} from '../constants';
import useClickStream from '@src/services/clickStream';
import { CLICK_STREAM_EVENT_FACTORY } from '@src/services/clickStream/constants/values';
import { ApiService } from '@src/services/api';
import MembersDetails from '@src/components/MembersDetails';
import DrawerStyles from '@src/Pages/Incidents/DrawerMode/DrawerMode.module.scss';
@@ -23,6 +18,11 @@ import styles from '../Team.module.scss';
import { ConfigProvider, Select, ThemeConfig } from 'antd';
import { getBots } from '../bots';
import SlackIcon from '@src/assets/SlackIcon';
import {
FETCH_SINGLE_TEAM_DATA,
TeamFormProps,
UPDATE_TEAM_DATA,
} from '../constants';
const TeamForm = (props: TeamFormProps) => {
const { teamId, isExpanded, setLastUpdatedAt } = props;
@@ -35,6 +35,9 @@ const TeamForm = (props: TeamFormProps) => {
const [psecOncallHandle, setPsecOncallHandle] = useState<string>('');
const [showTooltip, setShowTooltip] = useState<boolean>(false);
const { fireEvent } = useClickStream();
const { EVENT_NAME, SCREEN_NAME } = CLICK_STREAM_EVENT_FACTORY;
const fetchTeamById = (updateDate = false, showMainLoader = true) => {
const endPoint = FETCH_SINGLE_TEAM_DATA(teamId);
if (showMainLoader) setIsLoading(true);
@@ -65,6 +68,9 @@ const TeamForm = (props: TeamFormProps) => {
}, [teamId, isExpanded]);
const addMemberHandler = (): void => {
fireEvent(EVENT_NAME.Houston_Add_Member, {
screen_name: SCREEN_NAME.TEAM_PAGE,
});
const endPoint = UPDATE_TEAM_DATA();
const finalSlackData = slackUserEmails?.includes(',')
? slackUserEmails.split(',').map(item => item?.trim())

View File

@@ -0,0 +1,16 @@
import { ApiService } from '../../api';
import { ClickStreamPayload } from '../types';
import { JANUS_API } from '@src/services/constants';
const useJanusApi = (): {
fireClickStreamPayload: (payload) => Promise<void>;
} => {
const janusServiceUrl = `${JANUS_API}`;
const fireClickStreamPayload = (payload: ClickStreamPayload): Promise<any> =>
ApiService.post(janusServiceUrl, { ...payload });
return { fireClickStreamPayload };
};
export default useJanusApi;

View File

@@ -0,0 +1,31 @@
import { useMemo } from 'react';
import { BasePayload } from '../types';
import { appName, eventsSource, eventBufferKey } from './values';
export { eventBufferKey };
const useConstants = (): { basePayload: BasePayload } => {
const { userAgent, vendor } = window.navigator;
const storedEmail = localStorage.getItem('email-id');
const basePayload = useMemo<BasePayload>(() => {
return {
app: {
name: appName,
},
device: {
model: userAgent,
manufacturer: vendor,
},
source: eventsSource,
user: {
customer_id: storedEmail || 'unknown',
},
};
}, [userAgent, vendor]);
return { basePayload };
};
export default useConstants;

View File

@@ -0,0 +1,23 @@
export const appName = 'houston-portal';
export const eventsSource = 'HoustonPortal';
export const eventBufferKey = 'clickStreamEvents';
const EVENT_NAME = {
Houston_Team_Land: 'Houston_Team_Land',
Houston_dashboard_Land: 'Houston_dashboard_Land',
Houston_Metric_Land: 'Houston_Metric_Land',
Houston_Add_Member: 'Houston_Add_Member',
Houston_Check_DateFilter: 'Houston_Check_DateFilter',
Houston_Check_Incident: 'Houston_Check_Incident',
};
const SCREEN_NAME = {
TEAM_PAGE: 'team_page',
DASHBOARD_PAGE: 'dashboard_page',
METRIC_PAGE: 'metric_page',
};
export const CLICK_STREAM_EVENT_FACTORY = {
EVENT_NAME,
SCREEN_NAME,
};

View File

@@ -0,0 +1,23 @@
import { Timestamp, ClickStreamEvent } from './types';
const useEvents = (): {
makeEvent: (...args: any) => any;
} => {
const makeEvent = (
eventName: string,
timestamp: Timestamp,
attributes: Record<string, string>,
): ClickStreamEvent[] => [
{
event_name: eventName,
timestamp,
attributes,
},
];
return {
makeEvent,
};
};
export default useEvents;

View File

@@ -0,0 +1,23 @@
import useJanusApi from './api/janusApi';
import useEvents from './events';
import usePayload from './payload';
const useClickStream = (): {
fireEvent: (event: string, attributes: Record<string, string>) => void;
} => {
const { makeEvent } = useEvents();
const { createPayload } = usePayload();
const { fireClickStreamPayload } = useJanusApi();
const fireEvent = (
event: string,
attributes: Record<string, string>,
): void => {
const finalEvent = makeEvent(event, Date.now(), attributes);
fireClickStreamPayload(createPayload(finalEvent));
};
return { fireEvent };
};
export default useClickStream;

View File

@@ -0,0 +1,34 @@
import {
BasePayload,
ClickStreamEvent,
ClickStreamPayload,
EventsPayload,
} from './types';
import useConstants from './constants';
const usePayload = (): {
createPayload: (events: ClickStreamEvent[]) => ClickStreamPayload;
} => {
const { basePayload } = useConstants();
const makePayload = (
basePayload: BasePayload,
eventsPayload: EventsPayload,
): ClickStreamPayload => ({
...basePayload,
...eventsPayload,
});
const createPayload = (events: ClickStreamEvent[]): ClickStreamPayload => {
const timestamp = Date.now();
const eventsPayload = {
events,
client_ts: timestamp,
};
return makePayload(basePayload, eventsPayload);
};
return { createPayload };
};
export default usePayload;

View File

@@ -0,0 +1,34 @@
export type Timestamp = number;
export interface AppInfo {
name: string;
}
export interface DeviceInfo {
model: string;
manufacturer: string;
}
export interface ClickStreamEvent {
event_name: string;
timestamp: Timestamp;
attributes?: Record<string, string>;
}
export interface UserInfo {
customer_id: string | unknown;
}
export interface BasePayload {
app: AppInfo;
device: DeviceInfo;
source: string;
user: UserInfo;
}
export interface EventsPayload {
client_ts: Timestamp;
events: ClickStreamEvent[];
}
export type ClickStreamPayload = BasePayload & EventsPayload;

View File

@@ -0,0 +1 @@
export const JANUS_API = `${window?.config?.JANUS_API_URL}/events/json`;

View File

@@ -8,6 +8,7 @@ interface AppConfig {
CSP_HEADER: string;
DISABLE_UNIVERSAL_AUTH: string;
TABLEAU_SERVER_URL: string;
JANUS_API_URL: string;
}
declare global {