Skip to content

Commit d6f0f5f

Browse files
Merge pull request #1405 from inplayer-org/improvement/use-analytics-hook
new useAnalytics hook
2 parents 486100f + f868113 commit d6f0f5f

12 files changed

+255
-184
lines changed

.eslintrc

+9-17
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,15 @@
6969
"linebreak-style": "off",
7070
"no-debugger": "off",
7171
"no-alert": "off",
72-
"no-use-before-define": "warn",
73-
"no-unused-vars": [
72+
"no-use-before-define": "off",
73+
"@typescript-eslint/no-use-before-define": ["error"],
74+
"no-unused-vars": "off",
75+
"@typescript-eslint/no-unused-vars": [
7476
"warn",
7577
{
76-
"argsIgnorePattern": "res|next|^err"
78+
"argsIgnorePattern": "res|next|^err|^_",
79+
"varsIgnorePattern": "^_",
80+
"caughtErrorsIgnorePattern": "^_"
7781
}
7882
],
7983
"prefer-const": [
@@ -110,20 +114,8 @@
110114
"consistent-return": "off",
111115
"jsx-a11y/accessible-emoji": "off",
112116
"radix": "off",
113-
"no-shadow": [
114-
2,
115-
{
116-
"hoist": "all",
117-
"allow": [
118-
"resolve",
119-
"reject",
120-
"done",
121-
"next",
122-
"err",
123-
"error"
124-
]
125-
}
126-
],
117+
"no-shadow": "off",
118+
"@typescript-eslint/no-shadow": ["warn"],
127119
"quotes": [
128120
2,
129121
"single",

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
# [2.5.24] - 09.03.2022
6+
7+
## Added
8+
9+
- New `useAnalytics` hook as an alternative to `AnalyticsComponent`
10+
511
# [2.5.23] - 21.02.2022
612

713
## Change

index.d.ts

+7
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,13 @@ export interface ContainerProps extends AnalyticsProps{
140140
alignContent?: string;
141141
}
142142

143+
declare type TrackParams = Pick<Event, 'event' | 'type' | 'tag'> & Partial<Pick<Event, 'pages' | 'merchantId' | 'ip'>>;
144+
145+
export declare const useAnalytics: () => {
146+
track: (trackParams: TrackParams) => void;
147+
trackCallback: (trackParams: TrackParams) => () => void;
148+
};
149+
143150
export interface CellProps extends AnalyticsProps{
144151
className?: string;
145152
width?: number;

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@inplayer-org/inplayer-ui",
33
"sideEffects": false,
4-
"version": "2.5.23",
4+
"version": "2.5.24",
55
"author": "InPlayer",
66
"description": "InPlayer React UI Components",
77
"main": "dist/inplayer-ui.cjs.js",
@@ -107,4 +107,4 @@
107107
"formik": "^2.1.5",
108108
"yup": "^0.32.11"
109109
}
110-
}
110+
}

src/analytics/AnalyticsComponent.tsx

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import React, { ReactNode } from 'react';
2+
import { AnalyticsContext, AnalyticsContextValue } from './AnalyticsPage';
3+
4+
export type AnalyticsComponentProps = {
5+
children: (context: AnalyticsContextValue) => ReactNode;
6+
};
7+
8+
/** A component to wrap other components with to gain access to the AnalyticsContextValue. */
9+
const AnalyticsComponent = ({ children }: AnalyticsComponentProps) => (
10+
<AnalyticsContext.Consumer>{children}</AnalyticsContext.Consumer>
11+
);
12+
13+
export default AnalyticsComponent;

src/analytics/AnalyticsPage.tsx

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import React, { createContext } from 'react';
2+
import AnalyticsTracker from './AnalyticsTracker';
3+
4+
export type AnalyticsTag = string;
5+
6+
export enum AnalyticsPageType {
7+
PAGE = 'page',
8+
MODAL = 'modal',
9+
TAB = 'tab',
10+
}
11+
12+
export interface AnalyticsPageObject {
13+
tag: AnalyticsTag;
14+
type: AnalyticsPageType;
15+
}
16+
17+
export interface AnalyticsContextValue {
18+
pages: AnalyticsPageObject[];
19+
tracker: AnalyticsTracker;
20+
merchantId: number;
21+
ip: string;
22+
}
23+
24+
export const ROOT_ANALYTICS_CONTEXT: AnalyticsContextValue = {
25+
pages: [],
26+
tracker: new AnalyticsTracker(),
27+
merchantId: 0,
28+
ip: '',
29+
};
30+
31+
export const AnalyticsContext = createContext(ROOT_ANALYTICS_CONTEXT);
32+
33+
export interface AnalyticsPageProps {
34+
/** Tag of this page. */
35+
tag: AnalyticsTag;
36+
37+
/** Type of this page. */
38+
type: AnalyticsPageType;
39+
40+
/** Children in the page. */
41+
children?: React.ReactNode;
42+
43+
/** merchant id */
44+
merchantId?: number;
45+
46+
/** user ip address */
47+
ip?: string;
48+
}
49+
50+
/** Registers a subpage in the analytics component hierarchy. */
51+
const AnalyticsPageComponent = ({
52+
tag,
53+
type,
54+
children,
55+
merchantId: mid,
56+
ip: ipAddress,
57+
}: AnalyticsPageProps) => (
58+
<AnalyticsContext.Consumer>
59+
{({ pages, tracker, merchantId, ip }) => (
60+
<AnalyticsContext.Provider
61+
value={{
62+
pages: [...pages, { tag, type }],
63+
tracker,
64+
merchantId: mid || merchantId,
65+
ip: ipAddress || ip,
66+
}}
67+
>
68+
{children}
69+
</AnalyticsContext.Provider>
70+
)}
71+
</AnalyticsContext.Consumer>
72+
);
73+
74+
export default AnalyticsPageComponent;

src/analytics/AnalyticsTracker.ts

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { AnalyticsPageObject, AnalyticsTag } from './AnalyticsPage';
2+
3+
export enum AnalyticsEvents {
4+
CLICK = 'click',
5+
DROPDOWN_CHANGE = 'dropdown_change',
6+
SWITCH_ON = 'switch_on',
7+
SWITCH_OFF = 'switch_off',
8+
DROPDOWN_SELECT = 'dropdown_select',
9+
CHECKBOX_ON = 'checkbox_on',
10+
CHECKBOX_OFF = 'checkbox_off',
11+
RADIOBUTTON_SELECT = 'radiobutton_select',
12+
DATEPICKER_CHANGE = 'datepicker_date_change',
13+
DAYPICKER_CHANGE = 'daypicker_date_change',
14+
KEYBOARD_EVENT = 'keyboard_event',
15+
FOCUS_OUT = 'focus_out',
16+
}
17+
18+
export enum AnalyticsComponentType {
19+
BUTTON = 'button',
20+
DROPDOWN = 'dropdown',
21+
SWITCH = 'switch',
22+
PAGINATION = 'pagination',
23+
ICON = 'icon',
24+
LINK = 'link',
25+
CHECKBOX = 'checkbox',
26+
DATEPICKER = 'datepicker',
27+
DAYPICKER = 'daypicker',
28+
DATEPICKER_PRESET = 'datepicker_preset',
29+
TAB = 'tab',
30+
ACCORDION = 'accordion',
31+
MODAL = 'modal',
32+
INPUT = 'input',
33+
TEXTAREA = 'textarea',
34+
TAB_NAVIGATION = 'tab_navigation',
35+
RADIO = 'radio',
36+
}
37+
38+
export interface TrackEvent {
39+
event: AnalyticsEvents;
40+
type: AnalyticsComponentType;
41+
tag: AnalyticsTag;
42+
pages: AnalyticsPageObject[];
43+
merchantId: number;
44+
ip: string;
45+
}
46+
47+
export type AnalyticsHandlerFn = (event: TrackEvent) => void;
48+
49+
export default class AnalyticsTracker {
50+
handlers: AnalyticsHandlerFn[] = [];
51+
52+
registerHandler = (fn: AnalyticsHandlerFn) => {
53+
this.handlers.push(fn);
54+
55+
return () => {
56+
this.unregisterHandler(fn);
57+
};
58+
};
59+
60+
unregisterHandler = (fn: AnalyticsHandlerFn) => {
61+
this.handlers = this.handlers.filter((handler) => handler !== fn);
62+
};
63+
64+
track = (event: TrackEvent) => {
65+
this.handlers.forEach((handler) => handler(event));
66+
};
67+
}

src/analytics/externalTypes.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { AnalyticsTag } from './AnalyticsPage';
2+
3+
export interface AnalyticsProps {
4+
/** Unique identifier of the component within the logical page hierarchy. */
5+
tag?: AnalyticsTag;
6+
7+
/** Posiition of the component within a table-like component. */
8+
position?: {
9+
/** Unique ID of the row (usually what you would use as a key in react). */
10+
id: string;
11+
12+
/** Row index. */
13+
row?: number;
14+
15+
/** Column index or name. */
16+
column?: number | string;
17+
};
18+
}

src/analytics/index.ts

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
export {
2+
default as AnalyticsPage,
3+
ROOT_ANALYTICS_CONTEXT,
4+
AnalyticsContext,
5+
} from './AnalyticsPage';
6+
7+
export {
8+
default as AnalyticsTracker,
9+
AnalyticsEvents,
10+
AnalyticsComponentType,
11+
} from './AnalyticsTracker';
12+
13+
export { default as AnalyticsComponent, AnalyticsComponentProps } from './AnalyticsComponent';
14+
15+
export { default as useAnalytics } from './useAnalytics';
16+
17+
export type {
18+
AnalyticsTag,
19+
AnalyticsContextValue,
20+
AnalyticsPageProps,
21+
AnalyticsPageType,
22+
} from './AnalyticsPage';
23+
24+
export type { TrackEvent as Event, AnalyticsHandlerFn } from './AnalyticsTracker';
25+
26+
export type { AnalyticsProps } from './externalTypes';

0 commit comments

Comments
 (0)