-
Notifications
You must be signed in to change notification settings - Fork 1.2k
[OPIK-2848] [FE] Add Comet Debugger Mode with app version and connectivity status #3982
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+220
−8
Merged
Changes from 10 commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
36efb5a
Add Comet Debugger Mode feature and related components
JetoPistola 0296fa0
Add Opik icon to AppDebugInfo component
JetoPistola 2aad3c7
Enhance Switch Component with Extra Small Size Variant
JetoPistola 0572251
Enhance AppNetworkStatus component with styled RTT display
JetoPistola d52576e
Add cometDebuggerModeEnabled toggle to ServiceTogglesConfig
JetoPistola 3540363
Update AppDebugInfo component to conditionally render OPIK version di…
JetoPistola aa1d272
Update end-to-end workflows and configuration for Comet Debugger Mode
JetoPistola 2a9ce72
[OPIK-2848] Fix Tailwind CSS classnames order
JetoPistola 4325754
Refactor UserMenu component to use logical AND for APP_VERSION check
JetoPistola 576b15d
Wrap CometIcon in a span within AppNetworkStatus component for improv…
JetoPistola 4dbd0e5
Revision 2: Add keyboard shortcut for debugger mode and remove menu t…
JetoPistola 51f169b
Revision 2: Remove COMET_DEBUGGER_MODE from feature toggles
JetoPistola ba43032
Revision 3: Revert to ThemeToggle and remove redundant empty line
JetoPistola d7f810e
Revision 4: Use absolute imports for ThemeToggle component
JetoPistola e2842f6
Revision 5: Remove redundant DebugStore and use simple localStorage s…
JetoPistola c9ce853
Revision 2: Refactor AppDebugInfo to use react-hotkeys-hook and make …
JetoPistola 2bb63cb
Revision 3: Move AppNetworkStatus to layout components
JetoPistola 8c1312e
Revision 4: Move AppDebugInfo to layout components
JetoPistola File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import api from "@/api/api"; | ||
| import { useQuery } from "@tanstack/react-query"; | ||
|
|
||
| const PING_FETCHING_TIMEOUT_SECONDS = 5; | ||
| const CONNECTED_PING_REFETCH_INTERVAL_SECONDS = 10; | ||
| const DISCONNECTED_PING_REFETCH_INTERVAL_SECONDS = 5; | ||
|
|
||
| interface IsAlivePingResponse { | ||
| healthy: boolean; | ||
| rtt: number; | ||
| } | ||
|
|
||
| const getPing = async (): Promise<IsAlivePingResponse> => { | ||
| const startTime = performance.now(); | ||
|
|
||
| const { data } = await api.get<IsAlivePingResponse>("/is-alive/ping", { | ||
| timeout: PING_FETCHING_TIMEOUT_SECONDS * 1000, | ||
| }); | ||
|
|
||
| const endTime = performance.now(); | ||
|
|
||
| const rtt = endTime - startTime; | ||
|
|
||
| return { ...data, rtt }; | ||
| }; | ||
|
|
||
| export const usePingBackend = (isNetworkOnline: boolean) => | ||
| useQuery({ | ||
| queryKey: ["backend-ping"], | ||
| queryFn: getPing, | ||
| enabled: isNetworkOnline, | ||
| retryDelay: 1000, | ||
| refetchInterval: (query) => { | ||
| const { error: isError, data } = query.state; | ||
| const isConnected = !isError && data?.healthy; | ||
|
|
||
| return isConnected | ||
| ? CONNECTED_PING_REFETCH_INTERVAL_SECONDS * 1000 | ||
| : DISCONNECTED_PING_REFETCH_INTERVAL_SECONDS * 1000; | ||
| }, | ||
| refetchOnReconnect: true, | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
apps/opik-frontend/src/components/layout/AppDebugInfo/AppDebugInfo.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| import { useIsFeatureEnabled } from "@/components/feature-toggles-provider"; | ||
| import { toast } from "@/components/ui/use-toast"; | ||
| import { APP_VERSION } from "@/constants/app"; | ||
| import AppNetworkStatus from "@/plugins/comet/AppNetworkStatus"; | ||
JetoPistola marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| import OpikIcon from "@/icons/opik.svg?react"; | ||
| import { COMET_DEBUGGER_MODE_KEY } from "@/plugins/comet/UserMenuAppDebugInfoToggle"; | ||
| import { useDebugStore } from "@/store/DebugStore"; | ||
| import { FeatureToggleKeys } from "@/types/feature-toggles"; | ||
| import copy from "clipboard-copy"; | ||
| import { Copy } from "lucide-react"; | ||
| import { useEffect } from "react"; | ||
|
|
||
| const AppDebugInfo = () => { | ||
| const showAppDebugInfo = useDebugStore((state) => state.showAppDebugInfo); | ||
| const isCometDebuggerModeEnabled = useIsFeatureEnabled( | ||
| FeatureToggleKeys.COMET_DEBUGGER_MODE_ENABLED, | ||
| ); | ||
| const setShowAppDebugInfo = useDebugStore( | ||
| (state) => state.setShowAppDebugInfo, | ||
| ); | ||
|
|
||
| useEffect(() => { | ||
JetoPistola marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const localStorageValue = localStorage.getItem(COMET_DEBUGGER_MODE_KEY); | ||
| const shouldShowAppDebugInfo = | ||
| isCometDebuggerModeEnabled && localStorageValue?.toLowerCase() === "true"; | ||
|
|
||
| setShowAppDebugInfo(shouldShowAppDebugInfo); | ||
| }, [isCometDebuggerModeEnabled, setShowAppDebugInfo]); | ||
|
|
||
| return ( | ||
| showAppDebugInfo && ( | ||
| <> | ||
| <div className="flex items-center"> | ||
| <AppNetworkStatus /> | ||
| </div> | ||
|
|
||
| {APP_VERSION && ( | ||
| <div | ||
| className="flex items-center gap-2" | ||
| onClick={() => { | ||
| copy(APP_VERSION); | ||
| toast({ description: "Successfully copied version" }); | ||
| }} | ||
| > | ||
JetoPistola marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| <span className="comet-body-s-accented flex items-center gap-2 truncate"> | ||
| <OpikIcon className="size-5" /> | ||
| OPIK VERSION {APP_VERSION} | ||
| </span> | ||
| <Copy className="size-4 shrink-0" /> | ||
| </div> | ||
| )} | ||
| </> | ||
| ) | ||
| ); | ||
| }; | ||
|
|
||
| export default AppDebugInfo; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| import { Check, Copy, Settings2 } from "lucide-react"; | ||
| import copy from "clipboard-copy"; | ||
|
|
||
| import { Button } from "@/components/ui/button"; | ||
| import { | ||
| DropdownMenu, | ||
| DropdownMenuContent, | ||
| DropdownMenuGroup, | ||
| DropdownMenuItem, | ||
| DropdownMenuPortal, | ||
| DropdownMenuSeparator, | ||
| DropdownMenuSub, | ||
| DropdownMenuSubContent, | ||
| DropdownMenuSubTrigger, | ||
| DropdownMenuTrigger, | ||
| } from "@/components/ui/dropdown-menu"; | ||
| import { useThemeOptions } from "@/hooks/useThemeOptions"; | ||
| import { APP_VERSION } from "@/constants/app"; | ||
| import { toast } from "../ui/use-toast"; | ||
| import UserMenuAppDebugInfoToggle from "@/plugins/comet/UserMenuAppDebugInfoToggle"; | ||
| import { FeatureToggleKeys } from "@/types/feature-toggles"; | ||
| import { useIsFeatureEnabled } from "../feature-toggles-provider"; | ||
|
|
||
| const NoUserMenu = () => { | ||
| const isCometDebuggerModeEnabled = useIsFeatureEnabled( | ||
| FeatureToggleKeys.COMET_DEBUGGER_MODE_ENABLED, | ||
| ); | ||
| const { theme, themeOptions, currentOption, CurrentIcon, handleThemeSelect } = | ||
| useThemeOptions(); | ||
|
|
||
| return ( | ||
| <DropdownMenu> | ||
| <DropdownMenuTrigger asChild> | ||
| <Button variant="outline" size="icon-sm"> | ||
| <Settings2 className="size-[1.2rem]" /> | ||
| <span className="sr-only"> | ||
| Current theme: {currentOption?.label || "Unknown"} | ||
| </span> | ||
| </Button> | ||
| </DropdownMenuTrigger> | ||
| <DropdownMenuContent align="end"> | ||
| <DropdownMenuGroup> | ||
| {isCometDebuggerModeEnabled && <UserMenuAppDebugInfoToggle />} | ||
| <DropdownMenuSub> | ||
| <DropdownMenuSubTrigger className="flex cursor-pointer items-center"> | ||
| <CurrentIcon className="mr-2 size-4" /> | ||
| <span>Theme</span> | ||
| </DropdownMenuSubTrigger> | ||
| <DropdownMenuPortal> | ||
| <DropdownMenuSubContent> | ||
| {themeOptions.map(({ value, label, icon: Icon }) => ( | ||
| <DropdownMenuItem | ||
| key={value} | ||
| className="cursor-pointer" | ||
| onClick={() => handleThemeSelect(value)} | ||
| > | ||
| <div className="relative flex w-full items-center pl-6"> | ||
| {theme === value && ( | ||
| <Check className="absolute left-0 size-4" /> | ||
| )} | ||
| <Icon className="mr-2 size-4" /> | ||
| <span>{label}</span> | ||
| </div> | ||
| </DropdownMenuItem> | ||
| ))} | ||
| </DropdownMenuSubContent> | ||
| </DropdownMenuPortal> | ||
| </DropdownMenuSub> | ||
| </DropdownMenuGroup> | ||
| {APP_VERSION && ( | ||
| <> | ||
| <DropdownMenuSeparator /> | ||
| <DropdownMenuItem | ||
| className="cursor-pointer justify-center text-light-slate" | ||
| onClick={() => { | ||
| copy(APP_VERSION); | ||
| toast({ description: "Successfully copied version" }); | ||
| }} | ||
| > | ||
| <span className="comet-body-xs-accented truncate "> | ||
| VERSION {APP_VERSION} | ||
| </span> | ||
| <Copy className="ml-2 size-3 shrink-0" /> | ||
| </DropdownMenuItem> | ||
| </> | ||
| )} | ||
| </DropdownMenuContent> | ||
| </DropdownMenu> | ||
| ); | ||
| }; | ||
|
|
||
| export default NoUserMenu; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import { useState, useEffect } from "react"; | ||
|
|
||
| const useIsNetworkOnline = () => { | ||
| const [isNetworkOnline, setIsNetworkOnline] = useState(navigator.onLine); | ||
|
|
||
| useEffect(() => { | ||
| const updateNetworkStatus = () => setIsNetworkOnline(navigator.onLine); | ||
|
|
||
| window.addEventListener("online", updateNetworkStatus); | ||
| window.addEventListener("offline", updateNetworkStatus); | ||
|
|
||
| return () => { | ||
| window.removeEventListener("online", updateNetworkStatus); | ||
| window.removeEventListener("offline", updateNetworkStatus); | ||
| }; | ||
| }, []); | ||
|
|
||
| return isNetworkOnline; | ||
| }; | ||
|
|
||
| export default useIsNetworkOnline; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.