From 444d241e3d6647a024dcc61c8b321efed5d25a63 Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Fri, 26 Apr 2024 18:35:45 +0200 Subject: [PATCH 01/15] Refactor empty state card for Highlights --- .../EmptyStateCard/EmptyStateCard.stories.tsx | 7 +- .../Highlights/EmptyStateCard/index.tsx | 69 ++++----------- .../Highlights/EmptyStateCard/styles.ts | 32 ++++--- .../Highlights/EmptyStateCard/types.ts | 12 ++- src/components/Highlights/Impact/index.tsx | 83 +++++++++++-------- .../Highlights/Performance/index.tsx | 42 ++++++---- .../highlightCards/addEnvironmentColumns.tsx | 4 +- src/components/Highlights/TopIssues/index.tsx | 44 ++++++---- .../common/icons/16px/InfinityIcon.tsx | 4 +- 9 files changed, 162 insertions(+), 135 deletions(-) diff --git a/src/components/Highlights/EmptyStateCard/EmptyStateCard.stories.tsx b/src/components/Highlights/EmptyStateCard/EmptyStateCard.stories.tsx index f75755d15..4b5ae8a2e 100644 --- a/src/components/Highlights/EmptyStateCard/EmptyStateCard.stories.tsx +++ b/src/components/Highlights/EmptyStateCard/EmptyStateCard.stories.tsx @@ -1,6 +1,8 @@ import { Meta, StoryObj } from "@storybook/react"; import { EmptyStateCard } from "."; +import { CrossCircleIcon } from "../../common/icons/16px/CrossCircleIcon"; +import { RefreshIcon } from "../../common/icons/16px/RefreshIcon"; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction const meta: Meta = { @@ -20,14 +22,15 @@ type Story = StoryObj; export const WaitingForData: Story = { args: { - type: "loading", + type: "lowSeverity", + icon: RefreshIcon, text: "Detected issues will appear here" } }; export const NoData: Story = { args: { - type: "noData", + icon: CrossCircleIcon, text: "No Issues available at the moment" } }; diff --git a/src/components/Highlights/EmptyStateCard/index.tsx b/src/components/Highlights/EmptyStateCard/index.tsx index 1f39522a6..7a4071f47 100644 --- a/src/components/Highlights/EmptyStateCard/index.tsx +++ b/src/components/Highlights/EmptyStateCard/index.tsx @@ -1,62 +1,25 @@ -import { CrossCircleIcon } from "../../common/icons/16px/CrossCircleIcon"; -import { RefreshIcon } from "../../common/icons/16px/RefreshIcon"; -import { InfinityIcon } from "../../common/icons/InfinityIcon"; import * as s from "./styles"; import { EmptyStateCardProps } from "./types"; export const EmptyStateCard = ({ type, + icon: Icon, title, text, customContent -}: EmptyStateCardProps) => { - const renderContent = () => { - switch (type) { - case "loading": - return ( - <> - - - - - {title || "Waiting for Data"} - {text} - - {customContent} - - ); - case "noData": - return ( - <> - - - - - {title || "No data"} - {text} - - {customContent} - - ); - case "unlock": - return ( - <> - - - - - {title} - {text} - - {customContent} - - ); +}: EmptyStateCardProps) => ( + + + {Icon && } + + + {title && {title}} + {text && {text}} + + {customContent} + } - }; - - return ( - {renderContent()}} - /> - ); -}; + /> +); diff --git a/src/components/Highlights/EmptyStateCard/styles.ts b/src/components/Highlights/EmptyStateCard/styles.ts index b7d8ebfff..f844f831a 100644 --- a/src/components/Highlights/EmptyStateCard/styles.ts +++ b/src/components/Highlights/EmptyStateCard/styles.ts @@ -4,6 +4,7 @@ import { subscriptRegularTypography } from "../../common/App/typographies"; import { Card as CommonCard } from "../../common/v3/Card"; +import { IconContainerProps } from "./types"; export const Card = styled(CommonCard)` box-sizing: border-box; @@ -20,7 +21,7 @@ export const ContentContainer = styled.div` height: 100%; `; -export const IconContainer = styled.div` +export const IconContainer = styled.div` display: flex; align-items: center; justify-content: center; @@ -28,16 +29,27 @@ export const IconContainer = styled.div` height: 28px; border-radius: 4px; border: 1px solid ${({ theme }) => theme.colors.v3.stroke.primaryLight}; -`; - -export const InactiveIconContainer = styled(IconContainer)` - background: ${({ theme }) => theme.colors.v3.surface.primaryLight}; - color: ${({ theme }) => theme.colors.v3.text.tertiary}; -`; -export const LoadingDataIconContainer = styled(IconContainer)` - background: ${({ theme }) => theme.colors.v3.status.backgroundLow}; - color: ${({ theme }) => theme.colors.v3.status.low}; + ${({ $type, theme }) => { + switch ($type) { + case "success": + return ` + background: ${theme.colors.v3.status.backgroundSuccess}; + color: ${theme.colors.v3.status.success}; + `; + case "lowSeverity": + return ` + background: ${theme.colors.v3.status.backgroundLow}; + color: ${theme.colors.v3.status.low}; + `; + case "default": + default: + return ` + background: ${theme.colors.v3.surface.primaryLight}; + color: ${theme.colors.v3.text.tertiary}; + `; + } + }} `; export const TextContainer = styled.div` diff --git a/src/components/Highlights/EmptyStateCard/types.ts b/src/components/Highlights/EmptyStateCard/types.ts index 4bd948850..7e790da60 100644 --- a/src/components/Highlights/EmptyStateCard/types.ts +++ b/src/components/Highlights/EmptyStateCard/types.ts @@ -1,6 +1,16 @@ +import { ComponentType } from "react"; +import { IconProps } from "../../common/icons/types"; + +type EmptyStateType = "default" | "success" | "lowSeverity"; + export interface EmptyStateCardProps { - type: "loading" | "noData" | "unlock"; + type?: EmptyStateType; + icon: ComponentType; title?: string; text: string; customContent?: React.ReactNode; } + +export interface IconContainerProps { + $type?: EmptyStateType; +} diff --git a/src/components/Highlights/Impact/index.tsx b/src/components/Highlights/Impact/index.tsx index 19f597064..e1b923ebe 100644 --- a/src/components/Highlights/Impact/index.tsx +++ b/src/components/Highlights/Impact/index.tsx @@ -6,6 +6,9 @@ import { openURLInDefaultBrowser } from "../../../utils/actions/openURLInDefault import { sendUserActionTrackingEvent } from "../../../utils/actions/sendUserActionTrackingEvent"; import { ConfigContext } from "../../common/App/ConfigContext"; import { getImpactScoreLabel } from "../../common/ImpactScore"; +import { CrossCircleIcon } from "../../common/icons/16px/CrossCircleIcon"; +import { InfinityIcon } from "../../common/icons/16px/InfinityIcon"; +import { RefreshIcon } from "../../common/icons/16px/RefreshIcon"; import { Button } from "../../common/v3/Button"; import { Card } from "../../common/v3/Card"; import { Tag } from "../../common/v3/Tag"; @@ -111,44 +114,52 @@ export const Impact = () => { ); }; - const handleLearnMoreButtonClick = () => { - sendUserActionTrackingEvent( - trackingEvents.IMPACT_CARD_LEARN_MORE_BUTTON_CLICKED - ); - openURLInDefaultBrowser(PERFORMANCE_IMPACT_DOCUMENTATION_URL); - }; - - if (!config.backendInfo?.centralize) { - return ( - - } - /> - ); - } + const renderCard = () => { + const handleLearnMoreButtonClick = () => { + sendUserActionTrackingEvent( + trackingEvents.IMPACT_CARD_LEARN_MORE_BUTTON_CLICKED + ); + openURLInDefaultBrowser(PERFORMANCE_IMPACT_DOCUMENTATION_URL); + }; - return ( -
- {data && data.impactHighlights.length > 0 ? ( - renderImpactCard(data.impactHighlights) - ) : ( + if (!config.backendInfo?.centralize) { + return ( } /> - )} -
- ); + ); + } + + if (isInitialLoading) { + return ( + + ); + } + + if (!data || data.impactHighlights.length === 0) { + return ( + + ); + } + + return renderImpactCard(data.impactHighlights); + }; + + return
{renderCard()}
; }; diff --git a/src/components/Highlights/Performance/index.tsx b/src/components/Highlights/Performance/index.tsx index 6ff2b108b..25627cff2 100644 --- a/src/components/Highlights/Performance/index.tsx +++ b/src/components/Highlights/Performance/index.tsx @@ -7,6 +7,8 @@ import { sendUserActionTrackingEvent } from "../../../utils/actions/sendUserActi import { formatTimeDistance } from "../../../utils/formatTimeDistance"; import { getDurationString } from "../../../utils/getDurationString"; import { ConfigContext } from "../../common/App/ConfigContext"; +import { CrossCircleIcon } from "../../common/icons/16px/CrossCircleIcon"; +import { RefreshIcon } from "../../common/icons/16px/RefreshIcon"; import { Card } from "../../common/v3/Card"; import { Tag } from "../../common/v3/Tag"; import { EmptyStateCard } from "../EmptyStateCard"; @@ -135,20 +137,32 @@ export const Performance = () => { ); }; - return ( -
- {data && data.performance.length > 0 ? ( - renderPerformanceCard(data.performance) - ) : ( + const renderCard = () => { + if (isInitialLoading) { + return ( + ); + } + + if (!data || data.performance.length === 0) { + return ( + - )} -
- ); + ); + } + + if (data && data.performance.length > 0) { + return renderPerformanceCard(data.performance); + } + }; + + return
{renderCard()}
; }; diff --git a/src/components/Highlights/TopIssues/highlightCards/addEnvironmentColumns.tsx b/src/components/Highlights/TopIssues/highlightCards/addEnvironmentColumns.tsx index 5aa07edf9..13b7aae56 100644 --- a/src/components/Highlights/TopIssues/highlightCards/addEnvironmentColumns.tsx +++ b/src/components/Highlights/TopIssues/highlightCards/addEnvironmentColumns.tsx @@ -3,9 +3,7 @@ import { EnvironmentName } from "../../common/EnvironmentName"; import { TableInsightStatusBadge } from "../../common/TableInsightStatusBadge"; import { EnvironmentData } from "../types"; -export const addEnvironmentColumns = < - T extends { id: string; value: unknown }[] ->( +export const addEnvironmentColumns = ( columnHelper: ColumnHelper>, columns: ColumnDef, any>[] ) => { diff --git a/src/components/Highlights/TopIssues/index.tsx b/src/components/Highlights/TopIssues/index.tsx index dc53ddf7c..366da8874 100644 --- a/src/components/Highlights/TopIssues/index.tsx +++ b/src/components/Highlights/TopIssues/index.tsx @@ -4,6 +4,8 @@ import { ROUTES } from "../../../constants"; import { usePrevious } from "../../../hooks/usePrevious"; import { ChangeViewPayload } from "../../../types"; import { sendUserActionTrackingEvent } from "../../../utils/actions/sendUserActionTrackingEvent"; +import { CrossCircleIcon } from "../../common/icons/16px/CrossCircleIcon"; +import { RefreshIcon } from "../../common/icons/16px/RefreshIcon"; import { Link } from "../../common/v3/Link"; import { EmptyStateCard } from "../EmptyStateCard"; import { Section } from "../common/Section"; @@ -115,6 +117,33 @@ export const TopIssues = () => { const isViewAllLinkDisabled = (data?.topInsights || []).length === 0; + const renderContent = () => { + if (isInitialLoading) { + return ( + + ); + } + + if (!data || data.topInsights.length === 0) { + return ( + + ); + } + + return data.topInsights.map((x) => ( + {renderHighlightCard(x)} + )); + }; + return (
{ } > - {data && data.topInsights.length > 0 ? ( - data.topInsights.map((x) => ( - {renderHighlightCard(x)} - )) - ) : ( - - )} + {renderContent()}
); }; diff --git a/src/components/common/icons/16px/InfinityIcon.tsx b/src/components/common/icons/16px/InfinityIcon.tsx index 32a6b6ba6..6f66b5b89 100644 --- a/src/components/common/icons/16px/InfinityIcon.tsx +++ b/src/components/common/icons/16px/InfinityIcon.tsx @@ -2,7 +2,7 @@ import React from "react"; import { useIconProps } from "../hooks"; import { IconProps } from "../types"; -const CodeIconComponent = (props: IconProps) => { +const InfinityIconComponent = (props: IconProps) => { const { size, color } = useIconProps(props); return ( @@ -30,4 +30,4 @@ const CodeIconComponent = (props: IconProps) => { ); }; -export const CodeIcon = React.memo(CodeIconComponent); +export const InfinityIcon = React.memo(InfinityIconComponent); From dd1b08bbba0e571eef995bef03cfc3196e2075dd Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Fri, 26 Apr 2024 18:36:50 +0200 Subject: [PATCH 02/15] Add Highlights Scaling widget --- .../Highlights/Scaling/Scaling.stories.tsx | 47 +++++ src/components/Highlights/Scaling/index.tsx | 177 ++++++++++++++++++ src/components/Highlights/Scaling/mockData.ts | 49 +++++ src/components/Highlights/Scaling/styles.ts | 6 + src/components/Highlights/Scaling/types.ts | 18 ++ .../Highlights/Scaling/useScalingData.ts | 72 +++++++ src/components/Highlights/tracking.ts | 7 +- src/components/Main/actions.ts | 4 +- 8 files changed, 378 insertions(+), 2 deletions(-) create mode 100644 src/components/Highlights/Scaling/Scaling.stories.tsx create mode 100644 src/components/Highlights/Scaling/index.tsx create mode 100644 src/components/Highlights/Scaling/mockData.ts create mode 100644 src/components/Highlights/Scaling/styles.ts create mode 100644 src/components/Highlights/Scaling/types.ts create mode 100644 src/components/Highlights/Scaling/useScalingData.ts diff --git a/src/components/Highlights/Scaling/Scaling.stories.tsx b/src/components/Highlights/Scaling/Scaling.stories.tsx new file mode 100644 index 000000000..317ad92e2 --- /dev/null +++ b/src/components/Highlights/Scaling/Scaling.stories.tsx @@ -0,0 +1,47 @@ +import { Meta, StoryObj } from "@storybook/react"; + +import { Scaling } from "."; +import { actions } from "../../Main/actions"; +import { mockedScalingData } from "./mockData"; + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction +const meta: Meta = { + title: "Highlights/Scaling", + component: Scaling, + 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; + +// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args + +export const Default: Story = { + play: () => { + window.setTimeout(() => { + window.postMessage({ + type: "digma", + action: actions.SET_HIGHLIGHTS_SCALING_DATA, + payload: mockedScalingData + }); + }); + } +}; + +export const Loading: Story = {}; + +export const Empty: Story = { + play: () => { + window.setTimeout(() => { + window.postMessage({ + type: "digma", + action: actions.SET_HIGHLIGHTS_SCALING_DATA, + payload: { scaling: [] } + }); + }); + } +}; diff --git a/src/components/Highlights/Scaling/index.tsx b/src/components/Highlights/Scaling/index.tsx new file mode 100644 index 000000000..0065590df --- /dev/null +++ b/src/components/Highlights/Scaling/index.tsx @@ -0,0 +1,177 @@ +import { Row, createColumnHelper } from "@tanstack/react-table"; +import { useContext, useEffect, useState } from "react"; +import { actions as globalActions } from "../../../actions"; +import { ROUTES } from "../../../constants"; +import { usePrevious } from "../../../hooks/usePrevious"; +import { ChangeViewPayload } from "../../../types"; +import { openURLInDefaultBrowser } from "../../../utils/actions/openURLInDefaultBrowser"; +import { sendUserActionTrackingEvent } from "../../../utils/actions/sendUserActionTrackingEvent"; +import { getDurationString } from "../../../utils/getDurationString"; +import { ConfigContext } from "../../common/App/ConfigContext"; +import { CrossCircleIcon } from "../../common/icons/16px/CrossCircleIcon"; +import { CheckCircleIcon } from "../../common/icons/20px/CheckCircleIcon"; +import { InfinityIcon } from "../../common/icons/InfinityIcon"; +import { Button } from "../../common/v3/Button"; +import { Card } from "../../common/v3/Card"; +import { EmptyStateCard } from "../EmptyStateCard"; +import { addEnvironmentColumns } from "../TopIssues/highlightCards/addEnvironmentColumns"; +import { EnvironmentData } from "../TopIssues/types"; +import { Section } from "../common/Section"; +import { Table } from "../common/Table"; +import { TableText } from "../common/TableText"; +import { handleEnvironmentTableRowClick } from "../handleEnvironmentTableRowClick"; +import { trackingEvents } from "../tracking"; +import * as s from "./styles"; +import { EnvironmentScalingData } from "./types"; +import { useScalingData } from "./useScalingData"; + +export const Scaling = () => { + const [isInitialLoading, setIsInitialLoading] = useState(true); + const { data, getData } = useScalingData(); + const previousData = usePrevious(data); + const config = useContext(ConfigContext); + + useEffect(() => { + getData(); + }, []); + + useEffect(() => { + if (!previousData && data) { + setIsInitialLoading(false); + } + }, [previousData, data]); + + const renderScalingCard = ( + data: EnvironmentData[] + ) => { + const columnHelper = + createColumnHelper>(); + + const metricsColumns = [ + columnHelper.accessor((x) => x.metrics.concurrency, { + header: "Concurrency", + cell: (info) => { + const value = info.getValue(); + const concurrencyString = String(value); + + return ( + {concurrencyString} + ); + } + }), + columnHelper.accessor((x) => x.metrics.duration, { + header: "Duration", + cell: (info) => { + const value = info.getValue(); + const durationString = getDurationString(value); + + return {durationString}; + } + }) + ]; + + const columns = addEnvironmentColumns(columnHelper, metricsColumns); + + const handleTableRowClick = ( + row: Row> + ) => { + sendUserActionTrackingEvent( + trackingEvents.SCALING_CARD_TABLE_ROW_CLICKED + ); + handleEnvironmentTableRowClick( + config.environments, + row.original.environmentId, + ROUTES.INSIGHTS + ); + }; + + return ( + Scaling badly} + content={ + > + columns={columns} + data={data} + onRowClick={handleTableRowClick} + /> + } + /> + ); + }; + + const renderCard = () => { + const handleLearnMoreButtonClick = () => { + sendUserActionTrackingEvent( + trackingEvents.SCALING_CARD_LEARN_MORE_BUTTON_CLICKED + ); + + // TODO: provide the correct URL + openURLInDefaultBrowser("#"); + }; + + const handleViewAnalyticsButtonClick = () => { + sendUserActionTrackingEvent( + trackingEvents.SCALING_CARD_VIEW_ANALYTICS_BUTTON_CLICKED + ); + + window.sendMessageToDigma({ + action: globalActions.CHANGE_VIEW, + payload: { + view: ROUTES.ANALYTICS + } + }); + }; + + if (!config.backendInfo?.centralize) { + // TODO: refactor to unlock empty state card + return ( + + } + /> + ); + } + + if (isInitialLoading) { + return ( + + ); + } + + // TODO: show the card for partial data + + if (!data || data.scaling.length === 0) { + return ( + + } + /> + ); + } + + return renderScalingCard(data.scaling); + }; + + return
{renderCard()}
; +}; diff --git a/src/components/Highlights/Scaling/mockData.ts b/src/components/Highlights/Scaling/mockData.ts new file mode 100644 index 000000000..b275263be --- /dev/null +++ b/src/components/Highlights/Scaling/mockData.ts @@ -0,0 +1,49 @@ +import { InsightStatus } from "../../Insights/types"; +import { ScalingData } from "./types"; + +export const mockedScalingData: ScalingData = { + scaling: [ + { + environmentId: "1", + environmentName: "Production", + insightStatus: InsightStatus.Active, + criticality: 0.8, + metrics: { + concurrency: 100, + duration: { + value: 22.71, + unit: "ms", + raw: 22705900.0 + } + } + }, + { + environmentId: "2", + environmentName: "Staging", + insightStatus: InsightStatus.Active, + criticality: 0.8, + metrics: { + concurrency: 50, + duration: { + value: 22.71, + unit: "ms", + raw: 22705900.0 + } + } + }, + { + environmentId: "3", + environmentName: "Development", + insightStatus: InsightStatus.Active, + criticality: 0.8, + metrics: { + concurrency: 20, + duration: { + value: 22.71, + unit: "ms", + raw: 22705900.0 + } + } + } + ] +}; diff --git a/src/components/Highlights/Scaling/styles.ts b/src/components/Highlights/Scaling/styles.ts new file mode 100644 index 000000000..9a99e0c71 --- /dev/null +++ b/src/components/Highlights/Scaling/styles.ts @@ -0,0 +1,6 @@ +import styled from "styled-components"; +import { bodySemiboldTypography } from "../../common/App/typographies"; + +export const CardTitle = styled.div` + ${bodySemiboldTypography} +`; diff --git a/src/components/Highlights/Scaling/types.ts b/src/components/Highlights/Scaling/types.ts new file mode 100644 index 000000000..0490b0b88 --- /dev/null +++ b/src/components/Highlights/Scaling/types.ts @@ -0,0 +1,18 @@ +import { Duration } from "../../../globals"; +import { EnvironmentData } from "../TopIssues/types"; + +export type EnvironmentScalingData = { + concurrency: number; + duration: Duration; +}; + +export type ScalingData = { + scaling: EnvironmentData[]; +}; + +export interface GetHighlightsScalingDataPayload { + query: { + scopedSpanCodeObjectId: string | null; + environments: string[]; + }; +} diff --git a/src/components/Highlights/Scaling/useScalingData.ts b/src/components/Highlights/Scaling/useScalingData.ts new file mode 100644 index 000000000..3740e95e7 --- /dev/null +++ b/src/components/Highlights/Scaling/useScalingData.ts @@ -0,0 +1,72 @@ +import { useCallback, useContext, useEffect, useRef, useState } from "react"; +import { dispatcher } from "../../../dispatcher"; +import { usePrevious } from "../../../hooks/usePrevious"; +import { actions as mainActions } from "../../Main/actions"; +import { ConfigContext } from "../../common/App/ConfigContext"; +import { GetHighlightsScalingDataPayload, ScalingData } from "./types"; + +const REFRESH_INTERVAL = 10 * 1000; // in milliseconds + +export const useScalingData = () => { + const [data, setData] = useState(); + const config = useContext(ConfigContext); + const [lastSetDataTimeStamp, setLastSetDataTimeStamp] = useState(); + const previousLastSetDataTimeStamp = usePrevious(lastSetDataTimeStamp); + const refreshTimerId = useRef(); + + const getData = useCallback(() => { + window.sendMessageToDigma({ + action: mainActions.GET_HIGHLIGHTS_SCALING_DATA, + payload: { + query: { + scopedSpanCodeObjectId: config.scope?.span?.spanCodeObjectId || null, + environments: config.environments?.map((x) => x.id) || [] + } + } + }); + }, [config.scope?.span?.spanCodeObjectId, config.environments]); + const previousGetData = usePrevious(getData); + + useEffect(() => { + if (previousGetData && previousGetData !== getData) { + window.clearTimeout(refreshTimerId.current); + + getData(); + } + }, [previousGetData, getData]); + + useEffect(() => { + if ( + previousLastSetDataTimeStamp && + previousLastSetDataTimeStamp !== lastSetDataTimeStamp + ) { + refreshTimerId.current = window.setTimeout(() => { + getData(); + }, REFRESH_INTERVAL); + } + }, [previousLastSetDataTimeStamp, lastSetDataTimeStamp, getData]); + + useEffect(() => { + const handleScalingData = (data: any, timeStamp: number) => { + setData(data as ScalingData); + setLastSetDataTimeStamp(timeStamp); + }; + + dispatcher.addActionListener( + mainActions.SET_HIGHLIGHTS_SCALING_DATA, + handleScalingData + ); + + return () => { + dispatcher.removeActionListener( + mainActions.SET_HIGHLIGHTS_SCALING_DATA, + handleScalingData + ); + }; + }, []); + + return { + data, + getData + }; +}; diff --git a/src/components/Highlights/tracking.ts b/src/components/Highlights/tracking.ts index e35cf5d7e..25f02971a 100644 --- a/src/components/Highlights/tracking.ts +++ b/src/components/Highlights/tracking.ts @@ -11,7 +11,12 @@ export const trackingEvents = addPrefix( PERFORMANCE_CARD_TABLE_ROW_CLICKED: "performance card table row clicked", IMPACT_CARD_TABLE_ROW_CLICKED: "impact card table row clicked", IMPACT_CARD_LEARN_MORE_BUTTON_CLICKED: - "impact card learn more button clicked" + "impact card learn more button clicked", + SCALING_CARD_TABLE_ROW_CLICKED: "scaling card table row clicked", + SCALING_CARD_LEARN_MORE_BUTTON_CLICKED: + "scaling card learn more button clicked", + SCALING_CARD_VIEW_ANALYTICS_BUTTON_CLICKED: + "scaling card view analytics button clicked" }, " " ); diff --git a/src/components/Main/actions.ts b/src/components/Main/actions.ts index 6cf412d8e..b31149c6c 100644 --- a/src/components/Main/actions.ts +++ b/src/components/Main/actions.ts @@ -10,5 +10,7 @@ export const actions = addPrefix(ACTION_PREFIX, { GET_HIGHLIGHTS_PERFORMANCE_DATA: "GET_HIGHLIGHTS_PERFORMANCE_DATA", SET_HIGHLIGHTS_PERFORMANCE_DATA: "SET_HIGHLIGHTS_PERFORMANCE_DATA", GET_HIGHLIGHTS_IMPACT_DATA: "GET_HIGHLIGHTS_IMPACT_DATA", - SET_HIGHLIGHTS_IMPACT_DATA: "SET_HIGHLIGHTS_IMPACT_DATA" + SET_HIGHLIGHTS_IMPACT_DATA: "SET_HIGHLIGHTS_IMPACT_DATA", + GET_HIGHLIGHTS_SCALING_DATA: "GET_HIGHLIGHTS_SCALING_DATA", + SET_HIGHLIGHTS_SCALING_DATA: "SET_HIGHLIGHTS_SCALING_DATA" }); From e32e639902bba509106c384246f6a0803699670a Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Fri, 26 Apr 2024 18:40:01 +0200 Subject: [PATCH 03/15] Bump version --- src/featureFlags.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/featureFlags.ts b/src/featureFlags.ts index bd777f1ea..f73f6d6bb 100644 --- a/src/featureFlags.ts +++ b/src/featureFlags.ts @@ -3,7 +3,7 @@ import { ConfigContextData } from "./components/common/App/types"; import { FeatureFlag } from "./types"; export const featureFlagMinBackendVersions: Record = { - [FeatureFlag.ARE_IMPACT_HIGHLIGHTS_ENABLED]: "0.3.4" + [FeatureFlag.ARE_IMPACT_HIGHLIGHTS_ENABLED]: "0.3.6" }; export const getFeatureFlagValue = ( From db0bcfb1064b7d6daedb335baf3bc12816968ce0 Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Fri, 26 Apr 2024 21:04:00 +0200 Subject: [PATCH 04/15] Bump version --- src/featureFlags.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/featureFlags.ts b/src/featureFlags.ts index f73f6d6bb..809f29403 100644 --- a/src/featureFlags.ts +++ b/src/featureFlags.ts @@ -3,7 +3,7 @@ import { ConfigContextData } from "./components/common/App/types"; import { FeatureFlag } from "./types"; export const featureFlagMinBackendVersions: Record = { - [FeatureFlag.ARE_IMPACT_HIGHLIGHTS_ENABLED]: "0.3.6" + [FeatureFlag.ARE_IMPACT_HIGHLIGHTS_ENABLED]: "0.3.7" }; export const getFeatureFlagValue = ( From 8cd6a3cf3f68eefe799d04df2d81ec468247771a Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Fri, 26 Apr 2024 22:13:04 +0200 Subject: [PATCH 05/15] Update stories, add feature flag --- .../Highlights/EmptyStateCard/types.ts | 2 +- .../Highlights/Highlights.stories.tsx | 39 +++++++++++++ .../Highlights/Scaling/Scaling.stories.tsx | 56 ++++++++++++++++++- src/components/Highlights/Scaling/index.tsx | 2 +- src/components/Highlights/index.tsx | 6 ++ src/featureFlags.ts | 3 +- src/types.ts | 3 +- 7 files changed, 106 insertions(+), 5 deletions(-) diff --git a/src/components/Highlights/EmptyStateCard/types.ts b/src/components/Highlights/EmptyStateCard/types.ts index 7e790da60..6d628b15f 100644 --- a/src/components/Highlights/EmptyStateCard/types.ts +++ b/src/components/Highlights/EmptyStateCard/types.ts @@ -7,7 +7,7 @@ export interface EmptyStateCardProps { type?: EmptyStateType; icon: ComponentType; title?: string; - text: string; + text?: string; customContent?: React.ReactNode; } diff --git a/src/components/Highlights/Highlights.stories.tsx b/src/components/Highlights/Highlights.stories.tsx index 200d2385b..0a81c9a4f 100644 --- a/src/components/Highlights/Highlights.stories.tsx +++ b/src/components/Highlights/Highlights.stories.tsx @@ -1,9 +1,14 @@ import { Meta, StoryObj } from "@storybook/react"; import { Highlights } from "."; +import { featureFlagMinBackendVersions } from "../../featureFlags"; +import { FeatureFlag } from "../../types"; import { actions as mainActions } from "../Main/actions"; +import { ConfigContext, initialState } from "../common/App/ConfigContext"; +import { DeploymentType } from "../common/App/types"; import { mockedImpactData } from "./Impact/mockData"; import { mockedPerformanceData } from "./Performance/mockData"; +import { mockedScalingData } from "./Scaling/mockData"; import { mockedTopIssuesData } from "./TopIssues/mockData"; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction @@ -20,8 +25,25 @@ export default meta; type Story = StoryObj; +const mockedConfig = { + ...initialState, + backendInfo: { + applicationVersion: + featureFlagMinBackendVersions[FeatureFlag.ARE_SCALING_HIGHLIGHTS_ENABLED], + deploymentType: DeploymentType.HELM, + centralize: true + } +}; + // More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args export const Default: Story = { + decorators: [ + (Story) => ( + + + + ) + ], play: () => { window.setTimeout(() => { window.postMessage({ @@ -39,11 +61,23 @@ export const Default: Story = { action: mainActions.SET_HIGHLIGHTS_IMPACT_DATA, payload: mockedImpactData }); + window.postMessage({ + type: "digma", + action: mainActions.SET_HIGHLIGHTS_SCALING_DATA, + payload: mockedScalingData + }); }, 1000); } }; export const Empty: Story = { + decorators: [ + (Story) => ( + + + + ) + ], play: () => { window.setTimeout(() => { window.postMessage({ @@ -61,6 +95,11 @@ export const Empty: Story = { action: mainActions.SET_HIGHLIGHTS_IMPACT_DATA, payload: { impactHighlights: [] } }); + window.postMessage({ + type: "digma", + action: mainActions.SET_HIGHLIGHTS_SCALING_DATA, + payload: { scaling: [] } + }); }, 1000); } }; diff --git a/src/components/Highlights/Scaling/Scaling.stories.tsx b/src/components/Highlights/Scaling/Scaling.stories.tsx index 317ad92e2..2fa541d7a 100644 --- a/src/components/Highlights/Scaling/Scaling.stories.tsx +++ b/src/components/Highlights/Scaling/Scaling.stories.tsx @@ -1,7 +1,11 @@ import { Meta, StoryObj } from "@storybook/react"; import { Scaling } from "."; +import { featureFlagMinBackendVersions } from "../../../featureFlags"; +import { FeatureFlag } from "../../../types"; import { actions } from "../../Main/actions"; +import { ConfigContext, initialState } from "../../common/App/ConfigContext"; +import { DeploymentType } from "../../common/App/types"; import { mockedScalingData } from "./mockData"; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction @@ -20,7 +24,24 @@ type Story = StoryObj; // More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args +const mockedConfig = { + ...initialState, + backendInfo: { + applicationVersion: + featureFlagMinBackendVersions[FeatureFlag.ARE_IMPACT_HIGHLIGHTS_ENABLED], + deploymentType: DeploymentType.HELM, + centralize: true + } +}; + export const Default: Story = { + decorators: [ + (Story) => ( + + + + ) + ], play: () => { window.setTimeout(() => { window.postMessage({ @@ -32,9 +53,24 @@ export const Default: Story = { } }; -export const Loading: Story = {}; +export const Loading: Story = { + decorators: [ + (Story) => ( + + + + ) + ] +}; export const Empty: Story = { + decorators: [ + (Story) => ( + + + + ) + ], play: () => { window.setTimeout(() => { window.postMessage({ @@ -45,3 +81,21 @@ export const Empty: Story = { }); } }; + +export const Disabled: Story = { + decorators: [ + (Story) => ( + + + + ) + ] +}; diff --git a/src/components/Highlights/Scaling/index.tsx b/src/components/Highlights/Scaling/index.tsx index 0065590df..9e677f89c 100644 --- a/src/components/Highlights/Scaling/index.tsx +++ b/src/components/Highlights/Scaling/index.tsx @@ -145,7 +145,7 @@ export const Scaling = () => { ); } diff --git a/src/components/Highlights/index.tsx b/src/components/Highlights/index.tsx index c8a57f36a..b08838c6a 100644 --- a/src/components/Highlights/index.tsx +++ b/src/components/Highlights/index.tsx @@ -4,6 +4,7 @@ import { FeatureFlag } from "../../types"; import { ConfigContext } from "../common/App/ConfigContext"; import { Impact } from "./Impact"; import { Performance } from "./Performance"; +import { Scaling } from "./Scaling"; import { TopIssues } from "./TopIssues"; import * as s from "./styles"; @@ -13,12 +14,17 @@ export const Highlights = () => { config, FeatureFlag.ARE_IMPACT_HIGHLIGHTS_ENABLED ); + const areScalingHighlightsVisible = getFeatureFlagValue( + config, + FeatureFlag.ARE_SCALING_HIGHLIGHTS_ENABLED + ); return ( {areImpactHighlightsVisible && } + {areScalingHighlightsVisible && } ); }; diff --git a/src/featureFlags.ts b/src/featureFlags.ts index bd777f1ea..f6a308041 100644 --- a/src/featureFlags.ts +++ b/src/featureFlags.ts @@ -3,7 +3,8 @@ import { ConfigContextData } from "./components/common/App/types"; import { FeatureFlag } from "./types"; export const featureFlagMinBackendVersions: Record = { - [FeatureFlag.ARE_IMPACT_HIGHLIGHTS_ENABLED]: "0.3.4" + [FeatureFlag.ARE_IMPACT_HIGHLIGHTS_ENABLED]: "0.3.7", + [FeatureFlag.ARE_SCALING_HIGHLIGHTS_ENABLED]: "0.3.7" }; export const getFeatureFlagValue = ( diff --git a/src/types.ts b/src/types.ts index 1ec9ebf9e..66f64d2fd 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,7 +1,8 @@ import { Duration } from "./globals"; export enum FeatureFlag { - ARE_IMPACT_HIGHLIGHTS_ENABLED + ARE_IMPACT_HIGHLIGHTS_ENABLED, + ARE_SCALING_HIGHLIGHTS_ENABLED } export enum InsightType { From 2186012fd40760a3f4bb9c9f901ac54561dd4c43 Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Fri, 26 Apr 2024 22:16:11 +0200 Subject: [PATCH 06/15] Fix empty state cards --- .../Highlights/EmptyStateCard/types.ts | 2 +- .../Highlights/Impact/Impact.stories.tsx | 21 +++++++++---------- src/components/Highlights/Impact/index.tsx | 2 ++ .../Highlights/Performance/index.tsx | 2 +- src/components/Highlights/TopIssues/index.tsx | 4 ++-- 5 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/components/Highlights/EmptyStateCard/types.ts b/src/components/Highlights/EmptyStateCard/types.ts index 7e790da60..6d628b15f 100644 --- a/src/components/Highlights/EmptyStateCard/types.ts +++ b/src/components/Highlights/EmptyStateCard/types.ts @@ -7,7 +7,7 @@ export interface EmptyStateCardProps { type?: EmptyStateType; icon: ComponentType; title?: string; - text: string; + text?: string; customContent?: React.ReactNode; } diff --git a/src/components/Highlights/Impact/Impact.stories.tsx b/src/components/Highlights/Impact/Impact.stories.tsx index fc3106f97..8c3bf55ba 100644 --- a/src/components/Highlights/Impact/Impact.stories.tsx +++ b/src/components/Highlights/Impact/Impact.stories.tsx @@ -53,7 +53,15 @@ export const Default: Story = { } }; -export const Loading: Story = {}; +export const Loading: Story = { + decorators: [ + (Story) => ( + + + + ) + ] +}; export const Empty: Story = { decorators: [ @@ -89,14 +97,5 @@ export const Disabled: Story = { ) - ], - play: () => { - window.setTimeout(() => { - window.postMessage({ - type: "digma", - action: actions.SET_HIGHLIGHTS_IMPACT_DATA, - payload: { impactHighlights: [] } - }); - }); - } + ] }; diff --git a/src/components/Highlights/Impact/index.tsx b/src/components/Highlights/Impact/index.tsx index e1b923ebe..d58b16c81 100644 --- a/src/components/Highlights/Impact/index.tsx +++ b/src/components/Highlights/Impact/index.tsx @@ -144,6 +144,7 @@ export const Impact = () => { ); @@ -153,6 +154,7 @@ export const Impact = () => { return ( ); diff --git a/src/components/Highlights/Performance/index.tsx b/src/components/Highlights/Performance/index.tsx index 25627cff2..679d71de7 100644 --- a/src/components/Highlights/Performance/index.tsx +++ b/src/components/Highlights/Performance/index.tsx @@ -143,7 +143,7 @@ export const Performance = () => { ); diff --git a/src/components/Highlights/TopIssues/index.tsx b/src/components/Highlights/TopIssues/index.tsx index 366da8874..1cdd50769 100644 --- a/src/components/Highlights/TopIssues/index.tsx +++ b/src/components/Highlights/TopIssues/index.tsx @@ -123,7 +123,7 @@ export const TopIssues = () => { ); @@ -134,7 +134,7 @@ export const TopIssues = () => { ); } From c802df26921d6bfaaf884e428c17252fd601e88e Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Sat, 27 Apr 2024 00:11:32 +0200 Subject: [PATCH 07/15] Update icon --- src/components/Highlights/Scaling/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Highlights/Scaling/index.tsx b/src/components/Highlights/Scaling/index.tsx index 9e677f89c..ef860e6af 100644 --- a/src/components/Highlights/Scaling/index.tsx +++ b/src/components/Highlights/Scaling/index.tsx @@ -9,8 +9,8 @@ import { sendUserActionTrackingEvent } from "../../../utils/actions/sendUserActi import { getDurationString } from "../../../utils/getDurationString"; import { ConfigContext } from "../../common/App/ConfigContext"; import { CrossCircleIcon } from "../../common/icons/16px/CrossCircleIcon"; +import { RefreshIcon } from "../../common/icons/16px/RefreshIcon"; import { CheckCircleIcon } from "../../common/icons/20px/CheckCircleIcon"; -import { InfinityIcon } from "../../common/icons/InfinityIcon"; import { Button } from "../../common/v3/Button"; import { Card } from "../../common/v3/Card"; import { EmptyStateCard } from "../EmptyStateCard"; @@ -144,7 +144,7 @@ export const Scaling = () => { return ( ); From 9379ee39f37674f64ba23df6b1c51bc04ee3603b Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Sat, 27 Apr 2024 00:12:12 +0200 Subject: [PATCH 08/15] Use route constant --- src/components/Highlights/Impact/index.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/Highlights/Impact/index.tsx b/src/components/Highlights/Impact/index.tsx index d58b16c81..e0ac17611 100644 --- a/src/components/Highlights/Impact/index.tsx +++ b/src/components/Highlights/Impact/index.tsx @@ -1,6 +1,9 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; import { useContext, useEffect, useState } from "react"; -import { PERFORMANCE_IMPACT_DOCUMENTATION_URL } from "../../../constants"; +import { + PERFORMANCE_IMPACT_DOCUMENTATION_URL, + ROUTES +} from "../../../constants"; import { usePrevious } from "../../../hooks/usePrevious"; import { openURLInDefaultBrowser } from "../../../utils/actions/openURLInDefaultBrowser"; import { sendUserActionTrackingEvent } from "../../../utils/actions/sendUserActionTrackingEvent"; @@ -96,7 +99,7 @@ export const Impact = () => { handleEnvironmentTableRowClick( config.environments, row.original.environmentId, - "/analytics" + ROUTES.ANALYTICS ); }; From 835608ca48d2dd50aab4606bd4cd931c4ca26281 Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Mon, 29 Apr 2024 10:33:00 +0200 Subject: [PATCH 09/15] Rename field --- src/components/Highlights/Impact/index.tsx | 8 ++++---- src/components/Highlights/Impact/mockData.ts | 6 +++--- src/components/Highlights/Impact/types.ts | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/components/Highlights/Impact/index.tsx b/src/components/Highlights/Impact/index.tsx index e0ac17611..513472813 100644 --- a/src/components/Highlights/Impact/index.tsx +++ b/src/components/Highlights/Impact/index.tsx @@ -26,12 +26,12 @@ import * as s from "./styles"; import { EnvironmentImpactData } from "./types"; import { useImpactData } from "./useImpactData"; -const getRankTagType = (rankCriticality: number) => { - if (rankCriticality >= 0.9) { +const getRankTagType = (normalizedRank: number) => { + if (normalizedRank >= 0.9) { return "highSeverity"; } - if (rankCriticality >= 0.5) { + if (normalizedRank >= 0.5) { return "mediumSeverity"; } @@ -83,7 +83,7 @@ export const Impact = () => { cell: (info) => { const value = info.getValue(); const rank = value.rank; - const tagType = getRankTagType(value.rankCriticality); + const tagType = getRankTagType(value.rankNormalized); return ; }, diff --git a/src/components/Highlights/Impact/mockData.ts b/src/components/Highlights/Impact/mockData.ts index 63a79157f..4128c6df5 100644 --- a/src/components/Highlights/Impact/mockData.ts +++ b/src/components/Highlights/Impact/mockData.ts @@ -6,21 +6,21 @@ export const mockedImpactData: ImpactData = { environmentName: "Production", environmentId: "1", rank: 1, - rankCriticality: 0.9, + rankNormalized: 0.9, impact: 0.8 }, { environmentName: "Staging", environmentId: "2", rank: 2, - rankCriticality: 0.6, + rankNormalized: 0.6, impact: 0.6 }, { environmentName: "Development", environmentId: "3", rank: 3, - rankCriticality: 0.1, + rankNormalized: 0.1, impact: 0.2 } ] diff --git a/src/components/Highlights/Impact/types.ts b/src/components/Highlights/Impact/types.ts index 2b164bbea..e7b51b857 100644 --- a/src/components/Highlights/Impact/types.ts +++ b/src/components/Highlights/Impact/types.ts @@ -2,7 +2,7 @@ export type EnvironmentImpactData = { environmentName: string; environmentId: string; rank: number; - rankCriticality: number; + rankNormalized: number; impact: number; }; From a75cd8cfd8de650256369b9ed8c40699e48b3817 Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Tue, 30 Apr 2024 12:28:53 +0200 Subject: [PATCH 10/15] Add documentation links --- src/components/Highlights/Scaling/index.tsx | 6 ++---- src/constants.ts | 6 ++++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/Highlights/Scaling/index.tsx b/src/components/Highlights/Scaling/index.tsx index ef860e6af..7b95bfdea 100644 --- a/src/components/Highlights/Scaling/index.tsx +++ b/src/components/Highlights/Scaling/index.tsx @@ -1,7 +1,7 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; import { useContext, useEffect, useState } from "react"; import { actions as globalActions } from "../../../actions"; -import { ROUTES } from "../../../constants"; +import { ROUTES, SCALING_ISSUE_DOCUMENTATION_URL } from "../../../constants"; import { usePrevious } from "../../../hooks/usePrevious"; import { ChangeViewPayload } from "../../../types"; import { openURLInDefaultBrowser } from "../../../utils/actions/openURLInDefaultBrowser"; @@ -105,8 +105,7 @@ export const Scaling = () => { trackingEvents.SCALING_CARD_LEARN_MORE_BUTTON_CLICKED ); - // TODO: provide the correct URL - openURLInDefaultBrowser("#"); + openURLInDefaultBrowser(SCALING_ISSUE_DOCUMENTATION_URL); }; const handleViewAnalyticsButtonClick = () => { @@ -123,7 +122,6 @@ export const Scaling = () => { }; if (!config.backendInfo?.centralize) { - // TODO: refactor to unlock empty state card return ( Date: Tue, 30 Apr 2024 15:20:33 +0200 Subject: [PATCH 11/15] Switch to using of isCentralize flag --- src/components/Assets/AssetList/index.tsx | 4 +--- src/featureFlags.ts | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/components/Assets/AssetList/index.tsx b/src/components/Assets/AssetList/index.tsx index 5719ca027..140cc4367 100644 --- a/src/components/Assets/AssetList/index.tsx +++ b/src/components/Assets/AssetList/index.tsx @@ -13,7 +13,6 @@ import { isEnvironment } from "../../../typeGuards/isEnvironment"; import { isNumber } from "../../../typeGuards/isNumber"; import { isString } from "../../../typeGuards/isString"; import { ConfigContext } from "../../common/App/ConfigContext"; -import { DeploymentType } from "../../common/App/types"; import { EmptyState } from "../../common/EmptyState"; import { Menu } from "../../common/Menu"; import { NewCircleLoader } from "../../common/NewCircleLoader"; @@ -227,8 +226,7 @@ export const AssetList = (props: AssetListProps) => { const isImpactHidden = useMemo( () => !( - config.backendInfo?.deploymentType === DeploymentType.HELM && - config.environment?.type === "Public" + config.backendInfo?.centralize && config.environment?.type === "Public" ), [config.backendInfo?.deploymentType, config.environment?.type] ); diff --git a/src/featureFlags.ts b/src/featureFlags.ts index f6a308041..92e931a39 100644 --- a/src/featureFlags.ts +++ b/src/featureFlags.ts @@ -4,7 +4,7 @@ import { FeatureFlag } from "./types"; export const featureFlagMinBackendVersions: Record = { [FeatureFlag.ARE_IMPACT_HIGHLIGHTS_ENABLED]: "0.3.7", - [FeatureFlag.ARE_SCALING_HIGHLIGHTS_ENABLED]: "0.3.7" + [FeatureFlag.ARE_SCALING_HIGHLIGHTS_ENABLED]: "0.3.8" }; export const getFeatureFlagValue = ( From 8bbda4fa06af0cfb6f8d54674342182bd151f110 Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Thu, 2 May 2024 11:24:00 +0200 Subject: [PATCH 12/15] Update cards --- src/components/Highlights/Scaling/index.tsx | 64 +++++---------------- src/components/Highlights/tracking.ts | 2 - 2 files changed, 14 insertions(+), 52 deletions(-) diff --git a/src/components/Highlights/Scaling/index.tsx b/src/components/Highlights/Scaling/index.tsx index 7b95bfdea..851b3a3ff 100644 --- a/src/components/Highlights/Scaling/index.tsx +++ b/src/components/Highlights/Scaling/index.tsx @@ -1,15 +1,11 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; -import { useContext, useEffect, useState } from "react"; +import { useContext, useEffect } from "react"; import { actions as globalActions } from "../../../actions"; -import { ROUTES, SCALING_ISSUE_DOCUMENTATION_URL } from "../../../constants"; -import { usePrevious } from "../../../hooks/usePrevious"; +import { ROUTES } from "../../../constants"; import { ChangeViewPayload } from "../../../types"; -import { openURLInDefaultBrowser } from "../../../utils/actions/openURLInDefaultBrowser"; import { sendUserActionTrackingEvent } from "../../../utils/actions/sendUserActionTrackingEvent"; import { getDurationString } from "../../../utils/getDurationString"; import { ConfigContext } from "../../common/App/ConfigContext"; -import { CrossCircleIcon } from "../../common/icons/16px/CrossCircleIcon"; -import { RefreshIcon } from "../../common/icons/16px/RefreshIcon"; import { CheckCircleIcon } from "../../common/icons/20px/CheckCircleIcon"; import { Button } from "../../common/v3/Button"; import { Card } from "../../common/v3/Card"; @@ -26,21 +22,13 @@ import { EnvironmentScalingData } from "./types"; import { useScalingData } from "./useScalingData"; export const Scaling = () => { - const [isInitialLoading, setIsInitialLoading] = useState(true); const { data, getData } = useScalingData(); - const previousData = usePrevious(data); const config = useContext(ConfigContext); useEffect(() => { getData(); }, []); - useEffect(() => { - if (!previousData && data) { - setIsInitialLoading(false); - } - }, [previousData, data]); - const renderScalingCard = ( data: EnvironmentData[] ) => { @@ -100,14 +88,6 @@ export const Scaling = () => { }; const renderCard = () => { - const handleLearnMoreButtonClick = () => { - sendUserActionTrackingEvent( - trackingEvents.SCALING_CARD_LEARN_MORE_BUTTON_CLICKED - ); - - openURLInDefaultBrowser(SCALING_ISSUE_DOCUMENTATION_URL); - }; - const handleViewAnalyticsButtonClick = () => { sendUserActionTrackingEvent( trackingEvents.SCALING_CARD_VIEW_ANALYTICS_BUTTON_CLICKED @@ -121,35 +101,19 @@ export const Scaling = () => { }); }; - if (!config.backendInfo?.centralize) { - return ( - - } - /> - ); - } - - if (isInitialLoading) { - return ( - - ); - } - // TODO: show the card for partial data - + // if (false) { + // return ( + // + // ); + // } + + // TODO: change the condition if (!data || data.scaling.length === 0) { return ( Date: Thu, 2 May 2024 17:48:20 +0200 Subject: [PATCH 13/15] Update cards --- .../Highlights/Impact/Impact.stories.tsx | 2 +- .../Highlights/Scaling/Scaling.stories.tsx | 44 ++++++++------ src/components/Highlights/Scaling/index.tsx | 60 ++++++++++++++----- src/components/Highlights/Scaling/mockData.ts | 1 + src/components/Highlights/Scaling/types.ts | 1 + src/components/Highlights/tracking.ts | 2 + src/featureFlags.ts | 2 +- 7 files changed, 78 insertions(+), 34 deletions(-) diff --git a/src/components/Highlights/Impact/Impact.stories.tsx b/src/components/Highlights/Impact/Impact.stories.tsx index 8c3bf55ba..f4bb5cdc9 100644 --- a/src/components/Highlights/Impact/Impact.stories.tsx +++ b/src/components/Highlights/Impact/Impact.stories.tsx @@ -82,7 +82,7 @@ export const Empty: Story = { } }; -export const Disabled: Story = { +export const Locked: Story = { decorators: [ (Story) => ( ( @@ -47,23 +47,32 @@ export const Default: Story = { window.postMessage({ type: "digma", action: actions.SET_HIGHLIGHTS_SCALING_DATA, - payload: mockedScalingData + payload: { ...mockedScalingData, dataState: "noData" } }); }); } }; -export const Loading: Story = { +export const PartialData: Story = { decorators: [ (Story) => ( ) - ] + ], + play: () => { + window.setTimeout(() => { + window.postMessage({ + type: "digma", + action: actions.SET_HIGHLIGHTS_SCALING_DATA, + payload: { ...mockedScalingData, dataState: "partial" } + }); + }); + } }; -export const Empty: Story = { +export const ScalingWell: Story = { decorators: [ (Story) => ( @@ -76,26 +85,27 @@ export const Empty: Story = { window.postMessage({ type: "digma", action: actions.SET_HIGHLIGHTS_SCALING_DATA, - payload: { scaling: [] } + payload: { ...mockedScalingData, dataState: "scalingWell" } }); }); } }; -export const Disabled: Story = { +export const ScalingBadly: Story = { decorators: [ (Story) => ( - + ) - ] + ], + play: () => { + window.setTimeout(() => { + window.postMessage({ + type: "digma", + action: actions.SET_HIGHLIGHTS_SCALING_DATA, + payload: mockedScalingData + }); + }); + } }; diff --git a/src/components/Highlights/Scaling/index.tsx b/src/components/Highlights/Scaling/index.tsx index 851b3a3ff..33d901bf8 100644 --- a/src/components/Highlights/Scaling/index.tsx +++ b/src/components/Highlights/Scaling/index.tsx @@ -1,11 +1,14 @@ import { Row, createColumnHelper } from "@tanstack/react-table"; import { useContext, useEffect } from "react"; import { actions as globalActions } from "../../../actions"; -import { ROUTES } from "../../../constants"; +import { ROUTES, SCALING_ISSUE_DOCUMENTATION_URL } from "../../../constants"; import { ChangeViewPayload } from "../../../types"; +import { openURLInDefaultBrowser } from "../../../utils/actions/openURLInDefaultBrowser"; import { sendUserActionTrackingEvent } from "../../../utils/actions/sendUserActionTrackingEvent"; import { getDurationString } from "../../../utils/getDurationString"; import { ConfigContext } from "../../common/App/ConfigContext"; +import { CrossCircleIcon } from "../../common/icons/16px/CrossCircleIcon"; +import { RefreshIcon } from "../../common/icons/16px/RefreshIcon"; import { CheckCircleIcon } from "../../common/icons/20px/CheckCircleIcon"; import { Button } from "../../common/v3/Button"; import { Card } from "../../common/v3/Card"; @@ -88,6 +91,14 @@ export const Scaling = () => { }; const renderCard = () => { + const handleLearnMoreButtonClick = () => { + sendUserActionTrackingEvent( + trackingEvents.SCALING_CARD_LEARN_MORE_BUTTON_CLICKED + ); + + openURLInDefaultBrowser(SCALING_ISSUE_DOCUMENTATION_URL); + }; + const handleViewAnalyticsButtonClick = () => { sendUserActionTrackingEvent( trackingEvents.SCALING_CARD_VIEW_ANALYTICS_BUTTON_CLICKED @@ -101,20 +112,39 @@ export const Scaling = () => { }); }; - // TODO: show the card for partial data - // if (false) { - // return ( - // - // ); - // } - - // TODO: change the condition - if (!data || data.scaling.length === 0) { + if (!data) { + return null; + } + + if (data?.dataState === "noData") { + return ( + + } + /> + ); + } + + if (data?.dataState === "partial") { + return ( + + ); + } + + if (data?.dataState === "scalingWell") { return ( []; }; diff --git a/src/components/Highlights/tracking.ts b/src/components/Highlights/tracking.ts index dff859a4d..25f02971a 100644 --- a/src/components/Highlights/tracking.ts +++ b/src/components/Highlights/tracking.ts @@ -13,6 +13,8 @@ export const trackingEvents = addPrefix( IMPACT_CARD_LEARN_MORE_BUTTON_CLICKED: "impact card learn more button clicked", SCALING_CARD_TABLE_ROW_CLICKED: "scaling card table row clicked", + SCALING_CARD_LEARN_MORE_BUTTON_CLICKED: + "scaling card learn more button clicked", SCALING_CARD_VIEW_ANALYTICS_BUTTON_CLICKED: "scaling card view analytics button clicked" }, diff --git a/src/featureFlags.ts b/src/featureFlags.ts index 92e931a39..eea123e41 100644 --- a/src/featureFlags.ts +++ b/src/featureFlags.ts @@ -4,7 +4,7 @@ import { FeatureFlag } from "./types"; export const featureFlagMinBackendVersions: Record = { [FeatureFlag.ARE_IMPACT_HIGHLIGHTS_ENABLED]: "0.3.7", - [FeatureFlag.ARE_SCALING_HIGHLIGHTS_ENABLED]: "0.3.8" + [FeatureFlag.ARE_SCALING_HIGHLIGHTS_ENABLED]: "0.3.13" }; export const getFeatureFlagValue = ( From b77d4eee3b145c323632dc13ae97d5508fa07422 Mon Sep 17 00:00:00 2001 From: olehp Date: Thu, 9 May 2024 19:04:03 +0300 Subject: [PATCH 14/15] update enum --- src/components/Highlights/Scaling/index.tsx | 6 +++--- src/components/Highlights/Scaling/mockData.ts | 2 +- src/components/Highlights/Scaling/types.ts | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/Highlights/Scaling/index.tsx b/src/components/Highlights/Scaling/index.tsx index 33d901bf8..edd7ceced 100644 --- a/src/components/Highlights/Scaling/index.tsx +++ b/src/components/Highlights/Scaling/index.tsx @@ -116,7 +116,7 @@ export const Scaling = () => { return null; } - if (data?.dataState === "noData") { + if (data?.dataState === "NoData") { return ( { ); } - if (data?.dataState === "partial") { + if (data?.dataState === "Partial") { return ( { ); } - if (data?.dataState === "scalingWell") { + if (data?.dataState === "ScalingWell") { return ( []; }; From a5833afbd0c4fe6de1ad231ce2f90058f7b207a1 Mon Sep 17 00:00:00 2001 From: olehp Date: Thu, 9 May 2024 21:54:24 +0300 Subject: [PATCH 15/15] Fix merge --- src/components/Highlights/Highlights.stories.tsx | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/components/Highlights/Highlights.stories.tsx b/src/components/Highlights/Highlights.stories.tsx index 4fc12472a..020b5b1cf 100644 --- a/src/components/Highlights/Highlights.stories.tsx +++ b/src/components/Highlights/Highlights.stories.tsx @@ -13,16 +13,6 @@ import { mockedTopIssuesData } from "./TopIssues/mockData"; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction -const mockedConfig = { - ...initialState, - backendInfo: { - applicationVersion: - featureFlagMinBackendVersions[FeatureFlag.ARE_IMPACT_HIGHLIGHTS_ENABLED], - deploymentType: DeploymentType.HELM, - centralize: true - } -}; - const meta: Meta = { title: "Highlights/Highlights", component: Highlights,