Skip to content

Commit

Permalink
feat: integrate umami (janhq#1809)
Browse files Browse the repository at this point in the history
* feat: integrate umami

* fix: linter issue

* fix: run eslint

* fix window umami null

* fix property type error

* fix: check configuration before requesting analytics script

* fix: test cases

---------

Co-authored-by: Louis <[email protected]>
  • Loading branch information
0xHieu01 and louis-jan authored Feb 1, 2024
1 parent 11e2a76 commit 36cd598
Show file tree
Hide file tree
Showing 12 changed files with 101 additions and 89 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/template-build-linux-x64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ jobs:
make build-and-publish
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ANALYTICS_ID: ${{ secrets.JAN_APP_POSTHOG_PROJECT_API_KEY }}
ANALYTICS_HOST: ${{ secrets.JAN_APP_POSTHOG_URL }}
ANALYTICS_ID: ${{ secrets.JAN_APP_UMAMI_PROJECT_API_KEY }}
ANALYTICS_HOST: ${{ secrets.JAN_APP_UMAMI_URL }}

- name: Upload Artifact .deb file
if: inputs.public_provider != 'github'
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/template-build-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ jobs:
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
APP_PATH: "."
DEVELOPER_ID: ${{ secrets.DEVELOPER_ID }}
ANALYTICS_ID: ${{ secrets.JAN_APP_POSTHOG_PROJECT_API_KEY }}
ANALYTICS_HOST: ${{ secrets.JAN_APP_POSTHOG_URL }}
ANALYTICS_ID: ${{ secrets.JAN_APP_UMAMI_PROJECT_API_KEY }}
ANALYTICS_HOST: ${{ secrets.JAN_APP_UMAMI_URL }}

- name: Upload Artifact
if: inputs.public_provider != 'github'
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/template-build-windows-x64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ jobs:
make build-and-publish
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ANALYTICS_ID: ${{ secrets.JAN_APP_POSTHOG_PROJECT_API_KEY }}
ANALYTICS_HOST: ${{ secrets.JAN_APP_POSTHOG_URL }}
ANALYTICS_ID: ${{ secrets.JAN_APP_UMAMI_PROJECT_API_KEY }}
ANALYTICS_HOST: ${{ secrets.JAN_APP_UMAMI_URL }}
AZURE_KEY_VAULT_URI: ${{ secrets.AZURE_KEY_VAULT_URI }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
Expand Down
4 changes: 2 additions & 2 deletions docs/.env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
GTM_ID=xxxx
POSTHOG_PROJECT_API_KEY=xxxx
POSTHOG_APP_URL=xxxx
UMAMI_PROJECT_API_KEY=xxxx
UMAMI_APP_URL=xxxx
ALGOLIA_API_KEY=xxxx
ALGOLIA_APP_ID=xxxx
1 change: 0 additions & 1 deletion electron/tests/hub.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ test.afterAll(async () => {
})

test('explores hub', async () => {
// Set the timeout for this test to 60 seconds
test.setTimeout(TIMEOUT)
await page.getByTestId('Hub').first().click({
timeout: TIMEOUT,
Expand Down
8 changes: 6 additions & 2 deletions electron/tests/navigation.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ test.afterAll(async () => {
})

test('renders left navigation panel', async () => {
test.setTimeout(TIMEOUT)
const systemMonitorBtn = await page
.getByTestId('System Monitor')
.first()
Expand All @@ -50,8 +51,11 @@ test('renders left navigation panel', async () => {
.isEnabled({ timeout: TIMEOUT })
expect([systemMonitorBtn, settingsBtn].filter((e) => !e).length).toBe(0)
// Chat section should be there
const apiServer = await page.getByTestId('Local API Server').first()
expect(apiServer).toBeVisible({
await page.getByTestId('Local API Server').first().click({
timeout: TIMEOUT,
})
const localServer = await page.getByTestId('local-server-testid').first()
await expect(localServer).toBeVisible({
timeout: TIMEOUT,
})
})
3 changes: 2 additions & 1 deletion electron/tests/settings.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ test.afterAll(async () => {
})

test('shows settings', async () => {
test.setTimeout(TIMEOUT)
await page.getByTestId('Settings').first().click({ timeout: TIMEOUT })
const settingDescription = page.getByTestId('testid-setting-description')
expect(settingDescription).toBeVisible({ timeout: TIMEOUT })
await expect(settingDescription).toBeVisible({ timeout: TIMEOUT })
})
39 changes: 17 additions & 22 deletions web/containers/Providers/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import { Toaster } from 'react-hot-toast'

import { TooltipProvider } from '@janhq/uikit'

import { PostHogProvider } from 'posthog-js/react'

import GPUDriverPrompt from '@/containers/GPUDriverPromptModal'
import EventListenerWrapper from '@/containers/Providers/EventListener'
import JotaiWrapper from '@/containers/Providers/Jotai'
Expand All @@ -21,7 +19,7 @@ import {
setupBaseExtensions,
} from '@/services/extensionService'

import { instance } from '@/utils/posthog'
import Umami from '@/utils/umami'

import KeyListener from './KeyListener'

Expand Down Expand Up @@ -70,25 +68,22 @@ const Providers = (props: PropsWithChildren) => {
}, [setupCore])

return (
<PostHogProvider client={instance}>
<JotaiWrapper>
<ThemeWrapper>
{setupCore && activated && (
<KeyListener>
<FeatureToggleWrapper>
<EventListenerWrapper>
<TooltipProvider delayDuration={0}>
{children}
</TooltipProvider>
{!isMac && <GPUDriverPrompt />}
</EventListenerWrapper>
<Toaster />
</FeatureToggleWrapper>
</KeyListener>
)}
</ThemeWrapper>
</JotaiWrapper>
</PostHogProvider>
<JotaiWrapper>
<ThemeWrapper>
<Umami />
{setupCore && activated && (
<KeyListener>
<FeatureToggleWrapper>
<EventListenerWrapper>
<TooltipProvider delayDuration={0}>{children}</TooltipProvider>
{!isMac && <GPUDriverPrompt />}
</EventListenerWrapper>
<Toaster />
</FeatureToggleWrapper>
</KeyListener>
)}
</ThemeWrapper>
</JotaiWrapper>
)
}

Expand Down
6 changes: 2 additions & 4 deletions web/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,8 @@ const nextConfig = {
...config.plugins,
new webpack.DefinePlugin({
VERSION: JSON.stringify(packageJson.version),
ANALYTICS_ID:
JSON.stringify(process.env.ANALYTICS_ID) ?? JSON.stringify('xxx'),
ANALYTICS_HOST:
JSON.stringify(process.env.ANALYTICS_HOST) ?? JSON.stringify('xxx'),
ANALYTICS_ID: JSON.stringify(process.env.ANALYTICS_ID),
ANALYTICS_HOST: JSON.stringify(process.env.ANALYTICS_HOST),
API_BASE_URL: JSON.stringify('http://localhost:1337'),
isMac: process.platform === 'darwin',
isWindows: process.platform === 'win32',
Expand Down
2 changes: 1 addition & 1 deletion web/screens/LocalServer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ const LocalServerScreen = () => {
}, [handleChangePort, port])

return (
<div className="flex h-full w-full">
<div className="flex h-full w-full" data-testid="local-server-testid">
{/* Left SideBar */}
<div className="flex h-full w-60 flex-shrink-0 flex-col overflow-y-auto border-r border-border">
<div className="p-4">
Expand Down
50 changes: 0 additions & 50 deletions web/utils/posthog.ts

This file was deleted.

65 changes: 65 additions & 0 deletions web/utils/umami.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { useEffect } from 'react'

import Script from 'next/script'

// Define the type for the umami data object
interface UmamiData {
version: string
}

declare global {
interface Window {
umami:
| {
track: (event: string, data?: UmamiData) => void
}
| undefined
}
}

const Umami = () => {
const appVersion = VERSION
const analyticsHost = ANALYTICS_HOST
const analyticsId = ANALYTICS_ID

useEffect(() => {
if (!appVersion || !analyticsHost || !analyticsId) return
const ping = () => {
// Check if umami is defined before ping
if (window.umami !== null && typeof window.umami !== 'undefined') {
window.umami.track(appVersion, {
version: appVersion,
})
}
}

// Wait for umami to be defined before ping
if (window.umami !== null && typeof window.umami !== 'undefined') {
ping()
} else {
// Listen for umami script load event
document.addEventListener('umami:loaded', ping)
}

// Cleanup function to remove event listener if the component unmounts
return () => {
document.removeEventListener('umami:loaded', ping)
}
}, [appVersion, analyticsHost, analyticsId])

return (
<>
{appVersion && analyticsHost && analyticsId && (
<Script
src={analyticsHost}
data-website-id={analyticsId}
data-cache="true"
defer
onLoad={() => document.dispatchEvent(new Event('umami:loaded'))}
/>
)}
</>
)
}

export default Umami

0 comments on commit 36cd598

Please sign in to comment.