Skip to content

Commit 1fd95b8

Browse files
committed
save
1 parent dcfb111 commit 1fd95b8

File tree

4 files changed

+73
-8
lines changed

4 files changed

+73
-8
lines changed

src/frontend/apps/impress/src/core/config/ConfigProvider.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
useSynchronizedLanguage,
1313
} from '@/features/language';
1414
import { useAnalytics } from '@/libs';
15-
import { CrispProvider, PostHogAnalytic } from '@/services';
15+
import { CrispAnalytic, PostHogAnalytic } from '@/services';
1616
import { useSentryStore } from '@/stores/useSentryStore';
1717

1818
import { useConfig } from './api/useConfig';
@@ -73,6 +73,14 @@ export const ConfigProvider = ({ children }: PropsWithChildren) => {
7373
new PostHogAnalytic(conf.POSTHOG_KEY);
7474
}, [conf?.POSTHOG_KEY]);
7575

76+
useEffect(() => {
77+
if (!conf?.CRISP_WEBSITE_ID) {
78+
return;
79+
}
80+
81+
new CrispAnalytic({ websiteId: conf.CRISP_WEBSITE_ID });
82+
}, [conf?.CRISP_WEBSITE_ID]);
83+
7684
if (!conf) {
7785
return (
7886
<Box $height="100vh" $width="100vw" $align="center" $justify="center">
@@ -91,11 +99,7 @@ export const ConfigProvider = ({ children }: PropsWithChildren) => {
9199
{conf?.FRONTEND_JS_URL && (
92100
<Script src={conf?.FRONTEND_JS_URL} strategy="afterInteractive" />
93101
)}
94-
<AnalyticsProvider>
95-
<CrispProvider websiteId={conf?.CRISP_WEBSITE_ID}>
96-
{children}
97-
</CrispProvider>
98-
</AnalyticsProvider>
102+
<AnalyticsProvider>{children}</AnalyticsProvider>
99103
</>
100104
);
101105
};

src/frontend/apps/impress/src/libs/Analytics.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { JSX, PropsWithChildren, ReactNode } from 'react';
22

3+
import { Doc } from '@/features/docs/doc-management';
4+
35
type AnalyticEventClick = {
46
eventName: 'click';
57
};
@@ -8,8 +10,16 @@ type AnalyticEventUser = {
810
id: string;
911
email: string;
1012
};
13+
type AnalyticEventDoc = {
14+
eventName: 'doc';
15+
doc: Doc;
16+
authenticated: boolean;
17+
};
1118

12-
export type AnalyticEvent = AnalyticEventClick | AnalyticEventUser;
19+
export type AnalyticEvent =
20+
| AnalyticEventClick
21+
| AnalyticEventUser
22+
| AnalyticEventDoc;
1323

1424
export abstract class AbstractAnalytic {
1525
public constructor() {

src/frontend/apps/impress/src/pages/docs/[id]/index.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { getDocChildren, subPageToTree } from '@/features/docs/doc-tree/';
2323
import { useSkeletonStore } from '@/features/skeletons';
2424
import { MainLayout } from '@/layouts';
2525
import { MAIN_LAYOUT_ID } from '@/layouts/conf';
26+
import { useAnalytics } from '@/libs/Analytics';
2627
import { useBroadcastStore } from '@/stores';
2728
import { NextPageWithLayout } from '@/types/next';
2829

@@ -96,6 +97,8 @@ const DocPage = ({ id }: DocProps) => {
9697
const { t } = useTranslation();
9798
const { authenticated } = useAuth();
9899
const { untitledDocument } = useTrans();
100+
const { trackEvent } = useAnalytics();
101+
const [hasTracked, setHasTracked] = useState(false);
99102

100103
/**
101104
* Show skeleton when loading a document
@@ -171,6 +174,23 @@ const DocPage = ({ id }: DocProps) => {
171174
});
172175
}, [addTask, doc?.id, queryClient]);
173176

177+
useEffect(() => {
178+
setHasTracked(false);
179+
}, [id]);
180+
181+
useEffect(() => {
182+
if (hasTracked || !doc) {
183+
return;
184+
}
185+
186+
setHasTracked(true);
187+
trackEvent({
188+
eventName: 'doc',
189+
doc,
190+
authenticated,
191+
});
192+
}, [authenticated, doc, hasTracked, trackEvent]);
193+
174194
if (isError && error) {
175195
if ([404, 401].includes(error.status)) {
176196
let replacePath = `/${error.status}`;

src/frontend/apps/impress/src/services/Crisp.tsx

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
*/
44

55
import { Crisp } from 'crisp-sdk-web';
6-
import { PropsWithChildren, useEffect, useState } from 'react';
6+
import { JSX, PropsWithChildren, ReactNode, useEffect, useState } from 'react';
77
import { createGlobalStyle } from 'styled-components';
88

99
import { User } from '@/features/auth';
10+
import { LinkReach, getDocLinkReach } from '@/features/docs/doc-management';
11+
import { AbstractAnalytic, AnalyticEvent } from '@/libs';
1012

1113
const CrispStyle = createGlobalStyle`
1214
#crisp-chatbox a{
@@ -70,3 +72,32 @@ export const CrispProvider = ({
7072
</>
7173
);
7274
};
75+
76+
export class CrispAnalytic extends AbstractAnalytic {
77+
private conf?: CrispProviderProps = undefined;
78+
79+
public constructor(conf?: CrispProviderProps) {
80+
super();
81+
82+
this.conf = conf;
83+
}
84+
85+
public Provider(children?: ReactNode): JSX.Element {
86+
return (
87+
<CrispProvider websiteId={this.conf?.websiteId}>{children}</CrispProvider>
88+
);
89+
}
90+
91+
public trackEvent(evt: AnalyticEvent): void {
92+
if (evt.eventName === 'doc') {
93+
const docIsPublic = getDocLinkReach(evt.doc) === LinkReach.PUBLIC;
94+
if (docIsPublic && !evt.authenticated) {
95+
Crisp.trigger.run('public-doc-not-connected');
96+
}
97+
}
98+
}
99+
100+
public isFeatureFlagActivated(): boolean {
101+
return true;
102+
}
103+
}

0 commit comments

Comments
 (0)