Skip to content

Commit 0df0272

Browse files
Merge pull request #51 from topcoder-platform/TCA-314_heap
TCA-314 Add Heap and GTM to FCC -> dev
2 parents 81c9843 + 624a624 commit 0df0272

File tree

10 files changed

+284
-123
lines changed

10 files changed

+284
-123
lines changed

client/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
"react-dom": "16.14.0",
9797
"react-final-form": "6.5.9",
9898
"react-ga": "3.3.0",
99+
"react-gtm-module": "^2.0.11",
99100
"react-helmet": "6.1.0",
100101
"react-hotkeys": "2.0.0",
101102
"react-i18next": "11.16.9",
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { FC } from 'react';
2+
import TagManager from 'react-gtm-module';
3+
4+
import {
5+
devTagManagerId,
6+
prodTagManagerId
7+
} from '../../../../config/analytics-settings';
8+
9+
import envData from '../../../../config/env.json';
10+
11+
/* eslint-disable @typescript-eslint/ban-types */
12+
const GoogleTagManager: FC<{}> = () => {
13+
// if we have an ID
14+
// then tags are supported in this environment,
15+
// so initialize them
16+
const segmentId =
17+
envData.deploymentEnv === 'staging' ? devTagManagerId : prodTagManagerId;
18+
if (segmentId) {
19+
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
20+
/* eslint-disable @typescript-eslint/no-unsafe-call */
21+
TagManager.initialize({
22+
gtmId: segmentId
23+
});
24+
}
25+
26+
return null;
27+
};
28+
29+
export default GoogleTagManager;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as GoogleTagManager } from './GoogleTagManager';
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { FC } from 'react';
2+
3+
import {
4+
devSegmentId,
5+
prodSegmentId
6+
} from '../../../../config/analytics-settings';
7+
import envData from '../../../../config/env.json';
8+
import segment from './segment-snippet';
9+
10+
interface SegmentModel {
11+
load: (id: string) => void;
12+
page: () => void;
13+
}
14+
15+
const segmentModel: SegmentModel = segment as unknown as SegmentModel;
16+
17+
/* eslint-disable @typescript-eslint/ban-types */
18+
const Segment: FC<{}> = () => {
19+
// if we have a key for this environment, load it
20+
const segmentId =
21+
envData.deploymentEnv === 'staging' ? devSegmentId : prodSegmentId;
22+
if (segmentId) {
23+
segmentModel.load(segmentId);
24+
segmentModel.page();
25+
}
26+
27+
return null;
28+
};
29+
30+
export default Segment;

client/src/analytics/segment/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default as Segment } from './Segment';
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
function SegmentSnippet() {
2+
var analytics = [];
3+
4+
if (analytics.initialize) {
5+
return;
6+
}
7+
if (analytics.invoked) {
8+
window.console &&
9+
console.error &&
10+
console.error('Segment snippet included twice.');
11+
return;
12+
}
13+
analytics.invoked = !0;
14+
analytics.methods = [
15+
'trackSubmit',
16+
'trackClick',
17+
'trackLink',
18+
'trackForm',
19+
'pageview',
20+
'identify',
21+
'reset',
22+
'group',
23+
'track',
24+
'ready',
25+
'alias',
26+
'debug',
27+
'page',
28+
'once',
29+
'off',
30+
'on',
31+
'addSourceMiddleware',
32+
'addIntegrationMiddleware',
33+
'setAnonymousId',
34+
'addDestinationMiddleware'
35+
];
36+
analytics.factory = function (t) {
37+
return function () {
38+
var e = Array.prototype.slice.call(arguments);
39+
e.unshift(t);
40+
analytics.push(e);
41+
return analytics;
42+
};
43+
};
44+
for (var t = 0; t < analytics.methods.length; t++) {
45+
var e = analytics.methods[t];
46+
analytics[e] = analytics.factory(e);
47+
}
48+
analytics.load = function (t, e) {
49+
var n = document.createElement('script');
50+
n.type = 'text/javascript';
51+
n.async = !0;
52+
n.src =
53+
'https://cdn.segment.com/analytics.js/v1/' + t + '/analytics.min.js';
54+
var a = document.getElementsByTagName('script')[0];
55+
a.parentNode.insertBefore(n, a);
56+
analytics._loadOptions = e;
57+
};
58+
analytics.SNIPPET_VERSION = '4.1.0';
59+
// analytics.load("SEGMENT_ANALYTICS_KEY"); - don't load here and let the component decide to load or not
60+
// analytics.page(); - don't call the page, each app should call it when it loads a page by itself
61+
62+
return { ...analytics };
63+
}
64+
65+
export default SegmentSnippet();

client/src/templates/Challenges/classic/desktop-layout.tsx

Lines changed: 79 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import React, { useState, ReactElement } from 'react';
33
import { ReflexContainer, ReflexSplitter, ReflexElement } from 'react-reflex';
44
import { sortChallengeFiles } from '../../../../../utils/sort-challengefiles';
55
import { challengeTypes } from '../../../../utils/challenge-types';
6+
import { GoogleTagManager } from '../../../analytics/google-tag-manater';
7+
import { Segment } from '../../../analytics/segment';
68
import {
79
ChallengeFile,
810
ChallengeFiles,
@@ -110,86 +112,91 @@ const DesktopLayout = (props: DesktopLayoutProps): JSX.Element => {
110112
} = layoutState;
111113

112114
return (
113-
<div className='desktop-layout'>
114-
<ActionRow
115-
block={block}
116-
hasNotes={hasNotes}
117-
isMultifileCertProject={isMultifileCertProject}
118-
showConsole={showConsole}
119-
showNotes={showNotes}
120-
showInstructions={showInstructions}
121-
hasPreview={hasPreview}
122-
showPreview={showPreview}
123-
superBlock={superBlock}
124-
showBreadcrumbs={false}
125-
togglePane={togglePane}
126-
/>
127-
<div className='editor-row'>
128-
<ReflexContainer orientation='vertical'>
129-
{!projectBasedChallenge && showInstructions && (
130-
<ReflexElement flex={instructionPane.flex} {...resizeProps}>
131-
{instructions}
132-
</ReflexElement>
133-
)}
134-
{!projectBasedChallenge && displayEditor && (
135-
<ReflexSplitter propagate={true} {...resizeProps} />
136-
)}
115+
<>
116+
<div className='desktop-layout'>
117+
<ActionRow
118+
block={block}
119+
hasNotes={hasNotes}
120+
isMultifileCertProject={isMultifileCertProject}
121+
showConsole={showConsole}
122+
showNotes={showNotes}
123+
showInstructions={showInstructions}
124+
hasPreview={hasPreview}
125+
showPreview={showPreview}
126+
superBlock={superBlock}
127+
showBreadcrumbs={false}
128+
togglePane={togglePane}
129+
/>
130+
<div className='editor-row'>
131+
<ReflexContainer orientation='vertical'>
132+
{!projectBasedChallenge && showInstructions && (
133+
<ReflexElement flex={instructionPane.flex} {...resizeProps}>
134+
{instructions}
135+
</ReflexElement>
136+
)}
137+
{!projectBasedChallenge && displayEditor && (
138+
<ReflexSplitter propagate={true} {...resizeProps} />
139+
)}
137140

138-
{challengeFile && displayEditor && (
139-
<ReflexElement flex={editorPane.flex} {...resizeProps}>
140-
<ReflexContainer
141-
key={challengeFile.fileKey}
142-
orientation='horizontal'
143-
>
144-
<ReflexElement
145-
flex={codePane.flex}
146-
{...reflexProps}
147-
{...resizeProps}
141+
{challengeFile && displayEditor && (
142+
<ReflexElement flex={editorPane.flex} {...resizeProps}>
143+
<ReflexContainer
144+
key={challengeFile.fileKey}
145+
orientation='horizontal'
148146
>
149-
{editor}
150-
</ReflexElement>
151-
{displayNotes && (
152-
<ReflexSplitter propagate={true} {...resizeProps} />
153-
)}
154-
{displayNotes && (
155-
<ReflexElement flex={notesPane.flex} {...resizeProps}>
156-
{notes}
157-
</ReflexElement>
158-
)}
159-
</ReflexContainer>
160-
</ReflexElement>
161-
)}
162-
163-
{(displayPreview || displayConsole) && (
164-
<ReflexSplitter propagate={true} {...resizeProps} />
165-
)}
166-
167-
{(displayPreview || displayConsole) && (
168-
<ReflexElement flex={1} {...resizeProps}>
169-
<ReflexContainer orientation='horizontal'>
170-
{displayPreview && (
171-
<ReflexElement flex={previewPane.flex} {...resizeProps}>
172-
{preview}
173-
</ReflexElement>
174-
)}
175-
{displayConsole && displayPreview && (
176-
<ReflexSplitter propagate={true} {...resizeProps} />
177-
)}
178-
{displayConsole && (
179147
<ReflexElement
180-
flex={testsPane.flex}
148+
flex={codePane.flex}
181149
{...reflexProps}
182150
{...resizeProps}
183151
>
184-
{testOutput}
152+
{editor}
185153
</ReflexElement>
186-
)}
187-
</ReflexContainer>
188-
</ReflexElement>
189-
)}
190-
</ReflexContainer>
154+
{displayNotes && (
155+
<ReflexSplitter propagate={true} {...resizeProps} />
156+
)}
157+
{displayNotes && (
158+
<ReflexElement flex={notesPane.flex} {...resizeProps}>
159+
{notes}
160+
</ReflexElement>
161+
)}
162+
</ReflexContainer>
163+
</ReflexElement>
164+
)}
165+
166+
{(displayPreview || displayConsole) && (
167+
<ReflexSplitter propagate={true} {...resizeProps} />
168+
)}
169+
170+
{(displayPreview || displayConsole) && (
171+
<ReflexElement flex={1} {...resizeProps}>
172+
<ReflexContainer orientation='horizontal'>
173+
{displayPreview && (
174+
<ReflexElement flex={previewPane.flex} {...resizeProps}>
175+
{preview}
176+
</ReflexElement>
177+
)}
178+
{displayConsole && displayPreview && (
179+
<ReflexSplitter propagate={true} {...resizeProps} />
180+
)}
181+
{displayConsole && (
182+
<ReflexElement
183+
flex={testsPane.flex}
184+
{...reflexProps}
185+
{...resizeProps}
186+
>
187+
{testOutput}
188+
</ReflexElement>
189+
)}
190+
</ReflexContainer>
191+
</ReflexElement>
192+
)}
193+
</ReflexContainer>
194+
</div>
191195
</div>
192-
</div>
196+
197+
<Segment />
198+
<GoogleTagManager />
199+
</>
193200
);
194201
};
195202

0 commit comments

Comments
 (0)