diff --git a/.vscode/settings.json b/.vscode/settings.json index a2da032a6..e80de0519 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,5 +5,5 @@ }, "editor.defaultFormatter": "esbenp.prettier-vscode", "stylelint.validate": ["typescript"], - "cSpell.words": ["digma", "digmathon", "digmo", "undismiss"] + "cSpell.words": ["digma", "digmathon", "digmo", "leaderboard", "undismiss"] } diff --git a/digmathonLeaderboard.html b/digmathonLeaderboard.html new file mode 100644 index 000000000..2953ad335 --- /dev/null +++ b/digmathonLeaderboard.html @@ -0,0 +1,159 @@ + + + +
+ Leaderboard + * Updated at 9 am GMT+2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Contestant Email + Issues foundLast issueLast update
+
+
+ 1 +
+ example1@email.com +
+
26Bottleneck + Today, 1:20 pm +
+
+
+ 2 +
+ example2@email.com +
+
20Code Nexus Point + May 5, 2:33 pm +
+
+
+ 3 +
+ example3@email.com +
+
16Inefficient Query + May 5, 1:04 pm +
+
+ + diff --git a/digmathonLeaderboardEmpty.html b/digmathonLeaderboardEmpty.html new file mode 100644 index 000000000..816270de3 --- /dev/null +++ b/digmathonLeaderboardEmpty.html @@ -0,0 +1,152 @@ + + + +
+ Leaderboard + coming soon +
+ + + + + + + + + + + + + + + + + + + + + + + + + Stay tuned + Digmathon results will appear here and update hourly. +
+
+ + diff --git a/src/components/Highlights/Highlights.stories.tsx b/src/components/Highlights/Highlights.stories.tsx index 200d2385b..84fc6cd74 100644 --- a/src/components/Highlights/Highlights.stories.tsx +++ b/src/components/Highlights/Highlights.stories.tsx @@ -1,19 +1,41 @@ 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 { 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, parameters: { // More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout layout: "fullscreen" - } + }, + decorators: [ + (Story) => ( + + + + ) + ] }; export default meta; diff --git a/src/components/Highlights/Impact/index.tsx b/src/components/Highlights/Impact/index.tsx index b7b0f8c67..f56ec9dd7 100644 --- a/src/components/Highlights/Impact/index.tsx +++ b/src/components/Highlights/Impact/index.tsx @@ -146,5 +146,5 @@ export const Impact = () => { return renderImpactCard(data.impactHighlights); }; - return
{renderCard()}
; + return
{renderCard()}
; }; diff --git a/src/components/Highlights/Performance/index.tsx b/src/components/Highlights/Performance/index.tsx index 679d71de7..b69a4f860 100644 --- a/src/components/Highlights/Performance/index.tsx +++ b/src/components/Highlights/Performance/index.tsx @@ -125,7 +125,7 @@ export const Performance = () => { return ( Performance} + header={Duration} content={ columns={columns} diff --git a/src/components/Highlights/common/Section/index.tsx b/src/components/Highlights/common/Section/index.tsx index 62310a8ed..6eaa01b53 100644 --- a/src/components/Highlights/common/Section/index.tsx +++ b/src/components/Highlights/common/Section/index.tsx @@ -1,12 +1,15 @@ +import { isString } from "../../../../typeGuards/isString"; import * as s from "./styles"; import { SectionProps } from "./types"; export const Section = ({ title, toolbarContent, children }: SectionProps) => ( - - {title} -
{toolbarContent}
-
+ {(isString(title) || toolbarContent) && ( + + {title} +
{toolbarContent}
+
+ )} {children}
); diff --git a/src/components/Highlights/common/Section/types.ts b/src/components/Highlights/common/Section/types.ts index 82e882810..0da7b5c2d 100644 --- a/src/components/Highlights/common/Section/types.ts +++ b/src/components/Highlights/common/Section/types.ts @@ -1,7 +1,7 @@ import { ReactNode } from "react"; export interface SectionProps { - title: string; + title?: string; toolbarContent?: ReactNode; children: ReactNode; } diff --git a/src/components/Navigation/EnvironmentBar/index.tsx b/src/components/Navigation/EnvironmentBar/index.tsx index af7d9c222..4a624e0ca 100644 --- a/src/components/Navigation/EnvironmentBar/index.tsx +++ b/src/components/Navigation/EnvironmentBar/index.tsx @@ -16,6 +16,10 @@ export const EnvironmentBar = (props: EnvironmentBarProps) => { } }; + const environmentName = props.selectedEnvironment + ? props.selectedEnvironment.name + : "No environments"; + return ( { )} - {props.selectedEnvironment ? ( - - - {props.selectedEnvironment.name} - - - ) : ( - "No environments" - )} + + {environmentName} + theme.colors.v3.icon.disabled}; diff --git a/src/components/RecentActivity/Digmathon/CongratulationsView/index.tsx b/src/components/RecentActivity/Digmathon/CongratulationsView/index.tsx index 0205d3332..c108ee543 100644 --- a/src/components/RecentActivity/Digmathon/CongratulationsView/index.tsx +++ b/src/components/RecentActivity/Digmathon/CongratulationsView/index.tsx @@ -1,4 +1,5 @@ import { useContext, useEffect } from "react"; +import { isString } from "../../../../typeGuards/isString"; import { sendTrackingEvent } from "../../../../utils/actions/sendTrackingEvent"; import { sendUserActionTrackingEvent } from "../../../../utils/actions/sendUserActionTrackingEvent"; import { ConfigContext } from "../../../common/App/ConfigContext"; @@ -19,7 +20,7 @@ const getEmailURL = ( const subject = `Digmathon Challenge Completed! [${userId}]`; const foundInsights = data - .filter((x) => x.isFound) + .filter((x) => isString(x.foundAt)) .map((x) => x.data?.title || x.type) .join(", "); const body = [ diff --git a/src/components/RecentActivity/Digmathon/Digmathon.stories.tsx b/src/components/RecentActivity/Digmathon/Digmathon.stories.tsx index a4c596a04..536b3591c 100644 --- a/src/components/RecentActivity/Digmathon/Digmathon.stories.tsx +++ b/src/components/RecentActivity/Digmathon/Digmathon.stories.tsx @@ -1,12 +1,31 @@ import { Meta, StoryObj } from "@storybook/react"; import { Digmathon } from "."; import { actions } from "../actions"; +import { useDigmathonProgressData } from "../useDigmathonProgressData"; import { mockedDigmathonProgressData } from "./mockData"; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction const meta: Meta = { title: "Recent Activity/Digmathon", component: Digmathon, + decorators: [ + () => { + const { data, getData, foundIssuesCount, isDigmathonCompleted } = + useDigmathonProgressData(); + + return ( + { + return undefined; + }} + /> + ); + } + ], parameters: { // More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout layout: "fullscreen" @@ -19,35 +38,45 @@ type Story = StoryObj; // More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args export const Default: Story = { - args: { - getData: () => { - return undefined; - } - }, play: () => { window.setTimeout(() => { window.postMessage({ type: "digma", action: actions.SET_DIGMATHON_PROGRESS_DATA, - payload: mockedDigmathonProgressData + payload: { + ...mockedDigmathonProgressData, + insights: mockedDigmathonProgressData.insights.slice(0, 4) + } }); }, 0); } }; -export const Congratulations: Story = { - args: { - getData: () => { - return undefined; - } - }, +export const HasNewData: Story = { play: () => { window.setTimeout(() => { window.postMessage({ type: "digma", action: actions.SET_DIGMATHON_PROGRESS_DATA, - payload: mockedDigmathonProgressData + payload: { + ...mockedDigmathonProgressData, + insights: mockedDigmathonProgressData.insights.slice(0, 4) + } }); }, 0); + + window.setTimeout(() => { + window.postMessage({ + type: "digma", + action: actions.SET_DIGMATHON_PROGRESS_DATA, + payload: { + ...mockedDigmathonProgressData, + insights: mockedDigmathonProgressData.insights.slice(0, 6), + lastUpdatedByUserAt: "2023-01-05T13:14:47.010Z" + } + }); + }, 1000); } }; + +export const Congratulations: Story = {}; diff --git a/src/components/RecentActivity/Digmathon/DigmathonInsightCard/styles.ts b/src/components/RecentActivity/Digmathon/DigmathonInsightCard/styles.ts index 205d0cd22..5d13b6dbe 100644 --- a/src/components/RecentActivity/Digmathon/DigmathonInsightCard/styles.ts +++ b/src/components/RecentActivity/Digmathon/DigmathonInsightCard/styles.ts @@ -25,6 +25,7 @@ export const Container = styled.div` box-sizing: border-box; overflow: hidden; position: relative; + transition-duration: 500ms; `; export const NumberContainer = styled.div` diff --git a/src/components/RecentActivity/Digmathon/ProgressView/index.tsx b/src/components/RecentActivity/Digmathon/ProgressView/index.tsx index 6be8d3704..351fbb9f1 100644 --- a/src/components/RecentActivity/Digmathon/ProgressView/index.tsx +++ b/src/components/RecentActivity/Digmathon/ProgressView/index.tsx @@ -1,20 +1,77 @@ -import { useEffect } from "react"; +import { useContext, useEffect } from "react"; +import { CSSTransition } from "react-transition-group"; +import { isString } from "../../../../typeGuards/isString"; +import { openURLInDefaultBrowser } from "../../../../utils/actions/openURLInDefaultBrowser"; import { sendTrackingEvent } from "../../../../utils/actions/sendTrackingEvent"; +import { sendUserActionTrackingEvent } from "../../../../utils/actions/sendUserActionTrackingEvent"; +import { ConfigContext } from "../../../common/App/ConfigContext"; +import { ChevronIcon } from "../../../common/icons/16px/ChevronIcon"; +import { DigmaLogoIcon } from "../../../common/icons/DigmaLogoIcon"; +import { Direction } from "../../../common/icons/types"; +import { Button } from "../../../common/v3/Button"; +import { actions } from "../../actions"; import { trackingEvents } from "../../tracking"; import { DigmathonInsightCard } from "../DigmathonInsightCard"; +import { getProgressEmailLink } from "../getProgressEmailLink"; import * as s from "./styles"; import { ProgressViewProps } from "./types"; -export const ProgressView = ({ data, foundIssuesCount }: ProgressViewProps) => { +const DIGMATHON_URL = "https://www.digma.ai/digmathon"; +const DIGMATHON_LEADERBOARD_URL = "https://www.digma.ai/digmathon/#leaderboard"; + +export const ProgressView = ({ data }: ProgressViewProps) => { + const config = useContext(ConfigContext); useEffect(() => { sendTrackingEvent(trackingEvents.DIGMATHON_PROGRESS_VIEWED); }, []); + const handleFindOutMoreButtonClick = () => { + sendUserActionTrackingEvent( + trackingEvents.DIGMATHON_FIND_OUT_MORE_BUTTON_CLICKED + ); + openURLInDefaultBrowser(DIGMATHON_URL); + }; + + const handleUpdateProgressButtonClick = () => { + sendUserActionTrackingEvent( + trackingEvents.DIGMATHON_UPDATE_PROGRESS_BUTTON_CLICKED + ); + const anchorElement = document.createElement("a"); + anchorElement.href = getProgressEmailLink(data.insights, config); + anchorElement.click(); + anchorElement.remove(); + + window.sendMessageToDigma({ + action: actions.UPDATE_DIGMATHON_PROGRESS_DATA + }); + }; + + const handleDigmathonLeaderboard = () => { + sendUserActionTrackingEvent( + trackingEvents.DIGMATHON_LEADERBOARD_BUTTON_CLICKED + ); + openURLInDefaultBrowser(DIGMATHON_LEADERBOARD_URL); + }; + + const foundIssuesCount = data.insights.filter((x) => + isString(x.foundAt) + ).length; + + const isNewProgressDataAvailable = + (data.insights.length > 0 && data.lastUpdatedByUserAt === null) || + data.insights.some( + (x) => + isString(x.foundAt) && + isString(data.lastUpdatedByUserAt) && + new Date(x.foundAt).valueOf() >= + new Date(data.lastUpdatedByUserAt).valueOf() + ); + if (foundIssuesCount === 0) { return ( - + Start Digmathon @@ -22,6 +79,10 @@ export const ProgressView = ({ data, foundIssuesCount }: ProgressViewProps) => { issues. Check back here to see your progress! +