From 89a6cf7708a438ce667bd4f5a2bac20b6a5aae89 Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Tue, 12 Mar 2024 18:48:25 +0100 Subject: [PATCH 1/5] Add Main app --- package.json | 2 + src/api/index.ts | 4 +- src/api/types.ts | 6 ++ src/api/web/sendMessageToWebService.ts | 4 +- src/components/Main/Main.stories.tsx | 115 +++++++++++++++++++++++++ src/components/Main/actions.ts | 8 ++ src/components/Main/index.tsx | 42 +++++++++ src/components/Main/typeGuards.ts | 4 + src/components/Main/types.ts | 1 + src/components/Navigation/types.ts | 1 + src/containers/Main/index.tsx | 25 ++++++ webpackEntries.ts | 3 + 12 files changed, 212 insertions(+), 3 deletions(-) create mode 100644 src/components/Main/Main.stories.tsx create mode 100644 src/components/Main/actions.ts create mode 100644 src/components/Main/index.tsx create mode 100644 src/components/Main/typeGuards.ts create mode 100644 src/components/Main/types.ts create mode 100644 src/containers/Main/index.tsx diff --git a/package.json b/package.json index c8ed7b83e..2c41f8871 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "build:documentation:dev": "webpack --config webpack.dev.ts --env app=documentation", "build:insights:dev": "webpack --config webpack.dev.ts --env app=insights", "build:installation-wizard:dev": "webpack --config webpack.dev.ts --env app=installationWizard", + "build:main:dev": "webpack --config webpack.dev.ts --env app=main", "build:navigation:dev": "webpack --config webpack.dev.ts --env app=navigation", "build:notifications:dev": "webpack --config webpack.dev.ts --env app=notifications", "build:recentActivity:dev": "webpack --config webpack.dev.ts --env app=recentActivity", @@ -28,6 +29,7 @@ "build:documentation:prod": "webpack --config webpack.prod.ts --env app=documentation", "build:insights:prod": "webpack --config webpack.prod.ts --env app=insights", "build:installation-wizard:prod": "webpack --config webpack.prod.ts --env app=installationWizard", + "build:main:prod": "webpack --config webpack.prod.ts --env app=main", "build:navigation:prod": "webpack --config webpack.prod.ts --env app=navigation", "build:notifications:prod": "webpack --config webpack.prod.ts --env app=notifications", "build:recentActivity:prod": "webpack --config webpack.prod.ts --env app=recentActivity", diff --git a/src/api/index.ts b/src/api/index.ts index 335183426..1765b23b3 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -21,11 +21,13 @@ export const initializeDigmaMessageListener = ( export const sendMessage = ( message: DigmaOutgoingMessageData ): string | undefined => { + const extendedMessage = { ...message, id: `${message.action}-${Date.now()}` }; + console.debug("Message to send:", message); switch (platform) { case "Web": - sendMessageToWebService(message); + sendMessageToWebService(extendedMessage); break; case "VS Code": if (window.sendMessageToVSCode) { diff --git a/src/api/types.ts b/src/api/types.ts index b6496e958..78bacfb85 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -2,6 +2,7 @@ export type ActionListener = (data: unknown, timeStamp: number) => void; export interface DigmaIncomingMessageData { type: "digma"; + id?: string; action: string; payload?: unknown; } @@ -11,4 +12,9 @@ export interface DigmaOutgoingMessageData { payload?: T; } +export interface ExtendedDigmaOutgoingMessageData + extends DigmaOutgoingMessageData { + id: string; +} + export type DigmaMessageEvent = MessageEvent; diff --git a/src/api/web/sendMessageToWebService.ts b/src/api/web/sendMessageToWebService.ts index 4042feec8..3f153ca14 100644 --- a/src/api/web/sendMessageToWebService.ts +++ b/src/api/web/sendMessageToWebService.ts @@ -1,12 +1,12 @@ import { actions as globalActions } from "../../actions"; import { actions as dashboardActions } from "../../components/Dashboard/actions"; -import { DigmaOutgoingMessageData } from "../types"; +import { ExtendedDigmaOutgoingMessageData } from "../types"; import { getAboutInfo } from "./services/about"; import { GetDashboardParams, getDashboard } from "./services/dashboard"; import { GetEnvironmentParams, getEnvironment } from "./services/environments"; export const sendMessageToWebService = ( - message: DigmaOutgoingMessageData + message: ExtendedDigmaOutgoingMessageData ) => { switch (message.action) { case dashboardActions.GET_DATA: diff --git a/src/components/Main/Main.stories.tsx b/src/components/Main/Main.stories.tsx new file mode 100644 index 000000000..61d897795 --- /dev/null +++ b/src/components/Main/Main.stories.tsx @@ -0,0 +1,115 @@ +import { Meta, StoryObj } from "@storybook/react"; + +import { Main } from "."; +import { SetViewsPayload } from "../Navigation/types"; +import { actions } from "./actions"; + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction +const meta: Meta = { + title: "Main/Main", + component: Main, + parameters: { + // More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout + layout: "fullscreen" + } +}; + +export default meta; + +type Story = StoryObj; + +const data: SetViewsPayload = { + views: [ + { + isDisabled: false, + isSelected: true, + hasNewData: false, + isHidden: false, + title: "Insights", + id: "insights", + cardName: "insights" + }, + { + isDisabled: false, + isSelected: false, + hasNewData: false, + isHidden: false, + title: "Assets", + id: "assets", + cardName: "assets" + }, + { + isDisabled: false, + isSelected: false, + hasNewData: false, + isHidden: false, + title: "Errors", + id: "errors", + cardName: "errors" + }, + { + isDisabled: false, + isSelected: false, + hasNewData: false, + isHidden: true, + title: "Error Details", + id: "errorsDetails", + cardName: "errors" + }, + { + isDisabled: false, + isSelected: false, + hasNewData: false, + isHidden: false, + title: "Tests", + id: "tests", + cardName: "tests" + } + ], + isTriggeredByJcef: false +}; + +const updateSelectedView = ( + data: SetViewsPayload, + viewId: string +): SetViewsPayload => { + return { + ...data, + views: data.views.map((view) => + view.id === viewId + ? { ...view, isSelected: true } + : { ...view, isSelected: false } + ) + }; +}; + +// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args +export const Insights: Story = { + play: () => { + window.postMessage({ + type: "digma", + action: actions.SET_VIEWS, + payload: updateSelectedView(data, "insights") + }); + } +}; + +export const Assets: Story = { + play: () => { + window.postMessage({ + type: "digma", + action: actions.SET_VIEWS, + payload: updateSelectedView(data, "assets") + }); + } +}; + +export const Tests: Story = { + play: () => { + window.postMessage({ + type: "digma", + action: actions.SET_VIEWS, + payload: updateSelectedView(data, "tests") + }); + } +}; diff --git a/src/components/Main/actions.ts b/src/components/Main/actions.ts new file mode 100644 index 000000000..409609e1d --- /dev/null +++ b/src/components/Main/actions.ts @@ -0,0 +1,8 @@ +import { addPrefix } from "../../utils/addPrefix"; + +const ACTION_PREFIX = "MAIN"; + +export const actions = addPrefix(ACTION_PREFIX, { + INITIALIZE: "INITIALIZE", + SET_VIEWS: "SET_VIEWS" +}); diff --git a/src/components/Main/index.tsx b/src/components/Main/index.tsx new file mode 100644 index 000000000..bf0410e13 --- /dev/null +++ b/src/components/Main/index.tsx @@ -0,0 +1,42 @@ +import { useLayoutEffect, useState } from "react"; +import { dispatcher } from "../../dispatcher"; +import { Assets } from "../Assets"; +import { Insights } from "../Insights"; +import { SetViewsPayload } from "../Navigation/types"; +import { Tests } from "../Tests"; +import { actions } from "./actions"; +import { isView } from "./typeGuards"; +import { View } from "./types"; + +export const Main = () => { + const [view, setView] = useState("insights"); + + useLayoutEffect(() => { + window.sendMessageToDigma({ + action: actions.INITIALIZE + }); + + const handleSetViewsData = (data: unknown) => { + const payload = data as SetViewsPayload; + const view = payload.views.find((x) => x.isSelected); + if (view && isView(view?.id)) { + setView(view.id); + } + }; + + dispatcher.addActionListener(actions.SET_VIEWS, handleSetViewsData); + + return () => { + dispatcher.removeActionListener(actions.SET_VIEWS, handleSetViewsData); + }; + }, []); + + switch (view) { + case "insights": + return ; + case "assets": + return ; + case "tests": + return ; + } +}; diff --git a/src/components/Main/typeGuards.ts b/src/components/Main/typeGuards.ts new file mode 100644 index 000000000..2503a9bf7 --- /dev/null +++ b/src/components/Main/typeGuards.ts @@ -0,0 +1,4 @@ +import { View } from "./types"; + +export const isView = (view: string): view is View => + ["insights", "assets", "tests"].includes(view); diff --git a/src/components/Main/types.ts b/src/components/Main/types.ts new file mode 100644 index 000000000..abb49604a --- /dev/null +++ b/src/components/Main/types.ts @@ -0,0 +1 @@ +export type View = "insights" | "assets" | "tests"; diff --git a/src/components/Navigation/types.ts b/src/components/Navigation/types.ts index 48e981eea..2f74e9c61 100644 --- a/src/components/Navigation/types.ts +++ b/src/components/Navigation/types.ts @@ -39,6 +39,7 @@ export interface ChangeViewPayload { export interface SetViewsPayload { views: TabData[]; + isTriggeredByJcef: boolean; } export interface AutoFixMissingDependencyPayload { diff --git a/src/containers/Main/index.tsx b/src/containers/Main/index.tsx new file mode 100644 index 000000000..172470f58 --- /dev/null +++ b/src/containers/Main/index.tsx @@ -0,0 +1,25 @@ +import { createRoot } from "react-dom/client"; +import { + cancelMessage, + initializeDigmaMessageListener, + sendMessage +} from "../../api"; +import { Main } from "../../components/Main"; +import { App } from "../../components/common/App"; +import { dispatcher } from "../../dispatcher"; + +initializeDigmaMessageListener(dispatcher); + +window.sendMessageToDigma = sendMessage; +window.cancelMessageToDigma = cancelMessage; + +const rootElement = document.getElementById("root"); + +if (rootElement) { + const root = createRoot(rootElement); + root.render( + +
+ + ); +} diff --git a/webpackEntries.ts b/webpackEntries.ts index 1f2adaaf8..355c22442 100644 --- a/webpackEntries.ts +++ b/webpackEntries.ts @@ -28,6 +28,9 @@ export const entries: AppEntries = { ), environmentVariables: ["wizardFirstLaunch", "wizardSkipInstallationStep"] }, + main: { + entry: path.resolve(__dirname, "./src/containers/Main/index.tsx") + }, navigation: { entry: path.resolve(__dirname, "./src/containers/Navigation/index.tsx") }, From 12428beff58ae7e0295fc386e278256711626baa Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Thu, 14 Mar 2024 10:15:25 +0100 Subject: [PATCH 2/5] Add Analytics app --- src/components/Assets/actions.ts | 1 - src/components/Assets/index.tsx | 19 ++---- .../Insights/InsightsCatalog/index.tsx | 20 +++--- .../Insights/InsightsCatalog/types.ts | 1 + src/components/Insights/actions.ts | 1 - src/components/Insights/index.tsx | 30 +++++---- src/components/Insights/types.ts | 4 ++ src/components/Main/Main.stories.tsx | 58 ++---------------- src/components/Main/index.tsx | 4 +- src/components/Main/typeGuards.ts | 2 +- src/components/Main/types.ts | 2 +- .../Navigation/Navigation.stories.tsx | 10 ++- src/components/Navigation/Tabs/index.tsx | 5 +- src/components/Navigation/mockData.ts | 61 +++++++++++++++++++ .../RecentActivityTable/getTagType.ts | 6 +- .../RecentActivityTable/index.tsx | 2 +- src/components/RecentActivity/types.ts | 2 +- src/components/Tests/actions.ts | 1 - src/components/Tests/index.tsx | 4 -- src/containers/Insights/index.tsx | 2 +- webpackEntries.ts | 9 ++- 21 files changed, 140 insertions(+), 104 deletions(-) create mode 100644 src/components/Navigation/mockData.ts diff --git a/src/components/Assets/actions.ts b/src/components/Assets/actions.ts index 3c7a27e86..89d8b1d12 100644 --- a/src/components/Assets/actions.ts +++ b/src/components/Assets/actions.ts @@ -3,7 +3,6 @@ import { addPrefix } from "../../utils/addPrefix"; const ACTION_PREFIX = "ASSETS"; export const actions = addPrefix(ACTION_PREFIX, { - INITIALIZE: "INITIALIZE", GET_DATA: "GET_DATA", SET_DATA: "SET_DATA", GO_TO_ASSET: "GO_TO_ASSET", diff --git a/src/components/Assets/index.tsx b/src/components/Assets/index.tsx index baad64d03..6a80c10c6 100644 --- a/src/components/Assets/index.tsx +++ b/src/components/Assets/index.tsx @@ -1,10 +1,4 @@ -import { - useContext, - useEffect, - useLayoutEffect, - useMemo, - useState -} from "react"; +import { useContext, useEffect, useMemo, useState } from "react"; import { lt, valid } from "semver"; import { featureFlagMinBackendVersions, @@ -27,7 +21,6 @@ import { AssetsViewScopeConfiguration } from "./AssetsViewScopeConfiguration"; import { AssetScopeOption } from "./AssetsViewScopeConfiguration/types"; import { NoDataMessage } from "./NoDataMessage"; import { ServicesFilter } from "./ServicesFilter"; -import { actions } from "./actions"; import * as s from "./styles"; import { trackingEvents } from "./tracking"; import { DataRefresher } from "./types"; @@ -74,11 +67,11 @@ export const Assets = () => { ); }, [config]); - useLayoutEffect(() => { - window.sendMessageToDigma({ - action: actions.INITIALIZE - }); - }, []); + // useLayoutEffect(() => { + // window.sendMessageToDigma({ + // action: actions.INITIALIZE + // }); + // }, []); useEffect(() => { if (!config.scope?.span) { diff --git a/src/components/Insights/InsightsCatalog/index.tsx b/src/components/Insights/InsightsCatalog/index.tsx index 6cc3f9811..cd7b47313 100644 --- a/src/components/Insights/InsightsCatalog/index.tsx +++ b/src/components/Insights/InsightsCatalog/index.tsx @@ -2,11 +2,9 @@ import { useCallback, useContext, useEffect, useState } from "react"; import { usePrevious } from "../../../hooks/usePrevious"; import { useTheme } from "styled-components"; -import { getFeatureFlagValue } from "../../../featureFlags"; import { useDebounce } from "../../../hooks/useDebounce"; import { isNumber } from "../../../typeGuards/isNumber"; import { isUndefined } from "../../../typeGuards/isUndefined"; -import { FeatureFlag } from "../../../types"; import { sendTrackingEvent } from "../../../utils/sendTrackingEvent"; import { ConfigContext } from "../../common/App/ConfigContext"; import { Pagination } from "../../common/Pagination"; @@ -53,20 +51,27 @@ export const InsightsCatalog = (props: InsightsCatalogProps) => { const previousMode = usePrevious(mode); const theme = useTheme(); - const isViewModeButtonVisible = Boolean( - getFeatureFlagValue(config, FeatureFlag.IS_INSIGHT_DISMISSAL_ENABLED) && - (isUndefined(props.dismissedCount) || props.dismissedCount > 0) // isUndefined - check for backward compatibility, always show when BE does not return this counter - ); + const isViewModeButtonVisible = + props.isDismissalEnabled && + (isUndefined(props.dismissedCount) || props.dismissedCount > 0); // isUndefined - check for backward compatibility, always show when BE does not return this counter const refreshData = useCallback( () => props.onQueryChange({ + ...props.defaultQuery, page, sorting, searchQuery: debouncedSearchInputValue, showDismissed: mode === ViewMode.OnlyDismissed }), - [page, sorting, debouncedSearchInputValue, props, mode] + [ + page, + sorting, + debouncedSearchInputValue, + props.onQueryChange, + props.defaultQuery, + mode + ] ); const handleRefreshButtonClick = () => { @@ -119,7 +124,6 @@ export const InsightsCatalog = (props: InsightsCatalogProps) => { page, debouncedSearchInputValue, previousSearchQuery, - props.onQueryChange, refreshData, mode, previousMode diff --git a/src/components/Insights/InsightsCatalog/types.ts b/src/components/Insights/InsightsCatalog/types.ts index 87ba0cbfe..69cb5a607 100644 --- a/src/components/Insights/InsightsCatalog/types.ts +++ b/src/components/Insights/InsightsCatalog/types.ts @@ -11,6 +11,7 @@ export interface InsightsCatalogProps { onQueryChange: (query: InsightsQuery) => void; defaultQuery: InsightsQuery; onRefresh: () => void; + isDismissalEnabled: boolean; } export enum SORTING_CRITERION { diff --git a/src/components/Insights/actions.ts b/src/components/Insights/actions.ts index 6cf2567ca..009e93530 100644 --- a/src/components/Insights/actions.ts +++ b/src/components/Insights/actions.ts @@ -3,7 +3,6 @@ import { addPrefix } from "../../utils/addPrefix"; const ACTION_PREFIX = "INSIGHTS"; export const actions = addPrefix(ACTION_PREFIX, { - INITIALIZE: "INITIALIZE", GET_DATA: "GET_DATA", SET_DATA: "SET_DATA", GO_TO_ERRORS: "GO_TO_ERRORS", diff --git a/src/components/Insights/index.tsx b/src/components/Insights/index.tsx index 3b15c1d4b..169ce9302 100644 --- a/src/components/Insights/index.tsx +++ b/src/components/Insights/index.tsx @@ -1,9 +1,11 @@ import { useContext, useEffect, useLayoutEffect, useState } from "react"; import { actions as globalActions } from "../../actions"; import { SLACK_WORKSPACE_URL } from "../../constants"; +import { getFeatureFlagValue } from "../../featureFlags"; import { usePrevious } from "../../hooks/usePrevious"; import { trackingEvents as globalTrackingEvents } from "../../trackingEvents"; import { isNumber } from "../../typeGuards/isNumber"; +import { FeatureFlag } from "../../types"; import { openURLInDefaultBrowser } from "../../utils/openURLInDefaultBrowser"; import { sendTrackingEvent } from "../../utils/sendTrackingEvent"; import { ConfigContext } from "../common/App/ConfigContext"; @@ -20,7 +22,6 @@ import { OpenTelemetryLogoCrossedSmallIcon } from "../common/icons/OpenTelemetry import { SlackLogoIcon } from "../common/icons/SlackLogoIcon"; import { InsightsCatalog } from "./InsightsCatalog"; import { SORTING_CRITERION } from "./InsightsCatalog/types"; -import { actions } from "./actions"; import { useInsightsData } from "./common/useInsightsData"; import * as s from "./styles"; import { BottleneckInsightTicket } from "./tickets/BottleneckInsightTicket"; @@ -63,16 +64,6 @@ const REFRESH_INTERVAL = isNumber(window.insightsRefreshInterval) ? window.insightsRefreshInterval : 10 * 1000; // in milliseconds -const DEFAULT_QUERY = { - page: 0, - sorting: { - criterion: SORTING_CRITERION.LATEST, - order: SORTING_ORDER.DESC - }, - searchQuery: null, - showDismissed: false -}; - const renderInsightTicket = ( data: InsightTicketInfo, onClose: () => void @@ -190,6 +181,16 @@ const sendMessage = (action: string, data?: object) => { }; export const Insights = (props: InsightsProps) => { + const DEFAULT_QUERY: InsightsQuery = { + page: 0, + sorting: { + criterion: SORTING_CRITERION.LATEST, + order: SORTING_ORDER.DESC + }, + searchQuery: null, + showDismissed: false, + insightViewType: props.insightViewType + }; // const [isAutofixing, setIsAutofixing] = useState(false); const [query, setQuery] = useState(DEFAULT_QUERY); const { isInitialLoading, data, refresh } = useInsightsData({ @@ -205,8 +206,12 @@ export const Insights = (props: InsightsProps) => { const [isRegistrationInProgress, setIsRegistrationInProgress] = useState(false); + const isDismissalEnabled = Boolean( + getFeatureFlagValue(config, FeatureFlag.IS_INSIGHT_DISMISSAL_ENABLED) && + props.insightViewType === "Issues" + ); + useLayoutEffect(() => { - sendMessage(actions.INITIALIZE); sendMessage(globalActions.GET_STATE); }, []); @@ -296,6 +301,7 @@ export const Insights = (props: InsightsProps) => { onRefresh={refresh} defaultQuery={DEFAULT_QUERY} dismissedCount={data.dismissedCount} + isDismissalEnabled={isDismissalEnabled} /> ); }; diff --git a/src/components/Insights/types.ts b/src/components/Insights/types.ts index 244ef84a2..f6454883b 100644 --- a/src/components/Insights/types.ts +++ b/src/components/Insights/types.ts @@ -84,8 +84,11 @@ export interface InsightsData { // needsObservabilityFix: boolean; //remove } +export type InsightViewType = "Issues" | "Analytics"; + export interface InsightsProps { data?: InsightsData; + insightViewType: InsightViewType; } export interface InsightGroup { @@ -868,6 +871,7 @@ export interface InsightsQuery { sorting: Sorting; searchQuery: string | null; showDismissed: boolean; + insightViewType: InsightViewType; } export interface ScopedInsightsQuery extends InsightsQuery { diff --git a/src/components/Main/Main.stories.tsx b/src/components/Main/Main.stories.tsx index 61d897795..618a82e22 100644 --- a/src/components/Main/Main.stories.tsx +++ b/src/components/Main/Main.stories.tsx @@ -1,6 +1,7 @@ import { Meta, StoryObj } from "@storybook/react"; import { Main } from "."; +import { mockedViewsData } from "../Navigation/mockData"; import { SetViewsPayload } from "../Navigation/types"; import { actions } from "./actions"; @@ -18,57 +19,6 @@ export default meta; type Story = StoryObj; -const data: SetViewsPayload = { - views: [ - { - isDisabled: false, - isSelected: true, - hasNewData: false, - isHidden: false, - title: "Insights", - id: "insights", - cardName: "insights" - }, - { - isDisabled: false, - isSelected: false, - hasNewData: false, - isHidden: false, - title: "Assets", - id: "assets", - cardName: "assets" - }, - { - isDisabled: false, - isSelected: false, - hasNewData: false, - isHidden: false, - title: "Errors", - id: "errors", - cardName: "errors" - }, - { - isDisabled: false, - isSelected: false, - hasNewData: false, - isHidden: true, - title: "Error Details", - id: "errorsDetails", - cardName: "errors" - }, - { - isDisabled: false, - isSelected: false, - hasNewData: false, - isHidden: false, - title: "Tests", - id: "tests", - cardName: "tests" - } - ], - isTriggeredByJcef: false -}; - const updateSelectedView = ( data: SetViewsPayload, viewId: string @@ -89,7 +39,7 @@ export const Insights: Story = { window.postMessage({ type: "digma", action: actions.SET_VIEWS, - payload: updateSelectedView(data, "insights") + payload: updateSelectedView(mockedViewsData, "insights") }); } }; @@ -99,7 +49,7 @@ export const Assets: Story = { window.postMessage({ type: "digma", action: actions.SET_VIEWS, - payload: updateSelectedView(data, "assets") + payload: updateSelectedView(mockedViewsData, "assets") }); } }; @@ -109,7 +59,7 @@ export const Tests: Story = { window.postMessage({ type: "digma", action: actions.SET_VIEWS, - payload: updateSelectedView(data, "tests") + payload: updateSelectedView(mockedViewsData, "tests") }); } }; diff --git a/src/components/Main/index.tsx b/src/components/Main/index.tsx index bf0410e13..78d57f0ec 100644 --- a/src/components/Main/index.tsx +++ b/src/components/Main/index.tsx @@ -33,9 +33,11 @@ export const Main = () => { switch (view) { case "insights": - return ; + return ; case "assets": return ; + case "analytics": + return ; case "tests": return ; } diff --git a/src/components/Main/typeGuards.ts b/src/components/Main/typeGuards.ts index 2503a9bf7..12edd4373 100644 --- a/src/components/Main/typeGuards.ts +++ b/src/components/Main/typeGuards.ts @@ -1,4 +1,4 @@ import { View } from "./types"; export const isView = (view: string): view is View => - ["insights", "assets", "tests"].includes(view); + ["insights", "assets", "analytics", "tests"].includes(view); diff --git a/src/components/Main/types.ts b/src/components/Main/types.ts index abb49604a..c707e3e27 100644 --- a/src/components/Main/types.ts +++ b/src/components/Main/types.ts @@ -1 +1 @@ -export type View = "insights" | "assets" | "tests"; +export type View = "insights" | "assets" | "analytics" | "tests"; diff --git a/src/components/Navigation/Navigation.stories.tsx b/src/components/Navigation/Navigation.stories.tsx index 3e8fddba1..4ffc6f90e 100644 --- a/src/components/Navigation/Navigation.stories.tsx +++ b/src/components/Navigation/Navigation.stories.tsx @@ -1,6 +1,8 @@ import { Meta, StoryObj } from "@storybook/react"; import { Navigation } from "."; +import { actions } from "./actions"; +import { mockedViewsData } from "./mockData"; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction const meta: Meta = { @@ -18,5 +20,11 @@ type Story = StoryObj; // More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args export const Default: Story = { - args: {} + play: () => { + window.postMessage({ + type: "digma", + action: actions.SET_VIEWS, + payload: mockedViewsData + }); + } }; diff --git a/src/components/Navigation/Tabs/index.tsx b/src/components/Navigation/Tabs/index.tsx index 5240a8efe..f0583c62e 100644 --- a/src/components/Navigation/Tabs/index.tsx +++ b/src/components/Navigation/Tabs/index.tsx @@ -19,7 +19,10 @@ const getTabTooltipMessage = (tab: TabData, scope?: Scope) => { // TODO: remove after implementing this logic on the plugin's side const getIsTabDisabled = (tab: TabData, scope?: Scope) => { - if (!scope?.span && ["errors", "errorsDetails", "tests"].includes(tab.id)) { + if ( + !scope?.span && + ["analytics", "errors", "errorsDetails", "tests"].includes(tab.id) + ) { return true; } diff --git a/src/components/Navigation/mockData.ts b/src/components/Navigation/mockData.ts new file mode 100644 index 000000000..fe3296691 --- /dev/null +++ b/src/components/Navigation/mockData.ts @@ -0,0 +1,61 @@ +import { SetViewsPayload } from "./types"; + +export const mockedViewsData: SetViewsPayload = { + views: [ + { + isDisabled: false, + isSelected: true, + hasNewData: false, + isHidden: false, + title: "Insights", + id: "insights", + cardName: "insights" + }, + { + isDisabled: false, + isSelected: false, + hasNewData: false, + isHidden: false, + title: "Assets", + id: "assets", + cardName: "assets" + }, + { + isDisabled: false, + isSelected: false, + hasNewData: false, + isHidden: false, + title: "Analytics", + id: "analytics", + cardName: "analytics" + }, + { + isDisabled: false, + isSelected: false, + hasNewData: false, + isHidden: false, + title: "Errors", + id: "errors", + cardName: "errors" + }, + { + isDisabled: false, + isSelected: false, + hasNewData: false, + isHidden: true, + title: "Error Details", + id: "errorsDetails", + cardName: "errors" + }, + { + isDisabled: false, + isSelected: false, + hasNewData: false, + isHidden: false, + title: "Tests", + id: "tests", + cardName: "tests" + } + ], + isTriggeredByJcef: false +}; diff --git a/src/components/RecentActivity/RecentActivityTable/getTagType.ts b/src/components/RecentActivity/RecentActivityTable/getTagType.ts index 5875f9017..21c87022a 100644 --- a/src/components/RecentActivity/RecentActivityTable/getTagType.ts +++ b/src/components/RecentActivity/RecentActivityTable/getTagType.ts @@ -1,6 +1,10 @@ import { TagType } from "../../common/Tag/types"; -export const getTagType = (criticality: number): TagType => { +export const getTagType = (criticality?: number): TagType => { + if (criticality === undefined) { + return "default"; + } + if (criticality < 0.2) { return "lowSeverity"; } diff --git a/src/components/RecentActivity/RecentActivityTable/index.tsx b/src/components/RecentActivity/RecentActivityTable/index.tsx index afd58b1fb..e190f8799 100644 --- a/src/components/RecentActivity/RecentActivityTable/index.tsx +++ b/src/components/RecentActivity/RecentActivityTable/index.tsx @@ -74,7 +74,7 @@ const renderDuration = (duration: Duration, viewMode: ViewMode) => const renderInsights = (insights: SlimInsight[]) => { const sortedInsights = [...insights].sort( (a, b) => - b.criticality - a.criticality || + (b.criticality || 0) - (a.criticality || 0) || getInsightTypeOrderPriority(a.type) - getInsightTypeOrderPriority(b.type) ); diff --git a/src/components/RecentActivity/types.ts b/src/components/RecentActivity/types.ts index 84962cdd3..818de4578 100644 --- a/src/components/RecentActivity/types.ts +++ b/src/components/RecentActivity/types.ts @@ -46,7 +46,7 @@ export interface SlimInsight { type: string; codeObjectIds: string[]; importance: number; - criticality: number; + criticality?: number; } export interface ActivityEntry { diff --git a/src/components/Tests/actions.ts b/src/components/Tests/actions.ts index 9c24358ff..a72068f86 100644 --- a/src/components/Tests/actions.ts +++ b/src/components/Tests/actions.ts @@ -3,7 +3,6 @@ import { addPrefix } from "../../utils/addPrefix"; const ACTION_PREFIX = "TESTS"; export const actions = addPrefix(ACTION_PREFIX, { - INITIALIZE: "INITIALIZE", GET_SPAN_LATEST_DATA: "SPAN_GET_LATEST_DATA", SET_SPAN_LATEST_DATA: "SPAN_SET_LATEST_DATA", RUN_TEST: "RUN_TEST", diff --git a/src/components/Tests/index.tsx b/src/components/Tests/index.tsx index 7b5105fbe..6376f03d4 100644 --- a/src/components/Tests/index.tsx +++ b/src/components/Tests/index.tsx @@ -103,10 +103,6 @@ export const Tests = (props: TestsProps) => { const previousEnvironmentsToSend = usePrevious(environmentsToSend); useEffect(() => { - window.sendMessageToDigma({ - action: actions.INITIALIZE - }); - sendTrackingEvent(trackingEvents.PAGE_LOADED); window.sendMessageToDigma({ diff --git a/src/containers/Insights/index.tsx b/src/containers/Insights/index.tsx index 7d1b20f07..37fdfc8b4 100644 --- a/src/containers/Insights/index.tsx +++ b/src/containers/Insights/index.tsx @@ -21,7 +21,7 @@ if (rootElement) { root.render( - + ); } diff --git a/webpackEntries.ts b/webpackEntries.ts index 355c22442..0c8776af6 100644 --- a/webpackEntries.ts +++ b/webpackEntries.ts @@ -29,7 +29,14 @@ export const entries: AppEntries = { environmentVariables: ["wizardFirstLaunch", "wizardSkipInstallationStep"] }, main: { - entry: path.resolve(__dirname, "./src/containers/Main/index.tsx") + entry: path.resolve(__dirname, "./src/containers/Main/index.tsx"), + environmentVariables: [ + "assetsRefreshInterval", + "assetsSearch", + "assetsSelectedServices", + "insightsRefreshInterval", + "testsRefreshInterval" + ] }, navigation: { entry: path.resolve(__dirname, "./src/containers/Navigation/index.tsx") From 28693bde8589400d3727eb417315c08afb86d7f4 Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Thu, 14 Mar 2024 10:22:49 +0100 Subject: [PATCH 3/5] Use UUID for messages --- .vscode/settings.json | 2 +- package-lock.json | 20 ++++++++++++++++---- package.json | 4 +++- src/api/index.ts | 11 ++++++----- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 0c01357f2..29a230b06 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,5 +5,5 @@ }, "editor.defaultFormatter": "esbenp.prettier-vscode", "stylelint.validate": ["typescript"], - "cSpell.words": ["Digma", "UNDISMISS"] + "cSpell.words": ["Digma", "UNDISMISS", "uuidv"] } diff --git a/package-lock.json b/package-lock.json index 1d21909d9..776f04ff8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,8 @@ "react-transition-group": "^4.4.5", "recharts": "^2.6.2", "semver": "^7.5.4", - "styled-components": "^6.1.0" + "styled-components": "^6.1.0", + "uuid": "^9.0.1" }, "devDependencies": { "@babel/core": "^7.23.2", @@ -48,6 +49,7 @@ "@types/react-syntax-highlighter": "^15.5.7", "@types/react-transition-group": "^4.4.5", "@types/semver": "^7.5.6", + "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^5.49.0", "@typescript-eslint/parser": "^5.49.0", "babel-loader": "^9.1.3", @@ -6644,6 +6646,12 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.7.tgz", "integrity": "sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g==" }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true + }, "node_modules/@types/yargs": { "version": "16.0.5", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", @@ -18611,7 +18619,6 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "dev": true, "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -23675,6 +23682,12 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.7.tgz", "integrity": "sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g==" }, + "@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true + }, "@types/yargs": { "version": "16.0.5", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", @@ -32395,8 +32408,7 @@ "uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "dev": true + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" }, "v8-compile-cache-lib": { "version": "3.0.1", diff --git a/package.json b/package.json index 2c41f8871..e8ab51a9d 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "@types/react-syntax-highlighter": "^15.5.7", "@types/react-transition-group": "^4.4.5", "@types/semver": "^7.5.6", + "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^5.49.0", "@typescript-eslint/parser": "^5.49.0", "babel-loader": "^9.1.3", @@ -122,6 +123,7 @@ "react-transition-group": "^4.4.5", "recharts": "^2.6.2", "semver": "^7.5.4", - "styled-components": "^6.1.0" + "styled-components": "^6.1.0", + "uuid": "^9.0.1" } } diff --git a/src/api/index.ts b/src/api/index.ts index 1765b23b3..fc19fbd55 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -1,3 +1,4 @@ +import { v4 as uuidv4 } from "uuid"; import { platform } from "../platform"; import { isObject } from "../typeGuards/isObject"; import { ActionDispatcher } from "./ActionDispatcher"; @@ -21,9 +22,9 @@ export const initializeDigmaMessageListener = ( export const sendMessage = ( message: DigmaOutgoingMessageData ): string | undefined => { - const extendedMessage = { ...message, id: `${message.action}-${Date.now()}` }; + const extendedMessage = { ...message, id: uuidv4() }; - console.debug("Message to send:", message); + console.debug("Message to send:", extendedMessage); switch (platform) { case "Web": @@ -31,14 +32,14 @@ export const sendMessage = ( break; case "VS Code": if (window.sendMessageToVSCode) { - window.sendMessageToVSCode(message); - console.debug("Message has been sent to VS Code: ", message); + window.sendMessageToVSCode(extendedMessage); + console.debug("Message has been sent to VS Code: ", extendedMessage); } break; case "JetBrains": if (window.cefQuery) { return window.cefQuery({ - request: JSON.stringify(message), + request: JSON.stringify(extendedMessage), onSuccess: function (response) { console.debug("cefQuery has been successfully sent: %s", response); }, From 3f14e227e18f299d3bf60599481a531788a56261 Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Thu, 14 Mar 2024 12:32:29 +0100 Subject: [PATCH 4/5] Remove UUID, add feature flag --- .vscode/settings.json | 2 +- package-lock.json | 20 ++----- package.json | 4 +- src/api/index.ts | 13 ++-- src/api/types.ts | 6 -- src/api/web/sendMessageToWebService.ts | 4 +- src/components/Assets/index.tsx | 6 -- .../Insights/InsightJiraTicket/index.tsx | 1 - src/components/Navigation/Tabs/index.tsx | 59 +++++++++++-------- src/featureFlags.ts | 3 +- src/types.ts | 3 +- 11 files changed, 51 insertions(+), 70 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 29a230b06..0c01357f2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,5 +5,5 @@ }, "editor.defaultFormatter": "esbenp.prettier-vscode", "stylelint.validate": ["typescript"], - "cSpell.words": ["Digma", "UNDISMISS", "uuidv"] + "cSpell.words": ["Digma", "UNDISMISS"] } diff --git a/package-lock.json b/package-lock.json index 776f04ff8..1d21909d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,8 +26,7 @@ "react-transition-group": "^4.4.5", "recharts": "^2.6.2", "semver": "^7.5.4", - "styled-components": "^6.1.0", - "uuid": "^9.0.1" + "styled-components": "^6.1.0" }, "devDependencies": { "@babel/core": "^7.23.2", @@ -49,7 +48,6 @@ "@types/react-syntax-highlighter": "^15.5.7", "@types/react-transition-group": "^4.4.5", "@types/semver": "^7.5.6", - "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^5.49.0", "@typescript-eslint/parser": "^5.49.0", "babel-loader": "^9.1.3", @@ -6646,12 +6644,6 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.7.tgz", "integrity": "sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g==" }, - "node_modules/@types/uuid": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", - "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", - "dev": true - }, "node_modules/@types/yargs": { "version": "16.0.5", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", @@ -18619,6 +18611,7 @@ "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -23682,12 +23675,6 @@ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.7.tgz", "integrity": "sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g==" }, - "@types/uuid": { - "version": "9.0.8", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", - "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", - "dev": true - }, "@types/yargs": { "version": "16.0.5", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", @@ -32408,7 +32395,8 @@ "uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==" + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true }, "v8-compile-cache-lib": { "version": "3.0.1", diff --git a/package.json b/package.json index e8ab51a9d..2c41f8871 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,6 @@ "@types/react-syntax-highlighter": "^15.5.7", "@types/react-transition-group": "^4.4.5", "@types/semver": "^7.5.6", - "@types/uuid": "^9.0.8", "@typescript-eslint/eslint-plugin": "^5.49.0", "@typescript-eslint/parser": "^5.49.0", "babel-loader": "^9.1.3", @@ -123,7 +122,6 @@ "react-transition-group": "^4.4.5", "recharts": "^2.6.2", "semver": "^7.5.4", - "styled-components": "^6.1.0", - "uuid": "^9.0.1" + "styled-components": "^6.1.0" } } diff --git a/src/api/index.ts b/src/api/index.ts index fc19fbd55..335183426 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -1,4 +1,3 @@ -import { v4 as uuidv4 } from "uuid"; import { platform } from "../platform"; import { isObject } from "../typeGuards/isObject"; import { ActionDispatcher } from "./ActionDispatcher"; @@ -22,24 +21,22 @@ export const initializeDigmaMessageListener = ( export const sendMessage = ( message: DigmaOutgoingMessageData ): string | undefined => { - const extendedMessage = { ...message, id: uuidv4() }; - - console.debug("Message to send:", extendedMessage); + console.debug("Message to send:", message); switch (platform) { case "Web": - sendMessageToWebService(extendedMessage); + sendMessageToWebService(message); break; case "VS Code": if (window.sendMessageToVSCode) { - window.sendMessageToVSCode(extendedMessage); - console.debug("Message has been sent to VS Code: ", extendedMessage); + window.sendMessageToVSCode(message); + console.debug("Message has been sent to VS Code: ", message); } break; case "JetBrains": if (window.cefQuery) { return window.cefQuery({ - request: JSON.stringify(extendedMessage), + request: JSON.stringify(message), onSuccess: function (response) { console.debug("cefQuery has been successfully sent: %s", response); }, diff --git a/src/api/types.ts b/src/api/types.ts index 78bacfb85..b6496e958 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -2,7 +2,6 @@ export type ActionListener = (data: unknown, timeStamp: number) => void; export interface DigmaIncomingMessageData { type: "digma"; - id?: string; action: string; payload?: unknown; } @@ -12,9 +11,4 @@ export interface DigmaOutgoingMessageData { payload?: T; } -export interface ExtendedDigmaOutgoingMessageData - extends DigmaOutgoingMessageData { - id: string; -} - export type DigmaMessageEvent = MessageEvent; diff --git a/src/api/web/sendMessageToWebService.ts b/src/api/web/sendMessageToWebService.ts index 3f153ca14..4042feec8 100644 --- a/src/api/web/sendMessageToWebService.ts +++ b/src/api/web/sendMessageToWebService.ts @@ -1,12 +1,12 @@ import { actions as globalActions } from "../../actions"; import { actions as dashboardActions } from "../../components/Dashboard/actions"; -import { ExtendedDigmaOutgoingMessageData } from "../types"; +import { DigmaOutgoingMessageData } from "../types"; import { getAboutInfo } from "./services/about"; import { GetDashboardParams, getDashboard } from "./services/dashboard"; import { GetEnvironmentParams, getEnvironment } from "./services/environments"; export const sendMessageToWebService = ( - message: ExtendedDigmaOutgoingMessageData + message: DigmaOutgoingMessageData ) => { switch (message.action) { case dashboardActions.GET_DATA: diff --git a/src/components/Assets/index.tsx b/src/components/Assets/index.tsx index 6a80c10c6..15d0ea0b6 100644 --- a/src/components/Assets/index.tsx +++ b/src/components/Assets/index.tsx @@ -67,12 +67,6 @@ export const Assets = () => { ); }, [config]); - // useLayoutEffect(() => { - // window.sendMessageToDigma({ - // action: actions.INITIALIZE - // }); - // }, []); - useEffect(() => { if (!config.scope?.span) { setAssetScopeOption(null); diff --git a/src/components/Insights/InsightJiraTicket/index.tsx b/src/components/Insights/InsightJiraTicket/index.tsx index 3bf8a9753..b4f8fdd64 100644 --- a/src/components/Insights/InsightJiraTicket/index.tsx +++ b/src/components/Insights/InsightJiraTicket/index.tsx @@ -11,7 +11,6 @@ import { InsightsGetDataListQuery, LinkTicketResponse } from "./types"; -import { Attachment } from "../../common/JiraTicket/types"; export const InsightJiraTicket = (props: InsightJiraTicketProps) => { const [errorMessage, setErrorMessage] = useState(); diff --git a/src/components/Navigation/Tabs/index.tsx b/src/components/Navigation/Tabs/index.tsx index f0583c62e..b65445d60 100644 --- a/src/components/Navigation/Tabs/index.tsx +++ b/src/components/Navigation/Tabs/index.tsx @@ -1,4 +1,6 @@ import { useContext } from "react"; +import { getFeatureFlagValue } from "../../../featureFlags"; +import { FeatureFlag } from "../../../types"; import { sendTrackingEvent } from "../../../utils/sendTrackingEvent"; import { ConfigContext } from "../../common/App/ConfigContext"; import { Scope } from "../../common/App/types"; @@ -41,35 +43,42 @@ export const Tabs = (props: TabsProps) => { } }; + const tabs = props.tabs.filter( + (x) => + !x.isHidden && + !( + x.id === "analytics" && + !getFeatureFlagValue(config, FeatureFlag.IS_ANALYTICS_TAB_VISIBLE) + ) + ); + return ( - {props.tabs - .filter((x) => !x.isHidden) - .map((tab) => { - const tooltipMessage = getTabTooltipMessage(tab, config.scope); - const isDisabled = getIsTabDisabled(tab, config.scope); + {tabs.map((tab) => { + const tooltipMessage = getTabTooltipMessage(tab, config.scope); + const isDisabled = getIsTabDisabled(tab, config.scope); - return ( - + handleTabClick(tab)} > - handleTabClick(tab)} - > - {tab.title} - {tab.hasNewData && } - {config.scope?.hasErrors && - ["errorsDetails", "errors"].includes(tab.id) && ( - - )} - - - ); - })} + {tab.title} + {tab.hasNewData && } + {config.scope?.hasErrors && + ["errorsDetails", "errors"].includes(tab.id) && ( + + )} + + + ); + })} ); }; diff --git a/src/featureFlags.ts b/src/featureFlags.ts index da3553bea..1ccd8ec1e 100644 --- a/src/featureFlags.ts +++ b/src/featureFlags.ts @@ -9,7 +9,8 @@ export const featureFlagMinBackendVersions: Record = { [FeatureFlag.IS_ASSETS_OVERALL_IMPACT_HIDDEN]: "v0.2.181-alpha.1", [FeatureFlag.IS_INSIGHT_TICKET_LINKAGE_ENABLED]: "v0.2.200", [FeatureFlag.IS_ASSETS_COMPLEX_FILTER_ENABLED]: "v0.2.215", - [FeatureFlag.IS_INSIGHT_DISMISSAL_ENABLED]: "v0.2.238" + [FeatureFlag.IS_INSIGHT_DISMISSAL_ENABLED]: "v0.2.238", + [FeatureFlag.IS_ANALYTICS_TAB_VISIBLE]: "v0.2.243" }; export const getFeatureFlagValue = ( diff --git a/src/types.ts b/src/types.ts index abb7885ca..df28756f6 100644 --- a/src/types.ts +++ b/src/types.ts @@ -6,7 +6,8 @@ export enum FeatureFlag { IS_ASSETS_OVERALL_IMPACT_HIDDEN, IS_INSIGHT_TICKET_LINKAGE_ENABLED, IS_ASSETS_COMPLEX_FILTER_ENABLED, - IS_INSIGHT_DISMISSAL_ENABLED + IS_INSIGHT_DISMISSAL_ENABLED, + IS_ANALYTICS_TAB_VISIBLE } export enum InsightType { From 34652f64cf48d7b6182183381ff0c7014c28e686 Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Thu, 14 Mar 2024 15:06:32 +0100 Subject: [PATCH 5/5] Bump BE version for feature flag, fix component remount --- .../Insights/common/useInsightsData.ts | 28 +++++++++++-------- .../EndpointNPlusOneInsightTicket/index.tsx | 3 +- .../EndpointQueryOptimizationTicket/index.tsx | 3 +- .../tickets/NPlusOneInsightTicket/index.tsx | 3 +- .../QueryOptimizationInsightTicket/index.tsx | 3 +- .../ScalingIssueInsightTicket/index.tsx | 23 +++++++-------- .../index.tsx | 25 +++++++++-------- src/components/Main/index.tsx | 4 +-- src/components/Navigation/Tabs/index.tsx | 7 ++--- src/components/Tests/TestTicket/index.tsx | 4 +-- src/components/common/App/types.ts | 5 ++++ src/featureFlags.ts | 2 +- 12 files changed, 62 insertions(+), 48 deletions(-) diff --git a/src/components/Insights/common/useInsightsData.ts b/src/components/Insights/common/useInsightsData.ts index 8e1e68d29..b1e43b123 100644 --- a/src/components/Insights/common/useInsightsData.ts +++ b/src/components/Insights/common/useInsightsData.ts @@ -4,7 +4,6 @@ import { dispatcher } from "../../../dispatcher"; import { usePrevious } from "../../../hooks/usePrevious"; import { ConfigContext } from "../../common/App/ConfigContext"; import { - ConfigContextData, GlobalState, InsightsQuery as InsightsDataQuery } from "../../common/App/types"; @@ -22,14 +21,15 @@ interface UseInsightDataProps { query: InsightsQuery; } -const getData = (query: ScopedInsightsQuery, context: ConfigContextData) => { +const getData = (query: ScopedInsightsQuery, state?: GlobalState) => { const getDataQuery: InsightsDataQuery = { displayName: query.searchQuery, sortBy: query.sorting.criterion, sortOrder: query.sorting.order, page: query.page, scopedSpanCodeObjectId: query.scopedSpanCodeObjectId, - showDismissed: query.showDismissed + showDismissed: query.showDismissed, + insightViewType: query.insightViewType }; window.sendMessageToDigma({ @@ -39,12 +39,15 @@ const getData = (query: ScopedInsightsQuery, context: ConfigContextData) => { } }); + const globalStateSlice = + query.insightViewType === "Analytics" ? "analytics" : "insights"; + window.sendMessageToDigma({ action: globalActions.UPDATE_STATE, payload: { - ...context.state, - insights: { - ...context.state?.insights, + ...state, + [globalStateSlice]: { + ...state?.[globalStateSlice], query: getDataQuery } } @@ -64,8 +67,9 @@ export const useInsightsData = (props: UseInsightDataProps) => { const [isLoading, setIsLoading] = useState(false); const previousLastSetDataTimeStamp = usePrevious(lastSetDataTimeStamp); const refreshTimerId = useRef(); - const ctx = useContext(ConfigContext); - const { scope, environment } = ctx; + const config = useContext(ConfigContext); + const { scope, environment, state } = config; + const query = useMemo( () => ({ ...props.query, @@ -75,7 +79,7 @@ export const useInsightsData = (props: UseInsightDataProps) => { ); useEffect(() => { - getData(query, ctx); + getData(query, state); setIsInitialLoading(true); setIsLoading(true); @@ -110,7 +114,7 @@ export const useInsightsData = (props: UseInsightDataProps) => { window.clearTimeout(refreshTimerId.current); refreshTimerId.current = window.setTimeout( (insightsQuery: ScopedInsightsQuery) => { - getData(insightsQuery, ctx); + getData(insightsQuery, state); }, props.refreshInterval, query @@ -135,7 +139,7 @@ export const useInsightsData = (props: UseInsightDataProps) => { ...props.query, scopedSpanCodeObjectId: scope?.span?.spanCodeObjectId || null }, - ctx + state ); }, [props.query, scope, environment]); @@ -143,6 +147,6 @@ export const useInsightsData = (props: UseInsightDataProps) => { isInitialLoading, data, isLoading, - refresh: () => getData(query, ctx) + refresh: () => getData(query, state) }; }; diff --git a/src/components/Insights/tickets/EndpointNPlusOneInsightTicket/index.tsx b/src/components/Insights/tickets/EndpointNPlusOneInsightTicket/index.tsx index 423963ebe..6021a6d24 100644 --- a/src/components/Insights/tickets/EndpointNPlusOneInsightTicket/index.tsx +++ b/src/components/Insights/tickets/EndpointNPlusOneInsightTicket/index.tsx @@ -3,6 +3,7 @@ import { InsightType } from "../../../../types"; import { getCriticalityLabel } from "../../../../utils/getCriticalityLabel"; import { intersperse } from "../../../../utils/intersperse"; import { ConfigContext } from "../../../common/App/ConfigContext"; +import { Attachment } from "../../../common/JiraTicket/types"; import { InsightJiraTicket } from "../../InsightJiraTicket"; import { EndpointSpanNPlusOneInsight, SpanNPlusOneInsight } from "../../types"; import { useEndpointDataSource } from "../common"; @@ -73,7 +74,7 @@ export const EndpointNPlusOneInsightTicket = ( ); const traceId = span?.traceId; - const attachments = [ + const attachments: Attachment[] = [ ...(traceId ? [ { diff --git a/src/components/Insights/tickets/EndpointQueryOptimizationTicket/index.tsx b/src/components/Insights/tickets/EndpointQueryOptimizationTicket/index.tsx index d8d5ced45..c31a23910 100644 --- a/src/components/Insights/tickets/EndpointQueryOptimizationTicket/index.tsx +++ b/src/components/Insights/tickets/EndpointQueryOptimizationTicket/index.tsx @@ -4,6 +4,7 @@ import { getCriticalityLabel } from "../../../../utils/getCriticalityLabel"; import { getDurationString } from "../../../../utils/getDurationString"; import { intersperse } from "../../../../utils/intersperse"; import { ConfigContext } from "../../../common/App/ConfigContext"; +import { Attachment } from "../../../common/JiraTicket/types"; import { InsightJiraTicket } from "../../InsightJiraTicket"; import { EndpointQueryOptimizationInsight, @@ -101,7 +102,7 @@ export const EndpointQueryOptimizationInsightTicket = ( ); const traceId = span?.traceId; - const attachments = [ + const attachments: Attachment[] = [ ...(traceId ? [ { diff --git a/src/components/Insights/tickets/NPlusOneInsightTicket/index.tsx b/src/components/Insights/tickets/NPlusOneInsightTicket/index.tsx index 92ec56748..384db87ef 100644 --- a/src/components/Insights/tickets/NPlusOneInsightTicket/index.tsx +++ b/src/components/Insights/tickets/NPlusOneInsightTicket/index.tsx @@ -2,6 +2,7 @@ import { ReactElement, useContext } from "react"; import { getCriticalityLabel } from "../../../../utils/getCriticalityLabel"; import { intersperse } from "../../../../utils/intersperse"; import { ConfigContext } from "../../../common/App/ConfigContext"; +import { Attachment } from "../../../common/JiraTicket/types"; import { InsightJiraTicket } from "../../InsightJiraTicket"; import { SpanNPlusOneInsight } from "../../types"; import { useSpanDataSource } from "../common"; @@ -66,7 +67,7 @@ export const NPlusOneInsightTicket = ( ); const traceId = props.data.insight.traceId; - const attachments = [ + const attachments: Attachment[] = [ ...(traceId ? [ { diff --git a/src/components/Insights/tickets/QueryOptimizationInsightTicket/index.tsx b/src/components/Insights/tickets/QueryOptimizationInsightTicket/index.tsx index 29d6bf373..e191f2821 100644 --- a/src/components/Insights/tickets/QueryOptimizationInsightTicket/index.tsx +++ b/src/components/Insights/tickets/QueryOptimizationInsightTicket/index.tsx @@ -3,6 +3,7 @@ import { getCriticalityLabel } from "../../../../utils/getCriticalityLabel"; import { getDurationString } from "../../../../utils/getDurationString"; import { intersperse } from "../../../../utils/intersperse"; import { ConfigContext } from "../../../common/App/ConfigContext"; +import { Attachment } from "../../../common/JiraTicket/types"; import { InsightJiraTicket } from "../../InsightJiraTicket"; import { QueryOptimizationInsight } from "../../types"; import { useCommitInfos } from "../common"; @@ -80,7 +81,7 @@ export const QueryOptimizationInsightTicket = ( ); const traceId = props.data.insight.traceId; - const attachments = [ + const attachments: Attachment[] = [ ...(traceId ? [ { diff --git a/src/components/Insights/tickets/ScalingIssueInsightTicket/index.tsx b/src/components/Insights/tickets/ScalingIssueInsightTicket/index.tsx index 08c394cad..e51ad9874 100644 --- a/src/components/Insights/tickets/ScalingIssueInsightTicket/index.tsx +++ b/src/components/Insights/tickets/ScalingIssueInsightTicket/index.tsx @@ -1,23 +1,24 @@ -import { SpanScalingBadlyInsight } from "../../types"; -import { InsightTicketProps } from "../types"; -import { InsightJiraTicket } from "../../InsightJiraTicket"; -import { intersperse } from "../../../../utils/intersperse"; import { ReactElement, useContext } from "react"; +import { intersperse } from "../../../../utils/intersperse"; +import { ConfigContext } from "../../../common/App/ConfigContext"; +import { Attachment } from "../../../common/JiraTicket/types"; +import { InsightJiraTicket } from "../../InsightJiraTicket"; +import { SpanScalingBadlyInsight } from "../../types"; +import { useSpanDataSource } from "../common"; import { CodeLocations } from "../common/CodeLocations"; import { CommitInfos } from "../common/CommitInfos"; import { DigmaSignature } from "../common/DigmaSignature"; -import { useSpanDataSource } from "../common"; -import { ConfigContext } from "../../../common/App/ConfigContext"; import { - getHistogramAttachment, - getScalingIssueSummary, - getTraceAttachment, ScalingIssueAffectedEndpoints, ScalingIssueDuration, ScalingIssueMessage, ScalingIssueRootCauses, - ScalingIssueTestedConcurrency + ScalingIssueTestedConcurrency, + getHistogramAttachment, + getScalingIssueSummary, + getTraceAttachment } from "../common/ScalingIssueCommon"; +import { InsightTicketProps } from "../types"; export const ScalingIssueInsightTicket = ( props: InsightTicketProps @@ -80,7 +81,7 @@ export const ScalingIssueInsightTicket = ( ?.find((t) => t); const attachmentTrace = getTraceAttachment(config, traceId); const attachmentHistogram = getHistogramAttachment(config, insight); - const attachments = [ + const attachments: Attachment[] = [ ...(attachmentTrace ? [attachmentTrace] : []), ...(attachmentHistogram ? [attachmentHistogram] : []) ]; diff --git a/src/components/Insights/tickets/ScalingIssueInsightTicketByRootCause/index.tsx b/src/components/Insights/tickets/ScalingIssueInsightTicketByRootCause/index.tsx index 88c01d094..daad93759 100644 --- a/src/components/Insights/tickets/ScalingIssueInsightTicketByRootCause/index.tsx +++ b/src/components/Insights/tickets/ScalingIssueInsightTicketByRootCause/index.tsx @@ -1,24 +1,25 @@ -import { RootCauseSpanInfo, SpanScalingBadlyInsight } from "../../types"; -import { InsightTicketProps } from "../types"; -import { InsightJiraTicket } from "../../InsightJiraTicket"; -import { intersperse } from "../../../../utils/intersperse"; import { ReactElement, useContext } from "react"; +import { InsightType } from "../../../../types"; +import { intersperse } from "../../../../utils/intersperse"; +import { ConfigContext } from "../../../common/App/ConfigContext"; +import { Attachment } from "../../../common/JiraTicket/types"; +import { InsightJiraTicket } from "../../InsightJiraTicket"; +import { RootCauseSpanInfo, SpanScalingBadlyInsight } from "../../types"; +import { useEndpointDataSource } from "../common"; import { CodeLocations } from "../common/CodeLocations"; import { CommitInfos } from "../common/CommitInfos"; import { DigmaSignature } from "../common/DigmaSignature"; -import { useEndpointDataSource } from "../common"; -import { ConfigContext } from "../../../common/App/ConfigContext"; import { - getHistogramAttachment, - getScalingIssueSummary, - getTraceAttachment, ScalingIssueAffectedEndpoints, ScalingIssueDuration, ScalingIssueMessage, ScalingIssueRootCauses, - ScalingIssueTestedConcurrency + ScalingIssueTestedConcurrency, + getHistogramAttachment, + getScalingIssueSummary, + getTraceAttachment } from "../common/ScalingIssueCommon"; -import { InsightType } from "../../../../types"; +import { InsightTicketProps } from "../types"; export const ScalingIssueInsightTicketByRootCause = ( props: InsightTicketProps & { @@ -85,7 +86,7 @@ export const ScalingIssueInsightTicketByRootCause = ( const attachmentTrace = getTraceAttachment(config, spanInfo?.sampleTraceId); const attachmentHistogram = getHistogramAttachment(config, spanInsight); - const attachments = [ + const attachments: Attachment[] = [ ...(attachmentTrace ? [attachmentTrace] : []), ...(attachmentHistogram ? [attachmentHistogram] : []) ]; diff --git a/src/components/Main/index.tsx b/src/components/Main/index.tsx index 78d57f0ec..0f06fc520 100644 --- a/src/components/Main/index.tsx +++ b/src/components/Main/index.tsx @@ -33,11 +33,11 @@ export const Main = () => { switch (view) { case "insights": - return ; + return ; case "assets": return ; case "analytics": - return ; + return ; case "tests": return ; } diff --git a/src/components/Navigation/Tabs/index.tsx b/src/components/Navigation/Tabs/index.tsx index b65445d60..cca5029e0 100644 --- a/src/components/Navigation/Tabs/index.tsx +++ b/src/components/Navigation/Tabs/index.tsx @@ -45,11 +45,10 @@ export const Tabs = (props: TabsProps) => { const tabs = props.tabs.filter( (x) => - !x.isHidden && - !( + !x.isHidden || + (!x.isHidden && x.id === "analytics" && - !getFeatureFlagValue(config, FeatureFlag.IS_ANALYTICS_TAB_VISIBLE) - ) + getFeatureFlagValue(config, FeatureFlag.IS_ANALYTICS_TAB_VISIBLE)) ); return ( diff --git a/src/components/Tests/TestTicket/index.tsx b/src/components/Tests/TestTicket/index.tsx index e49c9c3cd..a8c853e5b 100644 --- a/src/components/Tests/TestTicket/index.tsx +++ b/src/components/Tests/TestTicket/index.tsx @@ -5,8 +5,8 @@ import { intersperse } from "../../../utils/intersperse"; import { DigmaSignature } from "../../Insights/tickets/common/DigmaSignature"; import { ConfigContext } from "../../common/App/ConfigContext"; import { JiraTicket } from "../../common/JiraTicket"; -import { TestTicketProps } from "./types"; import { Attachment } from "../../common/JiraTicket/types"; +import { TestTicketProps } from "./types"; export const TestTicket = (props: TestTicketProps) => { const { @@ -52,7 +52,7 @@ export const TestTicket = (props: TestTicketProps) => { ); - const attachments = [ + const attachments: Attachment[] = [ ...(traceId ? [ { diff --git a/src/components/common/App/types.ts b/src/components/common/App/types.ts index 631c230bd..8b5016932 100644 --- a/src/components/common/App/types.ts +++ b/src/components/common/App/types.ts @@ -1,4 +1,5 @@ import { Mode } from "../../../globals"; +import { InsightViewType } from "../../Insights/types"; export interface AppProps { children: React.ReactNode; @@ -64,12 +65,16 @@ export interface InsightsQuery { page: number; scopedSpanCodeObjectId?: string | null; showDismissed: boolean; + insightViewType: InsightViewType; } export interface GlobalState { insights?: { query?: InsightsQuery; }; + analytics?: { + query?: InsightsQuery; + }; } export interface ConfigContextData { diff --git a/src/featureFlags.ts b/src/featureFlags.ts index 1ccd8ec1e..e5a9257a4 100644 --- a/src/featureFlags.ts +++ b/src/featureFlags.ts @@ -10,7 +10,7 @@ export const featureFlagMinBackendVersions: Record = { [FeatureFlag.IS_INSIGHT_TICKET_LINKAGE_ENABLED]: "v0.2.200", [FeatureFlag.IS_ASSETS_COMPLEX_FILTER_ENABLED]: "v0.2.215", [FeatureFlag.IS_INSIGHT_DISMISSAL_ENABLED]: "v0.2.238", - [FeatureFlag.IS_ANALYTICS_TAB_VISIBLE]: "v0.2.243" + [FeatureFlag.IS_ANALYTICS_TAB_VISIBLE]: "v0.2.244" }; export const getFeatureFlagValue = (