diff --git a/src/api/index.ts b/src/api/index.ts index ebcd0788c..f1f994ac4 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -1,6 +1,6 @@ import { isObject } from "../typeGuards/isObject"; import { ActionDispatcher } from "./ActionDispatcher"; -import { DigmaMessageEvent } from "./types"; +import { DigmaMessageEvent, DigmaOutgoingMessageData } from "./types"; const isDigmaMessageEvent = (e: MessageEvent): e is DigmaMessageEvent => isObject(e.data) && e.data.type === "digma"; @@ -16,10 +16,9 @@ export const initializeDigmaMessageListener = ( }); }; -export const sendMessage = (message: { - action: string; - payload?: unknown; -}): string | undefined => { +export const sendMessage = ( + message: DigmaOutgoingMessageData +): string | undefined => { if (window.sendMessageToVSCode) { window.sendMessageToVSCode(message); console.info("Message has been sent to VS Code: ", message); diff --git a/src/api/types.ts b/src/api/types.ts index 330a2afca..8e7a18f30 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -1,9 +1,14 @@ export type ActionListener = (data: unknown) => void; -export interface DigmaMessageEventData { +export interface DigmaIncomingMessageData { type: "digma"; action: string; payload?: unknown; } -export type DigmaMessageEvent = MessageEvent; +export interface DigmaOutgoingMessageData { + action: string; + payload?: Record; +} + +export type DigmaMessageEvent = MessageEvent; diff --git a/src/components/Assets/AssetList/index.tsx b/src/components/Assets/AssetList/index.tsx index fea273ea8..1f222355a 100644 --- a/src/components/Assets/AssetList/index.tsx +++ b/src/components/Assets/AssetList/index.tsx @@ -183,7 +183,7 @@ export const AssetList = (props: AssetListProps) => { /> - + ({ value: x, label: x }))} diff --git a/src/components/Assets/index.tsx b/src/components/Assets/index.tsx index f01269a59..89f37cf8b 100644 --- a/src/components/Assets/index.tsx +++ b/src/components/Assets/index.tsx @@ -102,7 +102,7 @@ export const Assets = (props: AssetsProps) => { const handleAssetLinkClick = (entry: AssetEntry) => { window.sendMessageToDigma({ action: actions.goToAsset, - data: { entry } + payload: { entry } }); }; diff --git a/src/components/InstallationWizard/index.tsx b/src/components/InstallationWizard/index.tsx index e47083c0e..4c0e7daf6 100644 --- a/src/components/InstallationWizard/index.tsx +++ b/src/components/InstallationWizard/index.tsx @@ -1,40 +1,78 @@ import copy from "copy-to-clipboard"; -import { useState } from "react"; +import { useEffect, useState } from "react"; +import { dispatcher } from "../../dispatcher"; import { getActions } from "../../utils/getActions"; +import { actions as globalActions } from "../common/App"; import { CheckmarkCircleIcon } from "../common/icons/CheckmarkCircleIcon"; import { CheckmarkCircleInvertedIcon } from "../common/icons/CheckmarkCircleInvertedIcon"; import { CopyIcon } from "../common/icons/CopyIcon"; +import { CrossCircleIcon } from "../common/icons/CrossCircleIcon"; import { Loader } from "../common/Loader"; import { Button } from "./Button"; import * as s from "./styles"; +import { ConnectionCheckResultData, ConnectionCheckStatus } from "./types"; const ACTION_PREFIX = "INSTALLATION_WIZARD"; const actions = getActions(ACTION_PREFIX, { - finish: "FINISH" + finish: "FINISH", + checkConnection: "CHECK_CONNECTION", + setConnectionCheckResult: "SET_CONNECTION_CHECK_RESULT" }); export const InstallationWizard = () => { const [currentStep, setCurrentStep] = useState(0); - const [isDigmaInstalled, setIsDigmaInstalled] = useState(false); const [isCollectorModified, setIsCollectorModified] = useState(false); const [isAlreadyUsingOtel, setIsAlreadyUsingOtel] = useState(false); + const [connectionCheckStatus, setConnectionCheckStatus] = + useState(); + + useEffect(() => { + const handleConnectionCheckResultData = (data: unknown) => { + const result = (data as ConnectionCheckResultData).result; + setConnectionCheckStatus(result); + }; + + dispatcher.addActionListener( + actions.setConnectionCheckResult, + handleConnectionCheckResultData + ); + + return () => { + dispatcher.removeActionListener( + actions.setConnectionCheckResult, + handleConnectionCheckResultData + ); + }; + }, []); const handleCopyButtonClick = (text: string) => { copy(text); }; + const startConnectionCheck = () => { + setConnectionCheckStatus("pending"); + window.sendMessageToDigma({ + action: actions.checkConnection + }); + }; + const handleDigmaIsInstalledButtonClick = () => { - setIsDigmaInstalled(true); + startConnectionCheck(); + }; + + const handleRetryButtonClick = () => { + startConnectionCheck(); }; const handleInstallDigmaButtonClick = () => { - window.open( - "https://open.docker.com/extensions/marketplace?extensionId=digmaai/digma-docker-extension", - "_blank", - "noopener,noreferrer" - ); + window.sendMessageToDigma({ + action: globalActions.openURLInDefaultBrowser, + payload: { + url: "https://open.docker.com/extensions/marketplace?extensionId=digmaai/digma-docker-extension" + } + }); }; const handleContinueButtonClick = () => { @@ -78,9 +116,9 @@ export const InstallationWizard = () => { (You’ll need{" "} Docker Desktop {" "} @@ -88,7 +126,7 @@ export const InstallationWizard = () => { + )} + {connectionCheckStatus === "success" && ( + - ) : ( + )} + {connectionCheckStatus === "failure" && ( )} - + {connectionCheckStatus && ( + + )} - + {connectionCheckStatus === "failure" ? ( + + ) : ( + + )} Skip for now @@ -218,12 +271,12 @@ service: handleCopyButtonClick(collectorConfigurationSnippet)} > - + {isCollectorModified ? ( ) : ( diff --git a/src/components/InstallationWizard/types.ts b/src/components/InstallationWizard/types.ts new file mode 100644 index 000000000..61792b51e --- /dev/null +++ b/src/components/InstallationWizard/types.ts @@ -0,0 +1,10 @@ +export type ConnectionCheckResult = "success" | "failure"; + +export type ConnectionCheckStatus = + | ConnectionCheckResult + | "pending" + | undefined; + +export interface ConnectionCheckResultData { + result: ConnectionCheckResult; +} diff --git a/src/components/RecentActivity/EnvironmentPanel/styles.ts b/src/components/RecentActivity/EnvironmentPanel/styles.ts index 398fc2dae..05f73fd28 100644 --- a/src/components/RecentActivity/EnvironmentPanel/styles.ts +++ b/src/components/RecentActivity/EnvironmentPanel/styles.ts @@ -9,7 +9,6 @@ const backgroundAnimation = keyframes` `; export const BorderContainer = styled.div` padding: 1px; - height: 38px; min-width: fit-content; border-radius: ${BORDER_RADIUS}px; ${/* TODO: Change to radial gradient after cross-fading */ ""} @@ -58,6 +57,8 @@ export const Container = styled.div` border-radius: 8px; position: relative; box-sizing: border-box; + + flex-wrap: wrap; `; const rotateAnimation = keyframes` diff --git a/src/components/RecentActivity/RecentActivity.stories.tsx b/src/components/RecentActivity/RecentActivity.stories.tsx index 4e5e61cb4..9afde8c1b 100644 --- a/src/components/RecentActivity/RecentActivity.stories.tsx +++ b/src/components/RecentActivity/RecentActivity.stories.tsx @@ -22,7 +22,21 @@ Empty.args = {}; export const WithData = Template.bind({}); WithData.args = { data: { - environments: ["ENV_RENDER", "UNSET_ENV"], + environments: [ + "ENV_RENDER", + "UNSET_ENV", + "UNSET_ENV1", + "UNSET_ENV2", + "UNSET_ENV3", + "UNSET_ENV4", + "UNSET_ENV5", + "UNSET_ENV6", + "UNSET_ENV7", + "UNSET_ENV8", + "UNSET_ENV9", + "UNSET_ENV10", + "UNSET_ENV11" + ], entries: [ { environment: "ENV_RENDER", diff --git a/src/components/common/App/index.tsx b/src/components/common/App/index.tsx index aa6842c43..e1db74e5e 100644 --- a/src/components/common/App/index.tsx +++ b/src/components/common/App/index.tsx @@ -4,6 +4,7 @@ import { dispatcher } from "../../../dispatcher"; import { Mode } from "../../../globals"; import { isObject } from "../../../typeGuards/isObject"; import { isString } from "../../../typeGuards/isString"; +import { getActions } from "../../../utils/getActions"; import { GlobalStyle } from "./styles"; import { AppProps } from "./types"; @@ -24,11 +25,14 @@ const getMode = (): Mode => { return window.theme; }; -const actions = { - setColorMode: "GLOBAL/SET_THEME", - setMainFont: "GLOBAL/SET_MAIN_FONT", - setCodeFont: "GLOBAL/SET_CODE_FONT" -}; +const ACTION_PREFIX = "GLOBAL"; + +export const actions = getActions(ACTION_PREFIX, { + setColorMode: "SET_THEME", + setMainFont: "SET_MAIN_FONT", + setCodeFont: "SET_CODE_FONT", + openURLInDefaultBrowser: "OPEN_URL_IN_DEFAULT_BROWSER" +}); export const App = (props: AppProps) => { const [mode, setMode] = useState(getMode()); diff --git a/src/components/common/Loader/index.tsx b/src/components/common/Loader/index.tsx index a90267f2f..469b4af72 100644 --- a/src/components/common/Loader/index.tsx +++ b/src/components/common/Loader/index.tsx @@ -31,13 +31,15 @@ const PupilInnerCircle = styled.div` `; const LoaderComponent = (props: LoaderProps) => { + const size = props.size || 20; + switch (props.status) { case "success": return ( @@ -133,12 +135,161 @@ const LoaderComponent = (props: LoaderProps) => { /> ); + case "failure": + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); case "pending": return ( diff --git a/src/components/common/Loader/types.ts b/src/components/common/Loader/types.ts index a365118d3..314c6d004 100644 --- a/src/components/common/Loader/types.ts +++ b/src/components/common/Loader/types.ts @@ -1,4 +1,4 @@ export interface LoaderProps { size?: number; - status: "pending" | "success"; + status: "pending" | "success" | "failure"; } diff --git a/src/components/common/Popover/PopoverTrigger/index.tsx b/src/components/common/Popover/PopoverTrigger/index.tsx index 2f9b4b576..260d427b8 100644 --- a/src/components/common/Popover/PopoverTrigger/index.tsx +++ b/src/components/common/Popover/PopoverTrigger/index.tsx @@ -45,7 +45,7 @@ const PopoverTriggerComponent = ( return ( void; }) => string; cefQueryCancel?: (request_id: string) => void; - sendMessageToDigma: (message: any) => string | undefined; + sendMessageToDigma: ( + message: DigmaOutgoingMessageData + ) => string | undefined; cancelMessageToDigma: (request_id: string) => void; theme?: unknown; environment?: unknown;