From d85351c95581377173885375ec08495f408f5744 Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Tue, 15 Aug 2023 17:01:14 +0200 Subject: [PATCH 1/2] Update text and styles of No Data screens --- .../AssetEntry/AssetEntry.stories.tsx | 4 + .../Assets/AssetList/AssetEntry/index.tsx | 42 ++-- .../Assets/AssetList/AssetEntry/styles.ts | 9 +- src/components/Assets/index.tsx | 58 ++--- src/components/Assets/styles.ts | 44 +--- src/components/RecentActivity/index.tsx | 19 +- src/components/RecentActivity/styles.ts | 11 +- src/components/Troubleshooting/index.tsx | 6 + src/components/common/EmptyState/index.tsx | 32 +++ src/components/common/EmptyState/styles.ts | 43 ++++ src/components/common/EmptyState/types.ts | 8 + src/components/common/icons/CardsIcon.tsx | 206 ++++++++++++++++++ src/trackingEvents.ts | 3 + 13 files changed, 381 insertions(+), 104 deletions(-) create mode 100644 src/components/common/EmptyState/index.tsx create mode 100644 src/components/common/EmptyState/styles.ts create mode 100644 src/components/common/EmptyState/types.ts create mode 100644 src/components/common/icons/CardsIcon.tsx create mode 100644 src/trackingEvents.ts diff --git a/src/components/Assets/AssetList/AssetEntry/AssetEntry.stories.tsx b/src/components/Assets/AssetList/AssetEntry/AssetEntry.stories.tsx index 00aa837ad..8ff502eca 100644 --- a/src/components/Assets/AssetList/AssetEntry/AssetEntry.stories.tsx +++ b/src/components/Assets/AssetList/AssetEntry/AssetEntry.stories.tsx @@ -65,6 +65,10 @@ export const Default: Story = { traceIds: ["7343BEA8BDBC98BA4779A8808E5BD7C9"] } ], + impactScores: { + ScoreExp25: 0, + ScoreExp1000: 0 + }, insights: [ { type: "Errors", diff --git a/src/components/Assets/AssetList/AssetEntry/index.tsx b/src/components/Assets/AssetList/AssetEntry/index.tsx index 5734d9035..80c5e1a6b 100644 --- a/src/components/Assets/AssetList/AssetEntry/index.tsx +++ b/src/components/Assets/AssetList/AssetEntry/index.tsx @@ -107,7 +107,7 @@ export const AssetEntry = (props: AssetEntryProps) => { - + Services @@ -122,6 +122,15 @@ export const AssetEntry = (props: AssetEntryProps) => { )} + + Last + + {timeAgo(lastSeenDateTime)} + ago + + + + Performance @@ -131,23 +140,6 @@ export const AssetEntry = (props: AssetEntryProps) => { )} - {props.entry.impactScores && ( - - Performance impact - - {getImpactScoreLabel(props.entry.impactScores.ScoreExp25)} - - - )} - - - - Last - - {timeAgo(lastSeenDateTime)} - ago - - Slowest 5% @@ -159,15 +151,23 @@ export const AssetEntry = (props: AssetEntryProps) => { )} - {props.entry.impactScores && ( + + {props.entry.impactScores && ( + + + Performance impact + + {getImpactScoreLabel(props.entry.impactScores.ScoreExp25)} + + Overall impact {getImpactScoreLabel(props.entry.impactScores.ScoreExp1000)} - )} - + + )} ); diff --git a/src/components/Assets/AssetList/AssetEntry/styles.ts b/src/components/Assets/AssetList/AssetEntry/styles.ts index bb0a04c45..363753783 100644 --- a/src/components/Assets/AssetList/AssetEntry/styles.ts +++ b/src/components/Assets/AssetList/AssetEntry/styles.ts @@ -74,7 +74,7 @@ export const InsightIconContainer = styled(AssetTypeIconContainer)` export const StatsContainer = styled.div` display: flex; - gap: 16px 12px; + gap: 12px 16px; flex-wrap: wrap; font-size: 10px; line-height: 12px; @@ -83,13 +83,14 @@ export const StatsContainer = styled.div` export const Stats = styled.div` display: flex; flex-direction: column; - gap: 4px; + gap: 8px; width: 120px; `; -export const StatsRow = styled.div` +export const StatsColumn = styled.div` + flex-direction: column; display: flex; - gap: 16px; + gap: 12px; `; export const ServicesContainer = styled.div` diff --git a/src/components/Assets/index.tsx b/src/components/Assets/index.tsx index 13e268e08..78c2c3505 100644 --- a/src/components/Assets/index.tsx +++ b/src/components/Assets/index.tsx @@ -1,13 +1,13 @@ import { useEffect, useMemo, useState } from "react"; -import { DefaultTheme, useTheme } from "styled-components"; import { actions as globalActions } from "../../actions"; -import { SLACK_WORKSPACE_URL } from "../../constants"; import { dispatcher } from "../../dispatcher"; +import { trackingEvents as globalTrackingEvents } from "../../trackingEvents"; import { isNumber } from "../../typeGuards/isNumber"; import { addPrefix } from "../../utils/addPrefix"; import { groupBy } from "../../utils/groupBy"; -import { openURLInDefaultBrowser } from "../../utils/openURLInDefaultBrowser"; -import { StackIcon } from "../common/icons/StackIcon"; +import { sendTrackingEvent } from "../../utils/sendTrackingEvent"; +import { EmptyState } from "../common/EmptyState"; +import { CardsIcon } from "../common/icons/CardsIcon"; import { AssetList } from "./AssetList"; import { AssetTypeList } from "./AssetTypeList"; import * as s from "./styles"; @@ -59,24 +59,12 @@ const groupEntries = (data: ServiceAssetsEntry[]): GroupedAssetEntries => { return groupedAssetEntries; }; -const getNoDataIconColor = (theme: DefaultTheme) => { - switch (theme.mode) { - case "light": - return "#f1f5fa"; - case "dark": - case "dark-jetbrains": - return "#c6c6c6"; - } -}; - export const Assets = (props: AssetsProps) => { const [selectedAssetTypeId, setSelectedAssetTypeId] = useState( null ); const [data, setData] = useState(); const [lastSetDataTimeStamp, setLastSetDataTimeStamp] = useState(); - const theme = useTheme(); - const noDataIconColor = getNoDataIconColor(theme); useEffect(() => { window.sendMessageToDigma({ @@ -130,11 +118,11 @@ export const Assets = (props: AssetsProps) => { }); }; - const handleSlackLinkClick = () => { - openURLInDefaultBrowser(SLACK_WORKSPACE_URL); - }; + const handleTroubleshootingLinkClick = () => { + sendTrackingEvent(globalTrackingEvents.TROUBLESHOOTING_LINK_CLICKED, { + origin: "assets" + }); - const handleDocumentationLinkClick = () => { window.sendMessageToDigma({ action: globalActions.OPEN_TROUBLESHOOTING_GUIDE }); @@ -144,19 +132,21 @@ export const Assets = (props: AssetsProps) => { if (!data || Object.keys(data).length === 0) { return ( - - - - No Data - - Please check out our{" "} - - documentation - {" "} - to see how to collect data from your application. If you still have - any issues, please let us know on our{" "} - Slack channel. - + + + Trigger actions that call this application to learn more about + its runtime behavior + + + Not seeing your application data? + + + } + /> ); } @@ -177,7 +167,7 @@ export const Assets = (props: AssetsProps) => { entries={selectedAssetTypeEntries} /> ); - }, [data, selectedAssetTypeId, noDataIconColor]); + }, [data, selectedAssetTypeId]); return {renderContent}; }; diff --git a/src/components/Assets/styles.ts b/src/components/Assets/styles.ts index 9b1e1c034..5bb1b513c 100644 --- a/src/components/Assets/styles.ts +++ b/src/components/Assets/styles.ts @@ -15,12 +15,16 @@ export const Container = styled.div` `; export const NoDataContainer = styled.div` + min-height: 100vh; display: flex; flex-direction: column; align-items: center; - padding: 62px 38px; - font-weight: 500; +`; + +export const EmptyStateDescription = styled.span` font-size: 12px; + font-weight: 500; + margin-bottom: 4px; text-align: center; color: ${({ theme }) => { switch (theme.mode) { @@ -33,44 +37,16 @@ export const NoDataContainer = styled.div` }}; `; -export const NoDataTitle = styled.span` +export const TroubleshootingLink = styled(CommonLink)` font-size: 14px; - text-transform: capitalize; - margin: 20px 0 4px; + line-height: normal; color: ${({ theme }) => { switch (theme.mode) { case "light": - return "#4d668a"; + return "#7891d0"; case "dark": case "dark-jetbrains": - return "#dadada"; + return "#92affa"; } }}; `; - -export const NoDataText = styled.span` - margin-bottom: 14px; -`; - -export const Circle = styled.div` - width: 72px; - height: 72px; - display: flex; - align-items: center; - justify-content: center; - border-radius: 50%; - background: ${({ theme }) => { - switch (theme.mode) { - case "light": - return "#d0d6eb"; - case "dark": - case "dark-jetbrains": - return "#323334"; - } - }}; -`; - -export const Link = styled(CommonLink)` - font-size: 12px; - line-height: 16px; -`; diff --git a/src/components/RecentActivity/index.tsx b/src/components/RecentActivity/index.tsx index def07a44e..692414d52 100644 --- a/src/components/RecentActivity/index.tsx +++ b/src/components/RecentActivity/index.tsx @@ -4,8 +4,10 @@ import { useContext, useEffect, useMemo, useState } from "react"; import { actions as globalActions } from "../../actions"; import { dispatcher } from "../../dispatcher"; import { usePrevious } from "../../hooks/usePrevious"; +import { trackingEvents as globalTrackingEvents } from "../../trackingEvents"; import { addPrefix } from "../../utils/addPrefix"; import { groupBy } from "../../utils/groupBy"; +import { sendTrackingEvent } from "../../utils/sendTrackingEvent"; import { ConfigContext } from "../common/App/ConfigContext"; import { CursorFollower } from "../common/CursorFollower"; import { DigmaLogoFlatIcon } from "../common/icons/DigmaLogoFlatIcon"; @@ -28,7 +30,11 @@ const actions = addPrefix(ACTION_PREFIX, { CLOSE_LIVE_VIEW: "CLOSE_LIVE_VIEW" }); -const handleDocumentationLinkClick = () => { +const handleTroubleshootingLinkClick = () => { + sendTrackingEvent(globalTrackingEvents.TROUBLESHOOTING_LINK_CLICKED, { + origin: "recent activity" + }); + window.sendMessageToDigma({ action: globalActions.OPEN_TROUBLESHOOTING_GUIDE }); @@ -40,11 +46,14 @@ const renderNoData = () => { - No Recent Activity - Check our documentation - + No Data Yet + + Trigger actions that call this application to learn more about its + runtime behavior + + Not seeing your application data? - + ); }; diff --git a/src/components/RecentActivity/styles.ts b/src/components/RecentActivity/styles.ts index 557b007ea..b828d6b5b 100644 --- a/src/components/RecentActivity/styles.ts +++ b/src/components/RecentActivity/styles.ts @@ -69,6 +69,8 @@ export const NoDataContainer = styled.div` flex-direction: column; align-items: center; padding: 12px 0 18px; + border-radius: 12px; + gap: 4px; background: ${({ theme }) => { switch (theme.mode) { case "light": @@ -79,7 +81,6 @@ export const NoDataContainer = styled.div` return "#3d3f41"; } }}; - border-radius: 12px; `; export const NoDataTitle = styled.span` @@ -95,12 +96,11 @@ export const NoDataTitle = styled.span` return "#b9c2eb"; } }}; - margin-top: 4px; `; export const NoDataText = styled.span` font-weight: 400; - font-size: 10px; + font-size: 12px; line-height: 16px; color: ${({ theme }) => { switch (theme.mode) { @@ -111,11 +111,10 @@ export const NoDataText = styled.span` return "#7c7c94"; } }}; - margin-top: 4px; `; -export const DocumentationLink = styled(Link)` - font-size: 10px; +export const TroubleshootingLink = styled(Link)` + font-size: 14px; line-height: 16px; text-decoration: none; color: ${({ theme }) => { diff --git a/src/components/Troubleshooting/index.tsx b/src/components/Troubleshooting/index.tsx index 4d2b2170b..35d09993e 100644 --- a/src/components/Troubleshooting/index.tsx +++ b/src/components/Troubleshooting/index.tsx @@ -1,3 +1,4 @@ +import { useEffect } from "react"; import { DefaultTheme, useTheme } from "styled-components"; import { actions as globalActions } from "../../actions"; import { SLACK_WORKSPACE_URL } from "../../constants"; @@ -23,6 +24,7 @@ const TRACKING_PREFIX = "troubleshooting"; export const trackingEvents = addPrefix( TRACKING_PREFIX, { + PAGE_LOADED: "page loaded", RUN_OPTION_BUTTON_CLICKED: "run option button clicked", CLOSE_BUTTON_CLICKED: "close button clicked", SLACK_LINK_CLICKED: "slack link clicked" @@ -56,6 +58,10 @@ export const Troubleshooting = () => { const runOptionButtonIconColor = getRunOptionButtonIconColor(theme); const closeButtonIconColor = getCloseButtonIconColor(theme); + useEffect(() => { + sendTrackingEvent(trackingEvents.PAGE_LOADED); + }, []); + const runOptions = [ { key: "terminal", diff --git a/src/components/common/EmptyState/index.tsx b/src/components/common/EmptyState/index.tsx new file mode 100644 index 000000000..038272501 --- /dev/null +++ b/src/components/common/EmptyState/index.tsx @@ -0,0 +1,32 @@ +import { DefaultTheme, useTheme } from "styled-components"; +import { getThemeKind } from "../../common/App/styles"; +import * as s from "./styles"; +import { EmptyStateProps } from "./types"; + +const getIconColor = (theme: DefaultTheme) => { + switch (theme.mode) { + case "light": + return "#fbfdff"; + case "dark": + case "dark-jetbrains": + return "#9b9b9b"; + } +}; + +export const EmptyState = (props: EmptyStateProps) => { + const theme = useTheme(); + const themeKind = getThemeKind(theme); + const iconColor = getIconColor(theme); + + return ( + + {props.icon && ( + + + + )} + {props.title} + {props.content} + + ); +}; diff --git a/src/components/common/EmptyState/styles.ts b/src/components/common/EmptyState/styles.ts new file mode 100644 index 000000000..bae74d52f --- /dev/null +++ b/src/components/common/EmptyState/styles.ts @@ -0,0 +1,43 @@ +import styled from "styled-components"; + +export const Container = styled.div` + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + padding: 0 40px; + gap: 4px; + flex-grow: 1; +`; + +export const IconContainer = styled.div` + width: 72px; + height: 72px; + border-radius: 50%; + background: ${({ theme }) => { + switch (theme.mode) { + case "light": + return "#d0d6eb"; + case "dark": + case "dark-jetbrains": + return "#323334"; + } + }}; +`; + +export const Title = styled.div` + margin-top: 4px; + text-transform: capitalize; + font-size: 14px; + font-weight: 500; + text-align: center; + color: ${({ theme }) => { + switch (theme.mode) { + case "light": + return "#4d668a"; + case "dark": + case "dark-jetbrains": + return "#dadada"; + } + }}; +`; diff --git a/src/components/common/EmptyState/types.ts b/src/components/common/EmptyState/types.ts new file mode 100644 index 000000000..7b8b0a102 --- /dev/null +++ b/src/components/common/EmptyState/types.ts @@ -0,0 +1,8 @@ +import { ReactNode } from "react"; +import { ThemeableIconProps } from "../../common/icons/types"; + +export interface EmptyStateProps { + icon?: React.ComponentType; + title?: string; + content?: ReactNode; +} diff --git a/src/components/common/icons/CardsIcon.tsx b/src/components/common/icons/CardsIcon.tsx new file mode 100644 index 000000000..140a62feb --- /dev/null +++ b/src/components/common/icons/CardsIcon.tsx @@ -0,0 +1,206 @@ +import React from "react"; +import { useIconProps } from "./hooks"; +import { ThemeableIconProps } from "./types"; + +const CardsIconComponent = (props: ThemeableIconProps) => { + const { size } = useIconProps(props); + + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export const CardsIcon = React.memo(CardsIconComponent); diff --git a/src/trackingEvents.ts b/src/trackingEvents.ts new file mode 100644 index 000000000..162df7dd4 --- /dev/null +++ b/src/trackingEvents.ts @@ -0,0 +1,3 @@ +export const trackingEvents = { + TROUBLESHOOTING_LINK_CLICKED: "troubleshooting link clicked" +}; From 2d90e118254d33bee05eb1aee5e1a57e2b3753bb Mon Sep 17 00:00:00 2001 From: Kyrylo Shmidt Date: Tue, 15 Aug 2023 17:06:14 +0200 Subject: [PATCH 2/2] Fix key in Page --- src/components/Documentation/Page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Documentation/Page.tsx b/src/components/Documentation/Page.tsx index bdce63659..cbf29cb7c 100644 --- a/src/components/Documentation/Page.tsx +++ b/src/components/Documentation/Page.tsx @@ -8,8 +8,8 @@ export const Page = (props: PageProps) => ( {props.description} {props.sections && - props.sections.map((section) => ( - + props.sections.map((section, i) => ( + {Number.isInteger(section.number) && ( {section.number}