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:
@@ -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 "$@"
|
||||
|
||||
@@ -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>',
|
||||
};
|
||||
|
||||
@@ -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 () => {
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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}`);
|
||||
}
|
||||
|
||||
@@ -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']}>
|
||||
|
||||
@@ -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));
|
||||
};
|
||||
|
||||
@@ -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())
|
||||
|
||||
16
src/services/clickStream/api/janusApi.ts
Normal file
16
src/services/clickStream/api/janusApi.ts
Normal 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;
|
||||
31
src/services/clickStream/constants/index.ts
Normal file
31
src/services/clickStream/constants/index.ts
Normal 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;
|
||||
23
src/services/clickStream/constants/values.ts
Normal file
23
src/services/clickStream/constants/values.ts
Normal 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,
|
||||
};
|
||||
23
src/services/clickStream/events.ts
Normal file
23
src/services/clickStream/events.ts
Normal 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;
|
||||
23
src/services/clickStream/index.ts
Normal file
23
src/services/clickStream/index.ts
Normal 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;
|
||||
34
src/services/clickStream/payload.ts
Normal file
34
src/services/clickStream/payload.ts
Normal 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;
|
||||
34
src/services/clickStream/types/index.d.ts
vendored
Normal file
34
src/services/clickStream/types/index.d.ts
vendored
Normal 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;
|
||||
1
src/services/constants.ts
Normal file
1
src/services/constants.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const JANUS_API = `${window?.config?.JANUS_API_URL}/events/json`;
|
||||
1
src/types/index.d.ts
vendored
1
src/types/index.d.ts
vendored
@@ -8,6 +8,7 @@ interface AppConfig {
|
||||
CSP_HEADER: string;
|
||||
DISABLE_UNIVERSAL_AUTH: string;
|
||||
TABLEAU_SERVER_URL: string;
|
||||
JANUS_API_URL: string;
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
||||
Reference in New Issue
Block a user