From 752f9548a8e32075e1243d59f7f0e8c226672a2b Mon Sep 17 00:00:00 2001 From: Anup Cowkur Date: Mon, 4 Dec 2023 16:33:19 +0530 Subject: [PATCH] chore(webapp): format code --- measure-web-app/app/[teamId]/anrs/page.tsx | 6 +- measure-web-app/app/[teamId]/apps/page.tsx | 57 ++- .../app/[teamId]/crashes/[crashId]/page.tsx | 88 ++--- measure-web-app/app/[teamId]/crashes/page.tsx | 34 +- measure-web-app/app/[teamId]/layout.tsx | 232 ++++++------ .../app/[teamId]/overview/page.tsx | 54 +-- .../[teamId]/sessions/[sessionId]/page.tsx | 6 +- .../app/components/checkbox_dropdown.tsx | 12 +- measure-web-app/app/components/create_app.tsx | 64 ++-- measure-web-app/app/components/dropdown.tsx | 2 +- .../app/components/email_waitlist.tsx | 38 +- .../app/components/exception_count_chart.tsx | 131 +++---- .../app/components/exception_rate_chart.tsx | 131 +++---- .../app/components/filter_pill.tsx | 2 +- .../components/info_circle_app_adoption.tsx | 30 +- .../app/components/info_circle_app_size.tsx | 28 +- .../components/info_circle_app_start_time.tsx | 28 +- .../components/info_circle_exception_rate.tsx | 24 +- .../app/components/landing_header.tsx | 10 +- .../app/components/metrics_overview.tsx | 30 +- .../app/components/session_replay.tsx | 351 +++++++++--------- .../app/components/team_switcher.tsx | 2 +- measure-web-app/app/components/user_flow.tsx | 164 ++++---- .../components/user_flow_crash_details.tsx | 104 +++--- measure-web-app/app/globals.css | 10 +- measure-web-app/app/layout.tsx | 16 +- measure-web-app/app/page.tsx | 94 ++--- measure-web-app/app/utils/auth_utils.tsx | 2 +- 28 files changed, 877 insertions(+), 873 deletions(-) diff --git a/measure-web-app/app/[teamId]/anrs/page.tsx b/measure-web-app/app/[teamId]/anrs/page.tsx index 5d78dfe0c..e1e544904 100644 --- a/measure-web-app/app/[teamId]/anrs/page.tsx +++ b/measure-web-app/app/[teamId]/anrs/page.tsx @@ -2,10 +2,10 @@ export default function ANRs({ params }: { params: { teamId: string } }) { return (
-
+

ANRs

-
-
+
+
) } diff --git a/measure-web-app/app/[teamId]/apps/page.tsx b/measure-web-app/app/[teamId]/apps/page.tsx index 58f2260f5..abb8428f0 100644 --- a/measure-web-app/app/[teamId]/apps/page.tsx +++ b/measure-web-app/app/[teamId]/apps/page.tsx @@ -1,7 +1,6 @@ "use client" import CreateApp from "@/app/components/create_app"; -import Dropdown from "@/app/components/dropdown"; import { getAccessTokenOrRedirectToAuth, logoutIfAuthError } from "@/app/utils/auth_utils"; import { useRouter } from 'next/navigation'; import React, { useState, useEffect } from 'react'; @@ -9,7 +8,7 @@ import React, { useState, useEffect } from 'react'; export default function Apps({ params }: { params: { teamId: string } }) { const router = useRouter() - + enum AppsApiStatus { Loading, Success, @@ -22,10 +21,10 @@ export default function Apps({ params }: { params: { teamId: string } }) { "team_id": "", "name": "", "api_key": { - "created_at": "", - "key": "", - "last_seen": null, - "revoked": false + "created_at": "", + "key": "", + "last_seen": null, + "revoked": false }, "onboarded": false, "created_at": "", @@ -38,7 +37,7 @@ export default function Apps({ params }: { params: { teamId: string } }) { const [apps, setApps] = useState([] as typeof emptyApp[]); const [appsApiStatus, setAppsApiStatus] = useState(AppsApiStatus.Loading); - const getApps = async (teamId:string, ) => { + const getApps = async (teamId: string,) => { setAppsApiStatus(AppsApiStatus.Loading) const authToken = await getAccessTokenOrRedirectToAuth(router) @@ -50,17 +49,17 @@ export default function Apps({ params }: { params: { teamId: string } }) { }; const res = await fetch(`${origin}/teams/${teamId}/apps`, opts); - - if(!res.ok && res.status == 404) { + + if (!res.ok && res.status == 404) { setAppsApiStatus(AppsApiStatus.NoApps) return - } + } - if(!res.ok) { + if (!res.ok) { setAppsApiStatus(AppsApiStatus.Error) logoutIfAuthError(router, res) return - } + } const data = await res.json() @@ -74,9 +73,9 @@ export default function Apps({ params }: { params: { teamId: string } }) { return (
-
+

Apps

-
+
{/* Loading message for apps */} {appsApiStatus === AppsApiStatus.Loading &&

Updating Apps...

} @@ -84,38 +83,38 @@ export default function Apps({ params }: { params: { teamId: string } }) { {appsApiStatus === AppsApiStatus.Error &&

Error fetching apps, please refresh page to try again

} {/* Show list of apps if app fetch succeeds */} - {appsApiStatus === AppsApiStatus.Success && + {appsApiStatus === AppsApiStatus.Success &&
- {apps.map(({id, name, unique_identifier, platform, api_key, created_at}) => ( + {apps.map(({ id, name, unique_identifier, platform, api_key, created_at }) => (

{name}

-
+

Package name: {unique_identifier}

-
+

Platform: {platform}

-
+

Created at: {created_at}

API key

-
- +
+
-
+
))} -
-
-
+
+
+
} - + {/* Show no apps message when no apps exist */} {appsApiStatus === AppsApiStatus.NoApps &&

Looks like you don't have any apps yet. Get started by creating your first app!

} - -
- + +
+
) } diff --git a/measure-web-app/app/[teamId]/crashes/[crashId]/page.tsx b/measure-web-app/app/[teamId]/crashes/[crashId]/page.tsx index 72829ff8e..f97d3509a 100644 --- a/measure-web-app/app/[teamId]/crashes/[crashId]/page.tsx +++ b/measure-web-app/app/[teamId]/crashes/[crashId]/page.tsx @@ -180,7 +180,7 @@ const stackTraces = [ }, ] -export default function CrashDetails({ params }: { params: { teamId:string, crashId: string } }) { +export default function CrashDetails({ params }: { params: { teamId: string, crashId: string } }) { var apps = ['Readly prod', 'Readly alpha', 'Readly debug']; const [selectedApp, setSelectedApp] = useState(apps[0]); @@ -190,19 +190,19 @@ export default function CrashDetails({ params }: { params: { teamId:string, cras var countries = ['India', 'China', 'USA']; const [selectedCountries, setSelectedCountries] = useState(new Array()); - var networkProviders = ['Airtel', 'Jio','Vodafone']; + var networkProviders = ['Airtel', 'Jio', 'Vodafone']; const [selectedNetworkProviders, setSelectedNetworkProviders] = useState(new Array()); - var networkTypes = ['Wifi', '5G','4G', '3G', '2G', 'Edge']; + var networkTypes = ['Wifi', '5G', '4G', '3G', '2G', 'Edge']; const [selectedNetworkTypes, setSelectedNetworkTypes] = useState(new Array()); - var locales = ['en-in', 'en-us','en-uk']; + var locales = ['en-in', 'en-us', 'en-uk']; const [selectedLocales, setSelectedLocales] = useState(new Array()); - var deviceManufacturers = ['Samsung', 'Huawei','Motorola']; + var deviceManufacturers = ['Samsung', 'Huawei', 'Motorola']; const [selectedDeviceManufacturers, setSelectedDeviceManufacturers] = useState(new Array()); - var deviceNames = ['Samsung Galaxy Note 2', 'Motorola Razor V2','Huawei P30 Pro'] + var deviceNames = ['Samsung Galaxy Note 2', 'Motorola Razor V2', 'Huawei P30 Pro'] const [selectedDeviceNames, setSelectedDeviceNames] = useState(new Array()); const today = new Date(); @@ -222,9 +222,9 @@ export default function CrashDetails({ params }: { params: { teamId:string, cras return (
-
+

NullPointerException.java

-
+
setSelectedApp(item)} />
@@ -232,54 +232,54 @@ export default function CrashDetails({ params }: { params: { teamId:string, cras

to

setEndDate(e.target.value)} />
- setSelectedVersions(items)}/> - setSelectedCountries(items)}/> - setSelectedNetworkProviders(items)}/> - setSelectedNetworkTypes(items)}/> - setSelectedLocales(items)}/> - setSelectedDeviceManufacturers(items)}/> - setSelectedDeviceNames(items)}/> + setSelectedVersions(items)} /> + setSelectedCountries(items)} /> + setSelectedNetworkProviders(items)} /> + setSelectedNetworkTypes(items)} /> + setSelectedLocales(items)} /> + setSelectedDeviceManufacturers(items)} /> + setSelectedDeviceNames(items)} />

Filter by any field such as userId, device name etc

-
- +
+
-
+
- {selectedVersions.length > 0 && } - {selectedCountries.length > 0 && } - {selectedNetworkProviders.length > 0 && } - {selectedNetworkTypes.length > 0 && } - {selectedLocales.length > 0 && } - {selectedDeviceManufacturers.length > 0 && } - {selectedDeviceNames.length > 0 && } + {selectedVersions.length > 0 && } + {selectedCountries.length > 0 && } + {selectedNetworkProviders.length > 0 && } + {selectedNetworkTypes.length > 0 && } + {selectedLocales.length > 0 && } + {selectedDeviceManufacturers.length > 0 && } + {selectedDeviceNames.length > 0 && }
-
+
- +
-
+
- +
-
+

Stack trace

-
+
- {stackTraces.map((stackTrace, index) => ( - - {stackTrace.text} - - ))} + {stackTraces.map((stackTrace, index) => ( + + {stackTrace.text} + + ))}
-
+

Latest Sessions with NullpointerException.java

-
+
@@ -289,12 +289,12 @@ export default function CrashDetails({ params }: { params: { teamId:string, cras
- {sessions.map(({id, userId, dateTime }) => ( - -
{id}
-
{userId}
-
{dateTime}
- + {sessions.map(({ id, userId, dateTime }) => ( + +
{id}
+
{userId}
+
{dateTime}
+ ))}
diff --git a/measure-web-app/app/[teamId]/crashes/page.tsx b/measure-web-app/app/[teamId]/crashes/page.tsx index 102bce336..a51a0b5c7 100644 --- a/measure-web-app/app/[teamId]/crashes/page.tsx +++ b/measure-web-app/app/[teamId]/crashes/page.tsx @@ -97,9 +97,9 @@ export default function Crashes({ params }: { params: { teamId: string } }) { return (
-
+

Crashes

-
+
setSelectedApp(item)} />
@@ -107,26 +107,26 @@ export default function Crashes({ params }: { params: { teamId: string } }) {

to

setEndDate(e.target.value)} />
- setSelectedVersions(items)}/> - setSelectedCountries(items)}/> + setSelectedVersions(items)} /> + setSelectedCountries(items)} />

Search by any field such as crash string, userId, device name etc

-
- +
+
-
+
- {selectedVersions.length > 0 && } - {selectedCountries.length > 0 &&} + {selectedVersions.length > 0 && } + {selectedCountries.length > 0 && }
-
+
- +
-
+
@@ -137,11 +137,11 @@ export default function Crashes({ params }: { params: { teamId: string } }) {
{crashes.map(({ id, title, count, percentage }) => ( - -
{title}
-
{count} instances
-
{percentage}%
- + +
{title}
+
{count} instances
+
{percentage}%
+ ))}
diff --git a/measure-web-app/app/[teamId]/layout.tsx b/measure-web-app/app/[teamId]/layout.tsx index 2752a6bdd..d411d7e66 100644 --- a/measure-web-app/app/[teamId]/layout.tsx +++ b/measure-web-app/app/[teamId]/layout.tsx @@ -8,137 +8,137 @@ import TeamSwitcher from "../components/team_switcher"; import { getAccessTokenOrRedirectToAuth, logoutIfAuthError, logout } from "../utils/auth_utils"; export default function DashboardLayout({ - children, + children, }: { - children: React.ReactNode + children: React.ReactNode }) { - enum TeamsApiStatus { - Loading, - Success, - Error - } - - const emptyTeams = [{'id':'', 'name':''}] + enum TeamsApiStatus { + Loading, + Success, + Error + } - var menuItems = [ - { - hrefSuffix: `overview`, - title: 'Overview', - }, - { - hrefSuffix: 'crashes', - title: 'Crashes', - }, - { - hrefSuffix: 'anrs', - title: 'ANRs', - }, - { - hrefSuffix: 'team', - title: 'Team', - }, - { - hrefSuffix: 'apps', - title: 'Apps', - }, - ]; + const emptyTeams = [{ 'id': '', 'name': '' }] - const [teamsApiStatus, setTeamsApiStatus] = useState(TeamsApiStatus.Loading); - const [teams, setTeams] = useState(emptyTeams); - const [selectedTeam, setSelectedTeam] = useState(teams[0].id) + var menuItems = [ + { + hrefSuffix: `overview`, + title: 'Overview', + }, + { + hrefSuffix: 'crashes', + title: 'Crashes', + }, + { + hrefSuffix: 'anrs', + title: 'ANRs', + }, + { + hrefSuffix: 'team', + title: 'Team', + }, + { + hrefSuffix: 'apps', + title: 'Apps', + }, + ]; - const pathName = usePathname(); - const router = useRouter(); + const [teamsApiStatus, setTeamsApiStatus] = useState(TeamsApiStatus.Loading); + const [teams, setTeams] = useState(emptyTeams); + const [selectedTeam, setSelectedTeam] = useState(teams[0].id) - const getTeams = async () => { - setTeamsApiStatus(TeamsApiStatus.Loading) + const pathName = usePathname(); + const router = useRouter(); - const authToken = await getAccessTokenOrRedirectToAuth(router) - const origin = process.env.NEXT_PUBLIC_API_BASE_URL - const opts = { - headers: { - "Authorization": `Bearer ${authToken}` - } - }; + const getTeams = async () => { + setTeamsApiStatus(TeamsApiStatus.Loading) - const res = await fetch(`${origin}/teams`, opts); - if(!res.ok) { - setTeamsApiStatus(TeamsApiStatus.Error) - logoutIfAuthError(router, res) - return + const authToken = await getAccessTokenOrRedirectToAuth(router) + const origin = process.env.NEXT_PUBLIC_API_BASE_URL + const opts = { + headers: { + "Authorization": `Bearer ${authToken}` } + }; - setTeamsApiStatus(TeamsApiStatus.Success) - const data = await res.json() - setTeams(data) - setSelectedTeam(data.find((e:{id:string, name:string}) => pathName.includes(e.id)).id) + const res = await fetch(`${origin}/teams`, opts); + if (!res.ok) { + setTeamsApiStatus(TeamsApiStatus.Error) + logoutIfAuthError(router, res) + return } - const logoutUser = async () => { - await logout(router) - } + setTeamsApiStatus(TeamsApiStatus.Success) + const data = await res.json() + setTeams(data) + setSelectedTeam(data.find((e: { id: string, name: string }) => pathName.includes(e.id)).id) + } - useEffect(() => { - getTeams() - }, []); + const logoutUser = async () => { + await logout(router) + } - const onTeamChanged = (item:string) => { - const selectedTeamId = teams.find((e) => e.name === item)!.id - const newPath = pathName.replace(/^\/[^\/]*/, '/' + selectedTeamId); - router.push(newPath) - } + useEffect(() => { + getTeams() + }, []); + + const onTeamChanged = (item: string) => { + const selectedTeamId = teams.find((e) => e.name === item)!.id + const newPath = pathName.replace(/^\/[^\/]*/, '/' + selectedTeamId); + router.push(newPath) + } - return ( -
- {/* Side nav and main content layout on normal+ size screens */} -
- - {teamsApiStatus === TeamsApiStatus.Success &&
{children}
} -
+ return ( +
+ {/* Side nav and main content layout on normal+ size screens */} +
+ + {teamsApiStatus === TeamsApiStatus.Success &&
{children}
} +
- {/* Side nav and main content layout on small screens */} -
- - {teamsApiStatus === TeamsApiStatus.Success &&
{children}
} -
+ {/* Side nav and main content layout on small screens */} +
+ + {teamsApiStatus === TeamsApiStatus.Success &&
{children}
}
- ); +
+ ); } \ No newline at end of file diff --git a/measure-web-app/app/[teamId]/overview/page.tsx b/measure-web-app/app/[teamId]/overview/page.tsx index 15f3cc314..2fe86f8ac 100644 --- a/measure-web-app/app/[teamId]/overview/page.tsx +++ b/measure-web-app/app/[teamId]/overview/page.tsx @@ -25,7 +25,7 @@ export default function Overview({ params }: { params: { teamId: string } }) { Error, NoData } - + const [appsApiStatus, setAppsApiStatus] = useState(AppsApiStatus.Loading); const [filtersApiStatus, setFiltersApiStatus] = useState(FiltersApiStatus.Loading); @@ -34,10 +34,10 @@ export default function Overview({ params }: { params: { teamId: string } }) { "team_id": "", "name": "", "api_key": { - "created_at": "", - "key": "", - "last_seen": null, - "revoked": false + "created_at": "", + "key": "", + "last_seen": null, + "revoked": false }, "onboarded": false, "created_at": "", @@ -45,14 +45,14 @@ export default function Overview({ params }: { params: { teamId: string } }) { "platform": null, "onboarded_at": null, "unique_identifier": null -} + } const [apps, setApps] = useState([] as typeof emptyApp[]); const [selectedApp, setSelectedApp] = useState(emptyApp); const [versions, setVersions] = useState([] as string[]); const [selectedVersion, setSelectedVersion] = useState(versions[0]); - + const today = new Date(); var initialEndDate = `${today.getFullYear()}-${(today.getMonth() + 1).toString().padStart(2, '0')}-${today.getDate().toString().padStart(2, '0')}`; const [endDate, setEndDate] = useState(initialEndDate); @@ -68,7 +68,7 @@ export default function Overview({ params }: { params: { teamId: string } }) { setFormattedEndDate(new Date(endDate).toLocaleDateString()); }, [startDate, endDate]); - const getApps = async (teamId:string, ) => { + const getApps = async (teamId: string,) => { setAppsApiStatus(AppsApiStatus.Loading) const authToken = await getAccessTokenOrRedirectToAuth(router) @@ -80,17 +80,17 @@ export default function Overview({ params }: { params: { teamId: string } }) { }; const res = await fetch(`${origin}/teams/${teamId}/apps`, opts); - - if(!res.ok && res.status == 404) { + + if (!res.ok && res.status == 404) { setAppsApiStatus(AppsApiStatus.NoApps) return - } + } - if(!res.ok) { + if (!res.ok) { setAppsApiStatus(AppsApiStatus.Error) logoutIfAuthError(router, res) return - } + } const data = await res.json() @@ -103,7 +103,7 @@ export default function Overview({ params }: { params: { teamId: string } }) { getApps(params.teamId) }, []); - const getFilters = async (appId:string, ) => { + const getFilters = async (appId: string,) => { setFiltersApiStatus(FiltersApiStatus.Loading) const authToken = await getAccessTokenOrRedirectToAuth(router) @@ -116,16 +116,16 @@ export default function Overview({ params }: { params: { teamId: string } }) { const res = await fetch(`${origin}/apps/${appId}/filters`, opts); - if(!res.ok && res.status == 404) { + if (!res.ok && res.status == 404) { setFiltersApiStatus(FiltersApiStatus.NoData) return - } + } - if(!res.ok) { + if (!res.ok) { logoutIfAuthError(router, res) setFiltersApiStatus(FiltersApiStatus.Error) return - } + } const data = await res.json() setVersions(data.version) @@ -148,30 +148,30 @@ export default function Overview({ params }: { params: { teamId: string } }) { {/* Error message for apps fetch error */} {appsApiStatus === AppsApiStatus.Error &&

Error fetching apps, please refresh page to try again

} - + {/* Create app when no apps exist */} {appsApiStatus === AppsApiStatus.NoApps &&

Looks like you don't have any apps yet. Get started by creating your first app!

} - {appsApiStatus === AppsApiStatus.NoApps &&
} - {appsApiStatus === AppsApiStatus.NoApps && } - + {appsApiStatus === AppsApiStatus.NoApps &&
} + {appsApiStatus === AppsApiStatus.NoApps && } + {/* Show app selector dropdown if apps fetch succeeds */} {appsApiStatus === AppsApiStatus.Success && e.name)} onChangeSelectedItem={(item) => setSelectedApp(apps.find((e) => e.name === item)!)} />} - + {/* Show date selector if apps and filters fetch succeeds */} - {appsApiStatus === AppsApiStatus.Success && filtersApiStatus === FiltersApiStatus.Success && + {appsApiStatus === AppsApiStatus.Success && filtersApiStatus === FiltersApiStatus.Success &&
setStartDate(e.target.value)} />

to

setEndDate(e.target.value)} />
} - {/* Loading message for filters */} + {/* Loading message for filters */} {appsApiStatus === AppsApiStatus.Success && filtersApiStatus === FiltersApiStatus.Loading &&

Updating filters...

} {/* Show versions selector if apps and filters fetch succeeds */} {appsApiStatus === AppsApiStatus.Success && filtersApiStatus === FiltersApiStatus.Success && setSelectedVersion(item)} />}
- + {appsApiStatus === AppsApiStatus.Success && filtersApiStatus === FiltersApiStatus.Success &&
} {/* Show filter pills if apps and filters fetch succeeds */} @@ -185,7 +185,7 @@ export default function Overview({ params }: { params: { teamId: string } }) { {appsApiStatus === AppsApiStatus.Success && filtersApiStatus === FiltersApiStatus.Error &&

Error fetching filters, please refresh page or select a different app to try again

} {/* Create app when app exists but has no data */} - {appsApiStatus === AppsApiStatus.Success && filtersApiStatus === FiltersApiStatus.NoData && } + {appsApiStatus === AppsApiStatus.Success && filtersApiStatus === FiltersApiStatus.NoData && } {/* Show user flow if apps and filters fetch succeeds */} {appsApiStatus === AppsApiStatus.Success && filtersApiStatus === FiltersApiStatus.Success && } diff --git a/measure-web-app/app/[teamId]/sessions/[sessionId]/page.tsx b/measure-web-app/app/[teamId]/sessions/[sessionId]/page.tsx index 82638a45e..bcc332ff6 100644 --- a/measure-web-app/app/[teamId]/sessions/[sessionId]/page.tsx +++ b/measure-web-app/app/[teamId]/sessions/[sessionId]/page.tsx @@ -4,7 +4,7 @@ export default function Session({ params }: { params: { sessionId: string } }) { return (
-
+

Session: {params.sessionId}

UserID: alskdflsj123434

Date: 24th Oct 2023

@@ -12,8 +12,8 @@ export default function Session({ params }: { params: { sessionId: string } }) {

Device: Samsung Galaxy S9 Pro

Location: Bangalore, India

Network provider: Airtel

-
- +
+
) } diff --git a/measure-web-app/app/components/checkbox_dropdown.tsx b/measure-web-app/app/components/checkbox_dropdown.tsx index e9d2c03a5..8dd72dfed 100644 --- a/measure-web-app/app/components/checkbox_dropdown.tsx +++ b/measure-web-app/app/components/checkbox_dropdown.tsx @@ -10,7 +10,7 @@ interface CheckboxDropdownProps { const CheckboxDropdown: React.FC = ({ title, items, onChangeSelectedItems }) => { const [isOpen, setIsOpen] = useState(false); - const [selectedItems,setSelectedItems] = useState(new Array()); + const [selectedItems, setSelectedItems] = useState(new Array()); const dropdownRef = useRef(null); useEffect(() => { @@ -46,17 +46,17 @@ const CheckboxDropdown: React.FC = ({ title, items, onCha }; const toggleItem = (item: string) => { - if(selectedItems.includes(item)) { + if (selectedItems.includes(item)) { setSelectedItems(selectedItems.filter(a => a != item)) } else { - setSelectedItems([item,...selectedItems]) + setSelectedItems([item, ...selectedItems]) } - + }; useEffect(() => { onChangeSelectedItems?.(selectedItems); -}, [selectedItems]); + }, [selectedItems]); return (
@@ -84,7 +84,7 @@ const CheckboxDropdown: React.FC = ({ title, items, onCha type="checkbox" className="appearance-none border-white rounded-sm text-black font-display bg-neutral-950 focus:ring-offset-yellow-200 focus:ring-0 checked:ring-1 checked:ring-white" value={item} - onChange={() => {toggleItem(item)}} + onChange={() => { toggleItem(item) }} /> {item}
diff --git a/measure-web-app/app/components/create_app.tsx b/measure-web-app/app/components/create_app.tsx index abbfbe9f3..0d3727cda 100644 --- a/measure-web-app/app/components/create_app.tsx +++ b/measure-web-app/app/components/create_app.tsx @@ -6,7 +6,7 @@ import { useRouter } from 'next/navigation'; import Accordion from './accordion'; interface CreateAppProps { - teamId:string, + teamId: string, existingAppName?: string, existingApiKey?: string } @@ -90,10 +90,10 @@ const CreateApp: React.FC = ({ teamId, existingAppName = null, e "team_id": "", "name": "", "api_key": { - "created_at": "", - "key": "", - "last_seen": null, - "revoked": false + "created_at": "", + "key": "", + "last_seen": null, + "revoked": false }, "onboarded": false, "created_at": "", @@ -101,24 +101,24 @@ const CreateApp: React.FC = ({ teamId, existingAppName = null, e "platform": null, "onboarded_at": null, "unique_identifier": null -} + } const [data, setData] = useState(emptyData); - const [createAppStatus, setCreateAppStatus] = useState(existingAppName === null && existingApiKey === null? CreateAppStatus.PreCreation: CreateAppStatus.PostCreation) + const [createAppStatus, setCreateAppStatus] = useState(existingAppName === null && existingApiKey === null ? CreateAppStatus.PreCreation : CreateAppStatus.PostCreation) const [createAppApiStatus, setCreateAppApiStatus] = useState(CreateAppApiStatus.Init); const [appName, setAppName] = useState(""); - + const router = useRouter() const createApp: FormEventHandler = async (event) => { event.preventDefault(); - if(appName === "") { + if (appName === "") { return } setCreateAppApiStatus(CreateAppApiStatus.Loading) - + const authToken = await getAccessTokenOrRedirectToAuth(router) const origin = process.env.NEXT_PUBLIC_API_BASE_URL const opts = { @@ -126,20 +126,20 @@ const CreateApp: React.FC = ({ teamId, existingAppName = null, e headers: { "Authorization": `Bearer ${authToken}` }, - body: JSON.stringify({name: appName}) + body: JSON.stringify({ name: appName }) }; - const res = await fetch(`${origin}/teams/${teamId}/apps`, opts); - - if(!res.ok) { + const res = await fetch(`${origin}/teams/${teamId}/apps`, opts); + + if (!res.ok) { setCreateAppApiStatus(CreateAppApiStatus.Error) logoutIfAuthError(router, res) - return - } - + return + } + setCreateAppApiStatus(CreateAppApiStatus.Success) setCreateAppStatus(CreateAppStatus.PostCreation) - setData(await res.json()) + setData(await res.json()) } return ( @@ -149,35 +149,35 @@ const CreateApp: React.FC = ({ teamId, existingAppName = null, e

Add new app

-
+
setAppName(event.target.value)} /> -
+
-
+
{createAppApiStatus === CreateAppApiStatus.Loading &&

Creating app...

} {createAppApiStatus === CreateAppApiStatus.Error &&

Error creating app. Please try again.

}
} - + {/* UI after app creation */} {createAppStatus === CreateAppStatus.PostCreation &&
-

Finish setting up {existingAppName !== null? existingAppName: data.name}

-
+

Finish setting up {existingAppName !== null ? existingAppName : data.name}

+

API key

- - + +
-
+

Steps:

- {addAppSteps.map((text, index) => ( - - {text.text} - - ))} + {addAppSteps.map((text, index) => ( + + {text.text} + + ))}
} diff --git a/measure-web-app/app/components/dropdown.tsx b/measure-web-app/app/components/dropdown.tsx index 2c1e08178..ef2a162e0 100644 --- a/measure-web-app/app/components/dropdown.tsx +++ b/measure-web-app/app/components/dropdown.tsx @@ -49,7 +49,7 @@ const Dropdown: React.FC = ({ items, initialItemIndex = 0, onChan const selectItem = (item: string) => { setSelectedItem(item); setIsOpen(false); - if(onChangeSelectedItem) { + if (onChangeSelectedItem) { onChangeSelectedItem(item); } }; diff --git a/measure-web-app/app/components/email_waitlist.tsx b/measure-web-app/app/components/email_waitlist.tsx index f2771b81e..1509418f9 100644 --- a/measure-web-app/app/components/email_waitlist.tsx +++ b/measure-web-app/app/components/email_waitlist.tsx @@ -6,11 +6,11 @@ import type { FC, FormEventHandler } from 'react'; const waitlist = 'clmq44pdk0002l509qxe27qr8'; export enum ApiStatus { - INIT = 'init', - PENDING = 'pending', - SUCCESS = 'success', - ERROR = 'error', - } + INIT = 'init', + PENDING = 'pending', + SUCCESS = 'success', + ERROR = 'error', +} const EmailWaitlist: FC = () => { const [email, setEmail] = useState(''); @@ -47,25 +47,25 @@ const EmailWaitlist: FC = () => { setButtonText('Subscribed!'); setErrorText('') } catch (error) { - if(error instanceof Error) { - setErrorText(error.message); - } else { - setErrorText('Something went wrong :-(. Please try again.') - } - setApiStatus(ApiStatus.ERROR); - setButtonText('Notify Me'); + if (error instanceof Error) { + setErrorText(error.message); + } else { + setErrorText('Something went wrong :-(. Please try again.') + } + setApiStatus(ApiStatus.ERROR); + setButtonText('Notify Me'); } }; return (
-
- setEmail(event.target.value)} /> -
- - -
-

{errorText}

+
+ setEmail(event.target.value)} /> +
+ + +
+

{errorText}

); }; diff --git a/measure-web-app/app/components/exception_count_chart.tsx b/measure-web-app/app/components/exception_count_chart.tsx index ddddeba20..42ffba03e 100644 --- a/measure-web-app/app/components/exception_count_chart.tsx +++ b/measure-web-app/app/components/exception_count_chart.tsx @@ -5,34 +5,34 @@ import { ResponsiveLine } from '@nivo/line' var today = new Date(); const sevenDaysAgo = new Date(today.setDate(today.getDate() - 7)); -const date1 = `${sevenDaysAgo.getFullYear()}-${(sevenDaysAgo.getMonth()+1).toString().padStart(2, '0')}-${sevenDaysAgo.getDate().toString().padStart(2, '0')}`; +const date1 = `${sevenDaysAgo.getFullYear()}-${(sevenDaysAgo.getMonth() + 1).toString().padStart(2, '0')}-${sevenDaysAgo.getDate().toString().padStart(2, '0')}`; today = new Date(); const sixDaysAgo = new Date(today.setDate(today.getDate() - 6)); -const date2 = `${sixDaysAgo.getFullYear()}-${(sixDaysAgo.getMonth()+1).toString().padStart(2, '0')}-${sixDaysAgo.getDate().toString().padStart(2, '0')}`; +const date2 = `${sixDaysAgo.getFullYear()}-${(sixDaysAgo.getMonth() + 1).toString().padStart(2, '0')}-${sixDaysAgo.getDate().toString().padStart(2, '0')}`; today = new Date(); const fiveDaysAgo = new Date(today.setDate(today.getDate() - 5)); -const date3 = `${fiveDaysAgo.getFullYear()}-${(fiveDaysAgo.getMonth()+1).toString().padStart(2, '0')}-${fiveDaysAgo.getDate().toString().padStart(2, '0')}`; +const date3 = `${fiveDaysAgo.getFullYear()}-${(fiveDaysAgo.getMonth() + 1).toString().padStart(2, '0')}-${fiveDaysAgo.getDate().toString().padStart(2, '0')}`; today = new Date(); const fourDaysAgo = new Date(today.setDate(today.getDate() - 4)); -const date4 = `${fourDaysAgo.getFullYear()}-${(fourDaysAgo.getMonth()+1).toString().padStart(2, '0')}-${fourDaysAgo.getDate().toString().padStart(2, '0')}`; +const date4 = `${fourDaysAgo.getFullYear()}-${(fourDaysAgo.getMonth() + 1).toString().padStart(2, '0')}-${fourDaysAgo.getDate().toString().padStart(2, '0')}`; today = new Date(); const threeDaysAgo = new Date(today.setDate(today.getDate() - 3)); -const date5 = `${threeDaysAgo.getFullYear()}-${(threeDaysAgo.getMonth()+1).toString().padStart(2, '0')}-${threeDaysAgo.getDate().toString().padStart(2, '0')}`; +const date5 = `${threeDaysAgo.getFullYear()}-${(threeDaysAgo.getMonth() + 1).toString().padStart(2, '0')}-${threeDaysAgo.getDate().toString().padStart(2, '0')}`; today = new Date(); const twoDaysAgo = new Date(today.setDate(today.getDate() - 2)); -const date6 = `${twoDaysAgo.getFullYear()}-${(twoDaysAgo.getMonth()+1).toString().padStart(2, '0')}-${twoDaysAgo.getDate().toString().padStart(2, '0')}`; +const date6 = `${twoDaysAgo.getFullYear()}-${(twoDaysAgo.getMonth() + 1).toString().padStart(2, '0')}-${twoDaysAgo.getDate().toString().padStart(2, '0')}`; today = new Date(); const oneDayAgo = new Date(today.setDate(today.getDate() - 1)); -const date7 = `${oneDayAgo.getFullYear()}-${(oneDayAgo.getMonth()+1).toString().padStart(2, '0')}-${oneDayAgo.getDate().toString().padStart(2, '0')}`; +const date7 = `${oneDayAgo.getFullYear()}-${(oneDayAgo.getMonth() + 1).toString().padStart(2, '0')}-${oneDayAgo.getDate().toString().padStart(2, '0')}`; today = new Date(); -const date8 = `${today.getFullYear()}-${(today.getMonth()+1).toString().padStart(2, '0')}-${today.getDate().toString().padStart(2, '0')}`; +const date8 = `${today.getFullYear()}-${(today.getMonth() + 1).toString().padStart(2, '0')}-${today.getDate().toString().padStart(2, '0')}`; const data = [ { @@ -152,63 +152,64 @@ const data = [ ] const ExceptionCountChart = () => { - return ( - - )}; + ) +}; export default ExceptionCountChart; \ No newline at end of file diff --git a/measure-web-app/app/components/exception_rate_chart.tsx b/measure-web-app/app/components/exception_rate_chart.tsx index efac1c142..0c49fb9cc 100644 --- a/measure-web-app/app/components/exception_rate_chart.tsx +++ b/measure-web-app/app/components/exception_rate_chart.tsx @@ -5,34 +5,34 @@ import { ResponsiveLine } from '@nivo/line' var today = new Date(); const sevenDaysAgo = new Date(today.setDate(today.getDate() - 7)); -const date1 = `${sevenDaysAgo.getFullYear()}-${(sevenDaysAgo.getMonth()+1).toString().padStart(2, '0')}-${sevenDaysAgo.getDate().toString().padStart(2, '0')}`; +const date1 = `${sevenDaysAgo.getFullYear()}-${(sevenDaysAgo.getMonth() + 1).toString().padStart(2, '0')}-${sevenDaysAgo.getDate().toString().padStart(2, '0')}`; today = new Date(); const sixDaysAgo = new Date(today.setDate(today.getDate() - 6)); -const date2 = `${sixDaysAgo.getFullYear()}-${(sixDaysAgo.getMonth()+1).toString().padStart(2, '0')}-${sixDaysAgo.getDate().toString().padStart(2, '0')}`; +const date2 = `${sixDaysAgo.getFullYear()}-${(sixDaysAgo.getMonth() + 1).toString().padStart(2, '0')}-${sixDaysAgo.getDate().toString().padStart(2, '0')}`; today = new Date(); const fiveDaysAgo = new Date(today.setDate(today.getDate() - 5)); -const date3 = `${fiveDaysAgo.getFullYear()}-${(fiveDaysAgo.getMonth()+1).toString().padStart(2, '0')}-${fiveDaysAgo.getDate().toString().padStart(2, '0')}`; +const date3 = `${fiveDaysAgo.getFullYear()}-${(fiveDaysAgo.getMonth() + 1).toString().padStart(2, '0')}-${fiveDaysAgo.getDate().toString().padStart(2, '0')}`; today = new Date(); const fourDaysAgo = new Date(today.setDate(today.getDate() - 4)); -const date4 = `${fourDaysAgo.getFullYear()}-${(fourDaysAgo.getMonth()+1).toString().padStart(2, '0')}-${fourDaysAgo.getDate().toString().padStart(2, '0')}`; +const date4 = `${fourDaysAgo.getFullYear()}-${(fourDaysAgo.getMonth() + 1).toString().padStart(2, '0')}-${fourDaysAgo.getDate().toString().padStart(2, '0')}`; today = new Date(); const threeDaysAgo = new Date(today.setDate(today.getDate() - 3)); -const date5 = `${threeDaysAgo.getFullYear()}-${(threeDaysAgo.getMonth()+1).toString().padStart(2, '0')}-${threeDaysAgo.getDate().toString().padStart(2, '0')}`; +const date5 = `${threeDaysAgo.getFullYear()}-${(threeDaysAgo.getMonth() + 1).toString().padStart(2, '0')}-${threeDaysAgo.getDate().toString().padStart(2, '0')}`; today = new Date(); const twoDaysAgo = new Date(today.setDate(today.getDate() - 2)); -const date6 = `${twoDaysAgo.getFullYear()}-${(twoDaysAgo.getMonth()+1).toString().padStart(2, '0')}-${twoDaysAgo.getDate().toString().padStart(2, '0')}`; +const date6 = `${twoDaysAgo.getFullYear()}-${(twoDaysAgo.getMonth() + 1).toString().padStart(2, '0')}-${twoDaysAgo.getDate().toString().padStart(2, '0')}`; today = new Date(); const oneDayAgo = new Date(today.setDate(today.getDate() - 1)); -const date7 = `${oneDayAgo.getFullYear()}-${(oneDayAgo.getMonth()+1).toString().padStart(2, '0')}-${oneDayAgo.getDate().toString().padStart(2, '0')}`; +const date7 = `${oneDayAgo.getFullYear()}-${(oneDayAgo.getMonth() + 1).toString().padStart(2, '0')}-${oneDayAgo.getDate().toString().padStart(2, '0')}`; today = new Date(); -const date8 = `${today.getFullYear()}-${(today.getMonth()+1).toString().padStart(2, '0')}-${today.getDate().toString().padStart(2, '0')}`; +const date8 = `${today.getFullYear()}-${(today.getMonth() + 1).toString().padStart(2, '0')}-${today.getDate().toString().padStart(2, '0')}`; const data = [ { @@ -152,63 +152,64 @@ const data = [ ] const ExceptionRateChart = () => { - return ( - - )}; + ) +}; export default ExceptionRateChart; \ No newline at end of file diff --git a/measure-web-app/app/components/filter_pill.tsx b/measure-web-app/app/components/filter_pill.tsx index f66b2b0a2..01d75c53e 100644 --- a/measure-web-app/app/components/filter_pill.tsx +++ b/measure-web-app/app/components/filter_pill.tsx @@ -9,7 +9,7 @@ const FilterPill: React.FC = ({ title }) => {

{title}

- ); + ); }; export default FilterPill; \ No newline at end of file diff --git a/measure-web-app/app/components/info_circle_app_adoption.tsx b/measure-web-app/app/components/info_circle_app_adoption.tsx index 4e67ae950..7d8744a88 100644 --- a/measure-web-app/app/components/info_circle_app_adoption.tsx +++ b/measure-web-app/app/components/info_circle_app_adoption.tsx @@ -12,21 +12,21 @@ interface InfoCircleAppAdoptionProps { const formatter = Intl.NumberFormat('en', { notation: 'compact' }); const InfoCircleAppAdoption = ({ status, value, users, totalUsers, title }: InfoCircleAppAdoptionProps) => { - return ( -
-
- {status === MetricsApiStatus.Loading &&

Updating...

} - {status === MetricsApiStatus.Error &&

Error

} - {status === MetricsApiStatus.Success &&

{value}%

} -
- {status === MetricsApiStatus.Success &&

{formatter.format(users)}/{formatter.format(totalUsers)} users

} - - Adoption = (Users of selected app version / Users of all app versions) * 100 - -
-
-

{title}

-
+ return ( +
+
+ {status === MetricsApiStatus.Loading &&

Updating...

} + {status === MetricsApiStatus.Error &&

Error

} + {status === MetricsApiStatus.Success &&

{value}%

} +
+ {status === MetricsApiStatus.Success &&

{formatter.format(users)}/{formatter.format(totalUsers)} users

} + + Adoption = (Users of selected app version / Users of all app versions) * 100 + +
+
+

{title}

+
); }; diff --git a/measure-web-app/app/components/info_circle_app_size.tsx b/measure-web-app/app/components/info_circle_app_size.tsx index 441d6197d..ea115a34b 100644 --- a/measure-web-app/app/components/info_circle_app_size.tsx +++ b/measure-web-app/app/components/info_circle_app_size.tsx @@ -9,21 +9,21 @@ interface InfoCircleAppSizeProps { } const InfoCircleAppSize = ({ status, value, delta, title }: InfoCircleAppSizeProps) => { - return ( -
-
- {status === MetricsApiStatus.Loading &&

Updating...

} - {status === MetricsApiStatus.Error &&

Error

} - {status === MetricsApiStatus.Success &&

{value}MB

} -
- {status === MetricsApiStatus.Success &&

0? 'text-red-400': 'opacity-0'}`}>{delta>0? '+':''}{delta}MB

} - - Delta value = App size of selected app version - Average app size of all app versions - -
-
-

{title}

+ return ( +
+
+ {status === MetricsApiStatus.Loading &&

Updating...

} + {status === MetricsApiStatus.Error &&

Error

} + {status === MetricsApiStatus.Success &&

{value}MB

} +
+ {status === MetricsApiStatus.Success &&

0 ? 'text-red-400' : 'opacity-0'}`}>{delta > 0 ? '+' : ''}{delta}MB

} + + Delta value = App size of selected app version - Average app size of all app versions +
+
+

{title}

+
); }; diff --git a/measure-web-app/app/components/info_circle_app_start_time.tsx b/measure-web-app/app/components/info_circle_app_start_time.tsx index e59826faa..d00f3a658 100644 --- a/measure-web-app/app/components/info_circle_app_start_time.tsx +++ b/measure-web-app/app/components/info_circle_app_start_time.tsx @@ -11,21 +11,21 @@ interface InfoCircleAppStartTimeProps { } const InfoCircleAppStartTime = ({ status, value, delta, title, launchType }: InfoCircleAppStartTimeProps) => { - return ( -
-
- {status === MetricsApiStatus.Loading &&

Updating...

} - {status === MetricsApiStatus.Error &&

Error

} - {status === MetricsApiStatus.Success &&

{value}ms

} -
- {status === MetricsApiStatus.Success &&

0? 'text-red-400': 'opacity-0'}`}>{delta>0? '+':''}{delta}ms

} - - App start time = p95 {launchType} launch time of selected app version in selected time period

Delta value = p95 {launchType} launch time of selected app version in selected time period - p95 {launchType} launch time of all app versions in selected time period -
-
-
-

{title}

+ return ( +
+
+ {status === MetricsApiStatus.Loading &&

Updating...

} + {status === MetricsApiStatus.Error &&

Error

} + {status === MetricsApiStatus.Success &&

{value}ms

} +
+ {status === MetricsApiStatus.Success &&

0 ? 'text-red-400' : 'opacity-0'}`}>{delta > 0 ? '+' : ''}{delta}ms

} + + App start time = p95 {launchType} launch time of selected app version in selected time period

Delta value = p95 {launchType} launch time of selected app version in selected time period - p95 {launchType} launch time of all app versions in selected time period +
+
+

{title}

+
); }; diff --git a/measure-web-app/app/components/info_circle_exception_rate.tsx b/measure-web-app/app/components/info_circle_exception_rate.tsx index 856ac0834..b12dc3f41 100644 --- a/measure-web-app/app/components/info_circle_exception_rate.tsx +++ b/measure-web-app/app/components/info_circle_exception_rate.tsx @@ -11,19 +11,19 @@ interface InfoCircleExceptionRateExceptionRateProps { } const InfoCircleExceptionRate = ({ status, value, delta, title, tooltipMsgLine1, tooltipMsgLine2 }: InfoCircleExceptionRateExceptionRateProps) => { - return ( -
-
95? 'border-green-400 hover:bg-green-400/25': value > 85? 'border-yellow-400 hover:bg-yellow-400/25': 'border-red-400 hover:bg-red-400/25'}`}> - {status === MetricsApiStatus.Loading &&

Updating...

} - {status === MetricsApiStatus.Error &&

Error

} - {status === MetricsApiStatus.Success &&

{value}%

} -
- {status === MetricsApiStatus.Success &&

0? 'text-green-600': delta < 0? 'text-red-400': 'opacity-0'}`}>{delta>0? '+':''}{delta}%

} - {tooltipMsgLine1}

{tooltipMsgLine2}
-
-
-

{title}

+ return ( +
+
95 ? 'border-green-400 hover:bg-green-400/25' : value > 85 ? 'border-yellow-400 hover:bg-yellow-400/25' : 'border-red-400 hover:bg-red-400/25'}`}> + {status === MetricsApiStatus.Loading &&

Updating...

} + {status === MetricsApiStatus.Error &&

Error

} + {status === MetricsApiStatus.Success &&

{value}%

} +
+ {status === MetricsApiStatus.Success &&

0 ? 'text-green-600' : delta < 0 ? 'text-red-400' : 'opacity-0'}`}>{delta > 0 ? '+' : ''}{delta}%

} + {tooltipMsgLine1}

{tooltipMsgLine2}
+
+

{title}

+
); }; diff --git a/measure-web-app/app/components/landing_header.tsx b/measure-web-app/app/components/landing_header.tsx index 27bbfe510..3f0f39f76 100644 --- a/measure-web-app/app/components/landing_header.tsx +++ b/measure-web-app/app/components/landing_header.tsx @@ -1,6 +1,6 @@ 'use client' -import { useRef, useState, useEffect} from 'react'; +import { useRef, useState, useEffect } from 'react'; import { useRouter } from 'next/navigation' function useScrollDirection() { @@ -38,19 +38,19 @@ function useScrollDirection() { return scrollDir; } -export default function LandingHeader() { +export default function LandingHeader() { const scrollDir = useScrollDirection(); const [isFocused, setIsFocused] = useState(false); const router = useRouter(); return ( -
setIsFocused(true)} onBlur={()=>setIsFocused(false)} className={`w-full flex flex-col z-50 bg-white fixed top-0 transition-transform duration-100 ease-in-out ${scrollDir === 'scrolling down' && isFocused === false ? '-translate-y-full' : 'translate-y-0'}`}> +
setIsFocused(true)} onBlur={() => setIsFocused(false)} className={`w-full flex flex-col z-50 bg-white fixed top-0 transition-transform duration-100 ease-in-out ${scrollDir === 'scrolling down' && isFocused === false ? '-translate-y-full' : 'translate-y-0'}`}>
-
+
-
+
) } diff --git a/measure-web-app/app/components/metrics_overview.tsx b/measure-web-app/app/components/metrics_overview.tsx index c31e423c9..014a24341 100644 --- a/measure-web-app/app/components/metrics_overview.tsx +++ b/measure-web-app/app/components/metrics_overview.tsx @@ -9,10 +9,10 @@ import { getAccessTokenOrRedirectToAuth, logoutIfAuthError } from '@/app/utils/a import { useRouter } from 'next/navigation'; interface MetricsOverviewProps { - appId:string, - startDate:string, - endDate:string, - appVersion:string, + appId: string, + startDate: string, + endDate: string, + appVersion: string, } export enum MetricsApiStatus { @@ -73,12 +73,12 @@ const MetricsOverview: React.FC = ({ appId, startDate, end const [data, setData] = useState(emptyData); const [metricsApiStatus, setMetricsApiStatus] = useState(MetricsApiStatus.Loading); - + const router = useRouter() - const getData = async (appId:string, startDate:string, endDate:string, appVersion:string) => { + const getData = async (appId: string, startDate: string, endDate: string, appVersion: string) => { setMetricsApiStatus(MetricsApiStatus.Loading) - + const authToken = await getAccessTokenOrRedirectToAuth(router) const origin = process.env.NEXT_PUBLIC_API_BASE_URL const opts = { @@ -89,18 +89,18 @@ const MetricsOverview: React.FC = ({ appId, startDate, end const serverFormattedStartDate = new Date(startDate).toISOString() const serverFormattedEndDate = new Date(endDate).toISOString() - const res = await fetch(`${origin}/apps/${appId}/metrics?version=${appVersion}&from=${serverFormattedStartDate}&to=${serverFormattedEndDate}`, opts); - - if(!res.ok) { + const res = await fetch(`${origin}/apps/${appId}/metrics?version=${appVersion}&from=${serverFormattedStartDate}&to=${serverFormattedEndDate}`, opts); + + if (!res.ok) { setMetricsApiStatus(MetricsApiStatus.Error) logoutIfAuthError(router, res) - return - } - + return + } + setMetricsApiStatus(MetricsApiStatus.Success) - setData(await res.json()) + setData(await res.json()) } - + useEffect(() => { getData(appId, startDate, endDate, appVersion) }, [appId, startDate, endDate, appVersion]); diff --git a/measure-web-app/app/components/session_replay.tsx b/measure-web-app/app/components/session_replay.tsx index d5321305b..0d0b84cd7 100644 --- a/measure-web-app/app/components/session_replay.tsx +++ b/measure-web-app/app/components/session_replay.tsx @@ -199,131 +199,131 @@ const threadData = [ ] const SessionReplay = () => { - return ( -
- {/* Memory line */} -
- i.color)} - defs={[ - { - colors: [ - { - color: memoryData.map((i) => i.color), - offset: 0 - }, - { - color: memoryData.map((i) => i.color), - offset: 60, - opacity: 0 - } - ], - id: 'memoryGradient', - type: 'linearGradient' - } - ]} - enableArea - fill={[ - { - id: 'memoryGradient', - match: '*' - } - ]} - tooltip={({ - point - }) =>
-

{point.data.yFormatted} MB

-
} - - /> -
- {/* CPU line */} -
- i.color)} - defs={[ - { - colors: [ - { - color: cpuData.map((i) => i.color), - offset: 0 - }, - { - color: cpuData.map((i) => i.color), - offset: 60, - opacity: 0 - } - ], - id: 'cpuGradient', - type: 'linearGradient' + return ( +
+ {/* Memory line */} +
+ i.color)} + defs={[ + { + colors: [ + { + color: memoryData.map((i) => i.color), + offset: 0 + }, + { + color: memoryData.map((i) => i.color), + offset: 60, + opacity: 0 + } + ], + id: 'memoryGradient', + type: 'linearGradient' + } + ]} + enableArea + fill={[ + { + id: 'memoryGradient', + match: '*' + } + ]} + tooltip={({ + point + }) =>
+

{point.data.yFormatted} MB

+
} + + /> +
+ {/* CPU line */} +
+ i.color)} + defs={[ + { + colors: [ + { + color: cpuData.map((i) => i.color), + offset: 0 + }, + { + color: cpuData.map((i) => i.color), + offset: 60, + opacity: 0 + } + ], + id: 'cpuGradient', + type: 'linearGradient' } ]} enableArea @@ -336,56 +336,57 @@ const SessionReplay = () => { tooltip={({ point }) =>
-

{point.data.yFormatted}%

-
} - /> -
- {/* Threads line */} -
- threadPoints[point.index].color} - pointLabelYOffset={-12} - useMesh={true} - enableGridX={true} - enableGridY={false} - colors={threadData.map((i) => i.color)} - tooltip={({ - point - }) =>
-

{threadPoints[point.index].event}

-
} - /> -
+

{point.data.yFormatted}%

+
} + /> +
+ {/* Threads line */} +
+ threadPoints[point.index].color} + pointLabelYOffset={-12} + useMesh={true} + enableGridX={true} + enableGridY={false} + colors={threadData.map((i) => i.color)} + tooltip={({ + point + }) =>
+

{threadPoints[point.index].event}

+
} + /> +
- )}; + ) +}; export default SessionReplay; \ No newline at end of file diff --git a/measure-web-app/app/components/team_switcher.tsx b/measure-web-app/app/components/team_switcher.tsx index e7e7ae043..8f190885d 100644 --- a/measure-web-app/app/components/team_switcher.tsx +++ b/measure-web-app/app/components/team_switcher.tsx @@ -49,7 +49,7 @@ const TeamSwitcher: React.FC = ({ items, initialItemIndex = 0 const selectItem = (item: string) => { setSelectedItem(item); setIsOpen(false); - if(onChangeSelectedItem) { + if (onChangeSelectedItem) { onChangeSelectedItem(item); } }; diff --git a/measure-web-app/app/components/user_flow.tsx b/measure-web-app/app/components/user_flow.tsx index 7110e68f7..54944864b 100644 --- a/measure-web-app/app/components/user_flow.tsx +++ b/measure-web-app/app/components/user_flow.tsx @@ -6,10 +6,10 @@ import { getAccessTokenOrRedirectToAuth, logoutIfAuthError } from '@/app/utils/a import { useRouter } from 'next/navigation'; interface UserFlowProps { - appId:string, - startDate:string, - endDate:string, - appVersion:string, + appId: string, + startDate: string, + endDate: string, + appVersion: string, } const UserFlow: React.FC = ({ appId, startDate, endDate, appVersion }) => { @@ -26,7 +26,7 @@ const UserFlow: React.FC = ({ appId, startDate, endDate, appVersi "nodeColor": "", "issues": { "crashes": [], - "anrs":[] + "anrs": [] } }, ], @@ -35,15 +35,15 @@ const UserFlow: React.FC = ({ appId, startDate, endDate, appVersi } const formatter = Intl.NumberFormat('en', { notation: 'compact' }); - + const [journeyApiStatus, setJourneyApiStatus] = useState(JourneyApiStatus.Loading); const [data, setData] = useState(emptyData); const router = useRouter() - const getData = async (appId:string, startDate:string, endDate:string, appVersion:string) => { + const getData = async (appId: string, startDate: string, endDate: string, appVersion: string) => { setJourneyApiStatus(JourneyApiStatus.Loading) - + const authToken = await getAccessTokenOrRedirectToAuth(router) const origin = process.env.NEXT_PUBLIC_API_BASE_URL const opts = { @@ -54,92 +54,92 @@ const UserFlow: React.FC = ({ appId, startDate, endDate, appVersi const serverFormattedStartDate = new Date(startDate).toISOString() const serverFormattedEndDate = new Date(endDate).toISOString() - const res = await fetch(`${origin}/apps/${appId}/journey?version=${appVersion}&from=${serverFormattedStartDate}&to=${serverFormattedEndDate}`, opts); - - if(!res.ok) { + const res = await fetch(`${origin}/apps/${appId}/journey?version=${appVersion}&from=${serverFormattedStartDate}&to=${serverFormattedEndDate}`, opts); + + if (!res.ok) { setJourneyApiStatus(JourneyApiStatus.Error) logoutIfAuthError(router, res) return } - + setJourneyApiStatus(JourneyApiStatus.Success) setData(await res.json()) } - + useEffect(() => { getData(appId, startDate, endDate, appVersion) }, [appId, startDate, endDate, appVersion]); - + return (
- { journeyApiStatus === JourneyApiStatus.Loading &&

Updating data...

} - { journeyApiStatus === JourneyApiStatus.Error &&

Error fetching data. Please refresh page or change filters to try again.

} - { journeyApiStatus === JourneyApiStatus.Success - && nodeColor} - nodeOpacity={1} - nodeHoverOthersOpacity={0.35} - nodeThickness={18} - nodeSpacing={24} - nodeBorderWidth={0} - nodeBorderColor={{ - from: 'color', - modifiers: [ - [ - 'darker', - 0.8 - ] - ] - }} - nodeBorderRadius={3} - linkOpacity={0.25} - linkHoverOthersOpacity={0.1} - linkContract={3} - enableLinkGradient={false} - labelPosition="outside" - labelOrientation="horizontal" - labelPadding={16} - labelTextColor="#000000" - nodeTooltip={({ - node - }) =>
-

{node.label}

- {node.issues.crashes.length > 0 && -
-
-

Crashes:

-
    - {node.issues.crashes.map(({ title, count }) => ( -
  • - {title} - {formatter.format(count)} -
  • - ))} -
-
- } - {node.issues.anrs.length > 0 && -
-
-

ANRs:

-
    - {node.issues.anrs.map(({ title, count }) => ( -
  • - {title} - {formatter.format(count)} -
  • - ))} -
-
- } -
} - linkTooltip={({ - link - }) =>
-

{link.source.label} > {link.target.label} - {formatter.format(link.value)}

-
} - />} + {journeyApiStatus === JourneyApiStatus.Loading &&

Updating data...

} + {journeyApiStatus === JourneyApiStatus.Error &&

Error fetching data. Please refresh page or change filters to try again.

} + {journeyApiStatus === JourneyApiStatus.Success + && nodeColor} + nodeOpacity={1} + nodeHoverOthersOpacity={0.35} + nodeThickness={18} + nodeSpacing={24} + nodeBorderWidth={0} + nodeBorderColor={{ + from: 'color', + modifiers: [ + [ + 'darker', + 0.8 + ] + ] + }} + nodeBorderRadius={3} + linkOpacity={0.25} + linkHoverOthersOpacity={0.1} + linkContract={3} + enableLinkGradient={false} + labelPosition="outside" + labelOrientation="horizontal" + labelPadding={16} + labelTextColor="#000000" + nodeTooltip={({ + node + }) =>
+

{node.label}

+ {node.issues.crashes.length > 0 && +
+
+

Crashes:

+
    + {node.issues.crashes.map(({ title, count }) => ( +
  • + {title} - {formatter.format(count)} +
  • + ))} +
+
+ } + {node.issues.anrs.length > 0 && +
+
+

ANRs:

+
    + {node.issues.anrs.map(({ title, count }) => ( +
  • + {title} - {formatter.format(count)} +
  • + ))} +
+
+ } +
} + linkTooltip={({ + link + }) =>
+

{link.source.label} > {link.target.label} - {formatter.format(link.value)}

+
} + />}
); }; diff --git a/measure-web-app/app/components/user_flow_crash_details.tsx b/measure-web-app/app/components/user_flow_crash_details.tsx index 624e556e4..150bcc45c 100644 --- a/measure-web-app/app/components/user_flow_crash_details.tsx +++ b/measure-web-app/app/components/user_flow_crash_details.tsx @@ -11,7 +11,7 @@ const data = { "nodeColor": "hsl(142, 69%, 58%)", "issues": { "crashes": [], - "anrs":[] + "anrs": [] } }, { @@ -19,7 +19,7 @@ const data = { "nodeColor": "hsl(142, 69%, 58%)", "issues": { "crashes": [], - "anrs":[] + "anrs": [] } }, { @@ -30,7 +30,7 @@ const data = { "title": "NullPointerException.java", "count": 37893 }], - "anrs":[] + "anrs": [] } }, { @@ -38,7 +38,7 @@ const data = { "nodeColor": "hsl(142, 69%, 58%)", "issues": { "crashes": [], - "anrs":[] + "anrs": [] } }, { @@ -46,7 +46,7 @@ const data = { "nodeColor": "hsl(142, 69%, 58%)", "issues": { "crashes": [], - "anrs":[] + "anrs": [] } }, { @@ -54,7 +54,7 @@ const data = { "nodeColor": "hsl(142, 69%, 58%)", "issues": { "crashes": [], - "anrs":[] + "anrs": [] } }, { @@ -62,7 +62,7 @@ const data = { "nodeColor": "hsl(142, 69%, 58%)", "issues": { "crashes": [], - "anrs":[] + "anrs": [] } }, { @@ -70,7 +70,7 @@ const data = { "nodeColor": "hsl(142, 69%, 58%)", "issues": { "crashes": [], - "anrs":[] + "anrs": [] } }, { @@ -81,7 +81,7 @@ const data = { "title": "NullPointerException.java", "count": 37893 }], - "anrs":[] + "anrs": [] } }, { @@ -89,7 +89,7 @@ const data = { "nodeColor": "hsl(142, 69%, 58%)", "issues": { "crashes": [], - "anrs":[] + "anrs": [] } }, { @@ -97,7 +97,7 @@ const data = { "nodeColor": "hsl(142, 69%, 58%)", "issues": { "crashes": [], - "anrs":[] + "anrs": [] } }, { @@ -105,7 +105,7 @@ const data = { "nodeColor": "hsl(142, 69%, 58%)", "issues": { "crashes": [], - "anrs":[] + "anrs": [] } } ], @@ -186,25 +186,25 @@ const data = { const formatter = Intl.NumberFormat('en', { notation: 'compact' }); const UserFlowCrashDetails = () => { - return ( - nodeColor} + colors={({ nodeColor }) => nodeColor} nodeOpacity={1} nodeHoverOthersOpacity={0.35} nodeThickness={18} nodeSpacing={24} nodeBorderWidth={0} nodeBorderColor={{ - from: 'color', - modifiers: [ - [ - 'darker', - 0.8 - ] + from: 'color', + modifiers: [ + [ + 'darker', + 0.8 ] + ] }} nodeBorderRadius={3} linkOpacity={0.25} @@ -218,40 +218,40 @@ const UserFlowCrashDetails = () => { nodeTooltip={({ node }) =>
-

{node.label}

- {node.issues.crashes.length > 0 && -
-
-

Crashes:

-
    - {node.issues.crashes.map(({ title, count }) => ( -
  • - {title} - {formatter.format(count)} -
  • - ))} -
-
- } - {node.issues.anrs.length > 0 && -
-
-

ANRs:

-
    - {node.issues.anrs.map(({ title, count }) => ( -
  • - {title} - {formatter.format(count)} -
  • - ))} -
-
- } -
} +

{node.label}

+ {node.issues.crashes.length > 0 && +
+
+

Crashes:

+
    + {node.issues.crashes.map(({ title, count }) => ( +
  • + {title} - {formatter.format(count)} +
  • + ))} +
+
+ } + {node.issues.anrs.length > 0 && +
+
+

ANRs:

+
    + {node.issues.anrs.map(({ title, count }) => ( +
  • + {title} - {formatter.format(count)} +
  • + ))} +
+
+ } +
} linkTooltip={({ link }) =>
-

{link.source.label} > {link.target.label} - {formatter.format(link.value)}

-
} - /> +

{link.source.label} > {link.target.label} - {formatter.format(link.value)}

+
} + /> ); }; diff --git a/measure-web-app/app/globals.css b/measure-web-app/app/globals.css index 82a5b951d..e360de177 100644 --- a/measure-web-app/app/globals.css +++ b/measure-web-app/app/globals.css @@ -8,18 +8,16 @@ --background-end-rgb: 255, 255, 255; } -button, [role="button"] { +button, +[role="button"] { cursor: auto; } body { color: rgb(var(--foreground-rgb)); - background: linear-gradient( - to bottom, + background: linear-gradient(to bottom, transparent, - rgb(var(--background-end-rgb)) - ) - rgb(var(--background-start-rgb)); + rgb(var(--background-end-rgb))) rgb(var(--background-start-rgb)); } @layer base { diff --git a/measure-web-app/app/layout.tsx b/measure-web-app/app/layout.tsx index 9d14dc866..4e3a7cc40 100644 --- a/measure-web-app/app/layout.tsx +++ b/measure-web-app/app/layout.tsx @@ -1,16 +1,20 @@ import './globals.css' import type { Metadata } from 'next' -import {Josefin_Sans, Space_Mono } from 'next/font/google' +import { Josefin_Sans, Space_Mono } from 'next/font/google' -const display = Josefin_Sans({ subsets: ['latin'], display: 'swap', weight:['100','200', '300', '400', '500', '600', '700'], -variable: '--font-display'}) +const display = Josefin_Sans({ + subsets: ['latin'], display: 'swap', weight: ['100', '200', '300', '400', '500', '600', '700'], + variable: '--font-display' +}) -const body = Space_Mono({ subsets: ['latin'], display: 'swap', weight: ['400', '700'], -variable: '--font-body'}) +const body = Space_Mono({ + subsets: ['latin'], display: 'swap', weight: ['400', '700'], + variable: '--font-body' +}) export const metadata: Metadata = { title: 'Measure', description: 'Open source mobile app monitoring | Alternative to Firebase Crashlytics, Instabug, Sentry, Embrace', - viewport: { width: "device-width", initialScale: 1, minimumScale:1 } + viewport: { width: "device-width", initialScale: 1, minimumScale: 1 } } export default function RootLayout({ diff --git a/measure-web-app/app/page.tsx b/measure-web-app/app/page.tsx index 855ffb288..a6b1db3a2 100644 --- a/measure-web-app/app/page.tsx +++ b/measure-web-app/app/page.tsx @@ -9,103 +9,103 @@ import LandingHeader from './components/landing_header' export default function Home() { return (
- +
-
+

measure

-
+

open source app monitoring for mobile teams

-
- -
+
+ +

App health at a glance

-
+

Monitor core user flows and important metrics to stay on top of app health. Filter by various system or custom attributes to dive deeper.

-
- +
+ {/*
*/}
-
+

Crash debugging simplified

-
+

Track crashes and app hangs automatically, prioritise them by impact and use detailed event timelines to zoom in on production issues.

-
-
+
+
-
+

Buttery smooth performance

-
+

Automatically trace app startups, app hangs, network calls, database queries and slow page loads. Use custom traces to measure what matters in any part of your app.

-
-
+
+
-
+

Detailed logging

-
+

Capture standard output/Logcat output automatically. Add custom logs anywhere in your code for easy debugging in production.

-
-
+
+
-
+

Built by and for mobile devs

-
+

Open source platform with a welcoming community. Built by mobile devs who have shipped apps to hundreds of millions of users since the early days of iOS and Android.

-
-
+
+
-
+

Measure on every platform

-
+
-

Android

-

In progress

+

Android

+

In progress

-
+
-

iOS

-

In progress

+

iOS

+

In progress

-
+
-

Flutter

-

In progress

+

Flutter

+

In progress

-
+
-

React Native

-

In progress

+

React Native

+

In progress

-
+
-

Unity

-

In progress

+

Unity

+

In progress

-
+

Early access

-
+

We are building measure for mobile devs like you. Help us make it the best tool for the job!

-
- -
+
+ +
- +
) } diff --git a/measure-web-app/app/utils/auth_utils.tsx b/measure-web-app/app/utils/auth_utils.tsx index f97b91caf..76a3f2e71 100644 --- a/measure-web-app/app/utils/auth_utils.tsx +++ b/measure-web-app/app/utils/auth_utils.tsx @@ -5,7 +5,7 @@ import { AppRouterInstance } from 'next/dist/shared/lib/app-router-context'; const supabase = createBrowserClient() supabase.auth.onAuthStateChange(async (event: AuthChangeEvent, session) => { - switch(event) { + switch (event) { case 'INITIAL_SESSION': if (!globalThis.location) return const urlParams = new URLSearchParams(globalThis.location.hash.substring(1))