Skip to content

Commit a15b32e

Browse files
committed
feat(User Interaction): Get closest ancestor react component
If internal components are not tracking-enabled, use data-attribute to target the closest React component upon a DOM event
1 parent 9802c6d commit a15b32e

File tree

21 files changed

+332
-30
lines changed

21 files changed

+332
-30
lines changed

dist/react/components/withTracking.d.ts.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/react/components/withTracking.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,17 @@ export function withTracking(Component) {
3434
return function (props) {
3535
var eventHandlers = {};
3636
var trackers = props.trackers, origin = props.origin, dataContextFromProps = props.dataContext, originalProps = __rest(props, ["trackers", "origin", "dataContext"]);
37-
var dataContext = useContext(DataContext);
38-
if (dataContextFromProps) {
39-
dataContext = dataContextFromProps;
40-
}
37+
var dataContext = dataContextFromProps ? dataContextFromProps : useContext(DataContext);
4138
function trackUserInteraction(e, tracker) {
4239
var targetNode = e.target;
4340
var value = getValueFromNode(e);
44-
var userInteractionResource = UserInteraction.generateResource(dataContext.app, tracker.action, __assign(__assign({ context: dataContext.context }, (originalProps.origin && {
45-
origin: originalProps.origin
46-
})), { component: Component.displayName || Component.name, element: __assign({ currentTarget: e.currentTarget.nodeName, target: targetNode.nodeName || e.currentTarget.nodeName, innerHTML: targetNode.innerHTML, innerText: targetNode.innerText }, (value && {
41+
var closestComponent = targetNode.closest('[data-element-type="component"]');
42+
var userInteractionResource = UserInteraction.generateResource(dataContext.app, tracker.action, __assign(__assign({ context: dataContext.context }, (origin && {
43+
origin: origin,
44+
})), { component: {
45+
currentTarget: Component.displayName || Component.name,
46+
target: closestComponent ? closestComponent.getAttribute('data-display-name') : null
47+
}, element: __assign({ currentTarget: e.currentTarget.nodeName, target: targetNode.nodeName || e.currentTarget.nodeName, innerHTML: targetNode.innerHTML, innerText: targetNode.innerText }, (value && {
4748
value: value,
4849
})) }), tracker.data);
4950
tracker.track(e, userInteractionResource);

dist/resources/userInteractionResource.d.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ export interface UserInteractionResource extends BaseResource {
99
source: {
1010
context: string;
1111
origin?: string;
12-
component: string;
12+
component: {
13+
currentTarget: string;
14+
target: string | null;
15+
};
1316
element: {
1417
currentTarget: string;
1518
target: string;

dist/resources/userInteractionResource.d.ts.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,24 @@
99
"@types/jest": "^26.0.15",
1010
"@types/node": "^12.0.0",
1111
"@types/pako": "^1.0.1",
12-
"@types/react": "^17.0.0",
13-
"@types/react-dom": "^17.0.0",
1412
"localforage": "^1.9.0",
1513
"pako": "^2.0.3",
16-
"react": "^17.0.1",
17-
"react-dom": "^17.0.1",
1814
"react-router": "^5.2.0",
1915
"react-scripts": "4.0.3",
2016
"typescript": "^4.1.2",
2117
"web-vitals": "^2.0.1",
2218
"workerize-loader": "^1.3.0"
2319
},
20+
"peerDependencies": {
21+
"@types/react": "^17.0.0",
22+
"@types/react-dom": "^17.0.0",
23+
"react": "^17.0.1",
24+
"react-dom": "^17.0.1"
25+
},
2426
"scripts": {
2527
"start": "react-scripts start",
26-
"build": "react-scripts build",
28+
"build-scripts": "react-scripts build",
29+
"build": "npm run tsc",
2730
"test": "react-scripts test",
2831
"eject": "react-scripts eject",
2932
"storybook": "start-storybook -p 6006 -s public",
@@ -65,6 +68,8 @@
6568
"@storybook/react": "^6.1.18",
6669
"@types/styled-components": "^5.1.8",
6770
"antd": "^4.12.3",
71+
"react": "^17.0.1",
72+
"react-dom": "^17.0.1",
6873
"styled-components": "^5.2.1",
6974
"typedoc": "^0.21.2"
7075
}

src/examples/components/elements/Button/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ function Button(props: ButtonProps) {
2626

2727
return (
2828
<AntButton
29+
data-element-type="component"
30+
data-display-name="Button"
2931
{...rest}
3032
onClick={onClick}
3133
>

src/examples/components/elements/Header/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ function Header(props: HeaderProps) {
1111

1212
return (
1313
<PageHeader
14+
data-element-type="component"
15+
data-display-name="Header"
1416
{...props}
1517
/>
1618
);

src/examples/components/elements/Input/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ function Input(props: InputProps) {
1515

1616
return (
1717
<AntInput
18+
data-element-type="component"
19+
data-display-name="Input"
1820
{...props}
1921
/>
2022
);

src/examples/components/elements/Menu/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ function Menu(props: MenuProps) {
1616

1717
return (
1818
<AntMenu
19+
data-element-type="component"
20+
data-display-name="Menu"
1921
theme={theme}
2022
mode={mode}
2123
defaultSelectedKeys={defaultSelectedKeys}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { action } from '@storybook/addon-actions';
2+
import { Story } from '@storybook/react/types-6-0';
3+
4+
import TrackingOnTopLevel from './index';
5+
6+
export default {
7+
title: 'Components/Pages/Tracking on top level',
8+
component: TrackingOnTopLevel,
9+
argTypes: {
10+
mode: {
11+
control: {
12+
type: 'select',
13+
options: [
14+
"horizontal",
15+
"vertical",
16+
"vertical-left",
17+
"vertical-right",
18+
"inline",
19+
],
20+
},
21+
},
22+
defaultSelectedKeys: {
23+
control: {
24+
type: 'array',
25+
}
26+
}
27+
},
28+
};
29+
30+
const Template: Story<any> = (args) => {
31+
return (
32+
<TrackingOnTopLevel />
33+
)
34+
};
35+
36+
export const Default = Template.bind({});
37+
38+
Default.args = {};
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
2+
import UserInteractionResource, { UserInteraction } from 'library/resources/userInteractionResource';
3+
import { DataContext } from 'library/react/contexts/dataContext';
4+
5+
import MenuItem from '../../elements/Menu/MenuItem';
6+
import { LandingPageWithTracking } from '../../templates/LandingPageTwo';
7+
8+
export interface TopLevelProps {
9+
10+
}
11+
12+
const data = {
13+
context: "Tracking on top level",
14+
app: {
15+
version: "1",
16+
},
17+
} as UserInteraction.DataContext;
18+
19+
function TrackingOnTopLevel(props: TopLevelProps) {
20+
21+
function logEvent(
22+
event: React.MouseEvent<HTMLElement, MouseEvent>,
23+
interactionResource: UserInteractionResource
24+
) {
25+
// tracking logic goes here
26+
console.log("logEvent");
27+
console.log(interactionResource);
28+
}
29+
30+
const landingPageProps = {
31+
items: ["Landing 1", "Landing 2", "Landing 3"],
32+
}
33+
34+
return (
35+
<DataContext.Provider value={data}>
36+
<LandingPageWithTracking
37+
{...landingPageProps}
38+
trackers={[
39+
{
40+
action: "onClick",
41+
track: logEvent,
42+
},
43+
{
44+
action: "onMouseOver",
45+
track: logEvent,
46+
}
47+
]}
48+
origin="Tracking on Top Level"
49+
>
50+
51+
{
52+
landingPageProps.items.map((item: string, i: any) => {
53+
return (
54+
<MenuItem key={`${i}`}>{item}</MenuItem>
55+
)})
56+
}
57+
58+
</LandingPageWithTracking>
59+
</DataContext.Provider>
60+
)
61+
}
62+
63+
export default TrackingOnTopLevel;

src/examples/components/templates/LandingPageOne/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ function LandingPage(props: LandingPageProps) {
103103
</NavBar>
104104
<StyledContent>
105105
<div style={headerStyle}>
106-
<h1>Let us help solve your critical website development challenges.</h1>
106+
<h1>A sample Landing page that uses tracking-enabled components</h1>
107107
</div>
108108
</StyledContent>
109109
<NewsLetter
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { action } from '@storybook/addon-actions';
2+
import { Story } from '@storybook/react/types-6-0';
3+
import MenuItem from '../../elements/Menu/MenuItem';
4+
5+
import LandingPageTwo, { LandingPageTwoProps } from './index';
6+
7+
8+
export default {
9+
title: 'Components/Templates/Landing Page: Tracking only on top level',
10+
component: LandingPageTwo,
11+
argTypes: {
12+
mode: {
13+
control: {
14+
type: 'select',
15+
options: [
16+
"horizontal",
17+
"vertical",
18+
"vertical-left",
19+
"vertical-right",
20+
"inline",
21+
],
22+
},
23+
},
24+
theme: {
25+
control: {
26+
type: 'select',
27+
options: [
28+
"light",
29+
"dark",
30+
],
31+
},
32+
},
33+
items: {
34+
control: {
35+
type: 'array',
36+
},
37+
},
38+
defaultSelectedKeys: {
39+
control: {
40+
type: 'array',
41+
}
42+
}
43+
},
44+
};
45+
46+
const Template: Story<any> = (args) => {
47+
const { items } = args;
48+
return (
49+
<LandingPageTwo {...args}>
50+
51+
{
52+
items.map((item: string, i: any) => {
53+
return (
54+
<MenuItem key={`${i}`}>{item}</MenuItem>
55+
)})
56+
}
57+
58+
</LandingPageTwo>
59+
)};
60+
61+
export const Default = Template.bind({});
62+
63+
Default.args = {
64+
items: ["Landing 1", "Landing 2", "Landing 3"],
65+
};

0 commit comments

Comments
 (0)