diff --git a/.vscode/settings.json b/.vscode/settings.json
index 8dce37f62..ef16de1a5 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -12,6 +12,7 @@
"digmathon",
"digmo",
"dont",
+ "drilldowns",
"hotspot",
"leaderboard",
"precommit",
diff --git a/public/images/promotion/early-access/collapsedContainerBackground.svg b/public/images/promotion/early-access/collapsedContainerBackground.svg
new file mode 100644
index 000000000..e16c8423b
--- /dev/null
+++ b/public/images/promotion/early-access/collapsedContainerBackground.svg
@@ -0,0 +1,12 @@
+
diff --git a/public/images/promotion/early-access/promotionLogo.svg b/public/images/promotion/early-access/promotionLogo.svg
new file mode 100644
index 000000000..d276c21fe
--- /dev/null
+++ b/public/images/promotion/early-access/promotionLogo.svg
@@ -0,0 +1,105 @@
+
diff --git a/public/images/promotion/early-access/registrationPromoLogo.svg b/public/images/promotion/early-access/registrationPromoLogo.svg
new file mode 100644
index 000000000..dfaaf5c8c
--- /dev/null
+++ b/public/images/promotion/early-access/registrationPromoLogo.svg
@@ -0,0 +1,110 @@
+
diff --git a/public/images/promotion/early-access/registrationPromoSuccess_dark.svg b/public/images/promotion/early-access/registrationPromoSuccess_dark.svg
new file mode 100644
index 000000000..fd97848ad
--- /dev/null
+++ b/public/images/promotion/early-access/registrationPromoSuccess_dark.svg
@@ -0,0 +1,32 @@
+
diff --git a/public/images/promotion/early-access/registrationPromoSuccess_light.svg b/public/images/promotion/early-access/registrationPromoSuccess_light.svg
new file mode 100644
index 000000000..0fea2dc33
--- /dev/null
+++ b/public/images/promotion/early-access/registrationPromoSuccess_light.svg
@@ -0,0 +1,32 @@
+
diff --git a/public/images/promotion/collapsedContainerBackground.svg b/public/images/promotion/udemy/collapsedContainerBackground.svg
similarity index 100%
rename from public/images/promotion/collapsedContainerBackground.svg
rename to public/images/promotion/udemy/collapsedContainerBackground.svg
diff --git a/public/images/promotion/collapsedContainerEllipseShadow.svg b/public/images/promotion/udemy/collapsedContainerEllipseShadow.svg
similarity index 100%
rename from public/images/promotion/collapsedContainerEllipseShadow.svg
rename to public/images/promotion/udemy/collapsedContainerEllipseShadow.svg
diff --git a/public/images/promotion/promotionLogo.svg b/public/images/promotion/udemy/promotionLogo.svg
similarity index 100%
rename from public/images/promotion/promotionLogo.svg
rename to public/images/promotion/udemy/promotionLogo.svg
diff --git a/public/images/promotion/promotionLogoWithShadow.svg b/public/images/promotion/udemy/promotionLogoWithShadow.svg
similarity index 100%
rename from public/images/promotion/promotionLogoWithShadow.svg
rename to public/images/promotion/udemy/promotionLogoWithShadow.svg
diff --git a/public/images/promotion/registrationPromoLogo_dark.svg b/public/images/promotion/udemy/registrationPromoLogo_dark.svg
similarity index 100%
rename from public/images/promotion/registrationPromoLogo_dark.svg
rename to public/images/promotion/udemy/registrationPromoLogo_dark.svg
diff --git a/public/images/promotion/registrationPromoLogo_light.svg b/public/images/promotion/udemy/registrationPromoLogo_light.svg
similarity index 100%
rename from public/images/promotion/registrationPromoLogo_light.svg
rename to public/images/promotion/udemy/registrationPromoLogo_light.svg
diff --git a/public/images/promotion/registrationPromoSuccess_dark.svg b/public/images/promotion/udemy/registrationPromoSuccess_dark.svg
similarity index 100%
rename from public/images/promotion/registrationPromoSuccess_dark.svg
rename to public/images/promotion/udemy/registrationPromoSuccess_dark.svg
diff --git a/public/images/promotion/registrationPromoSuccess_light.svg b/public/images/promotion/udemy/registrationPromoSuccess_light.svg
similarity index 100%
rename from public/images/promotion/registrationPromoSuccess_light.svg
rename to public/images/promotion/udemy/registrationPromoSuccess_light.svg
diff --git a/src/components/Insights/InsightsCatalog/PromotionCard/index.tsx b/src/components/Insights/InsightsCatalog/PromotionCard/index.tsx
deleted file mode 100644
index dcedab471..000000000
--- a/src/components/Insights/InsightsCatalog/PromotionCard/index.tsx
+++ /dev/null
@@ -1,92 +0,0 @@
-import { useState } from "react";
-import { sendUserActionTrackingEvent } from "../../../../utils/actions/sendUserActionTrackingEvent";
-import { Link } from "../../../common/Link";
-import { CrossIcon } from "../../../common/icons/CrossIcon";
-import { trackingEvents } from "../../tracking";
-import { PromotionTag } from "./PromotionTag";
-import * as s from "./styles";
-import { PromotionCardProps } from "./types";
-
-export const PromotionCard = ({ onAccept, onDiscard }: PromotionCardProps) => {
- const [expanded, setExpanded] = useState(false);
-
- const handleDontShowButtonClick = () => {
- onDiscard();
- };
-
- const handleAccessCourseButtonClick = () => {
- onAccept();
- };
-
- const handleCollapseClick = () => {
- sendUserActionTrackingEvent(
- trackingEvents.PROMOTION_CLOSE_EXPANDED_VIEW_BUTTON_CLICKED
- );
- setExpanded(false);
- };
-
- const handleExpandClick = () => {
- sendUserActionTrackingEvent(
- trackingEvents.PROMOTION_OPEN_EXPANDED_VIEW_BUTTON_CLICKED
- );
- setExpanded(true);
- };
-
- if (!expanded) {
- return (
-
-
-
-
-
-
-
-
-
- Get our Udemy course FREE
-
- See more
-
-
- );
- }
-
- return (
-
-
-
-
-
-
-
-
-
-
-
-
- Learn how to get more out of Digma
- issues
-
-
-
-
-
-
-
-
-
-
- );
-};
diff --git a/src/components/Insights/InsightsCatalog/PromotionCard/types.ts b/src/components/Insights/InsightsCatalog/PromotionCard/types.ts
deleted file mode 100644
index 1ccc27bb3..000000000
--- a/src/components/Insights/InsightsCatalog/PromotionCard/types.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface ContainersProps {
- $expanded: boolean;
-}
-
-export interface PromotionCardProps {
- onDiscard: () => void;
- onAccept: () => void;
-}
diff --git a/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/EarlyAccessPromotionCard/EarlyAccessPromotionCard.stories.tsx b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/EarlyAccessPromotionCard/EarlyAccessPromotionCard.stories.tsx
new file mode 100644
index 000000000..9bcf827a9
--- /dev/null
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/EarlyAccessPromotionCard/EarlyAccessPromotionCard.stories.tsx
@@ -0,0 +1,21 @@
+import { Meta, StoryObj } from "@storybook/react";
+import { EarlyAccessPromotionCard } from ".";
+
+// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction
+const meta: Meta = {
+ title:
+ "Insights/InsightsCatalog/PromotionSection/PromotionCard/EarlyAccessPromotionCard",
+ component: EarlyAccessPromotionCard,
+ 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;
+
+export const Default: Story = {
+ args: {}
+};
diff --git a/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/EarlyAccessPromotionCard/index.tsx b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/EarlyAccessPromotionCard/index.tsx
new file mode 100644
index 000000000..0e2288112
--- /dev/null
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/EarlyAccessPromotionCard/index.tsx
@@ -0,0 +1,41 @@
+import { PromoText, PromoTextBold } from "../../../styles";
+import { Right } from "../styles";
+import * as s from "./styles";
+import { EarlyAccessPromotionCardProps } from "./types";
+
+export const EarlyAccessPromotionCard = ({
+ onAccept,
+ onDiscard
+}: EarlyAccessPromotionCardProps) => {
+ return (
+
+ Get Digma features early access
+
+ }
+ collapsedBackground={
+
+
+
+ }
+ background={
+
+ }
+ >
+
+ Register to get early
+ access to Digma
+ capabilities
+
+
+ );
+};
diff --git a/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/EarlyAccessPromotionCard/styles.ts b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/EarlyAccessPromotionCard/styles.ts
new file mode 100644
index 000000000..1635d8b67
--- /dev/null
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/EarlyAccessPromotionCard/styles.ts
@@ -0,0 +1,11 @@
+import styled from "styled-components";
+import { PromotionCard } from "..";
+import { Description } from "../styles";
+
+export const StyledDescription = styled(Description)`
+ height: 91px;
+`;
+
+export const StyledPromotionCard = styled(PromotionCard)`
+ padding: 16px;
+`;
diff --git a/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/EarlyAccessPromotionCard/types.ts b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/EarlyAccessPromotionCard/types.ts
new file mode 100644
index 000000000..c1a58c329
--- /dev/null
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/EarlyAccessPromotionCard/types.ts
@@ -0,0 +1,4 @@
+export interface EarlyAccessPromotionCardProps {
+ onDiscard: () => void;
+ onAccept: () => void;
+}
diff --git a/src/components/Insights/InsightsCatalog/PromotionCard/PromotionCard.stories.tsx b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/PromotionCard.stories.tsx
similarity index 88%
rename from src/components/Insights/InsightsCatalog/PromotionCard/PromotionCard.stories.tsx
rename to src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/PromotionCard.stories.tsx
index b56439e0d..fe426718a 100644
--- a/src/components/Insights/InsightsCatalog/PromotionCard/PromotionCard.stories.tsx
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/PromotionCard.stories.tsx
@@ -3,7 +3,7 @@ import { PromotionCard } from ".";
// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction
const meta: Meta = {
- title: "Insights/InsightsCatalog/PromotionCard",
+ title: "Insights/InsightsCatalog/PromotionSection/PromotionCard",
component: PromotionCard,
parameters: {
// More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout
diff --git a/src/components/Insights/InsightsCatalog/PromotionCard/PromotionTag/PromotionTag.stories.tsx b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/PromotionTag/PromotionTag.stories.tsx
similarity index 86%
rename from src/components/Insights/InsightsCatalog/PromotionCard/PromotionTag/PromotionTag.stories.tsx
rename to src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/PromotionTag/PromotionTag.stories.tsx
index 326b40af8..5fd3424ab 100644
--- a/src/components/Insights/InsightsCatalog/PromotionCard/PromotionTag/PromotionTag.stories.tsx
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/PromotionTag/PromotionTag.stories.tsx
@@ -3,7 +3,7 @@ import { PromotionTag } from ".";
// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction
const meta: Meta = {
- title: "Insights/InsightsCatalog/PromotionCard/PromotionTag",
+ title: "Insights/InsightsCatalog/PromotionSection/PromotionCard/PromotionTag",
component: PromotionTag,
parameters: {
// More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout
diff --git a/src/components/Insights/InsightsCatalog/PromotionCard/PromotionTag/index.tsx b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/PromotionTag/index.tsx
similarity index 77%
rename from src/components/Insights/InsightsCatalog/PromotionCard/PromotionTag/index.tsx
rename to src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/PromotionTag/index.tsx
index b337b0ef8..0b15b56a3 100644
--- a/src/components/Insights/InsightsCatalog/PromotionCard/PromotionTag/index.tsx
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/PromotionTag/index.tsx
@@ -1,4 +1,4 @@
-import { AffectIcon } from "../../../../common/icons/12px/AffectIcon";
+import { AffectIcon } from "../../../../../common/icons/12px/AffectIcon";
import * as s from "./styles";
export const PromotionTag = () => {
diff --git a/src/components/Insights/InsightsCatalog/PromotionCard/PromotionTag/styles.ts b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/PromotionTag/styles.ts
similarity index 88%
rename from src/components/Insights/InsightsCatalog/PromotionCard/PromotionTag/styles.ts
rename to src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/PromotionTag/styles.ts
index eb8770910..525d7b802 100644
--- a/src/components/Insights/InsightsCatalog/PromotionCard/PromotionTag/styles.ts
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/PromotionTag/styles.ts
@@ -1,5 +1,5 @@
import styled from "styled-components";
-import { caption2BoldTypography } from "../../../../common/App/typographies";
+import { caption2BoldTypography } from "../../../../../common/App/typographies";
export const Container = styled.div`
width: fit-content;
diff --git a/src/components/Insights/InsightsCatalog/PromotionCard/PromotionTag/types.ts b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/PromotionTag/types.ts
similarity index 100%
rename from src/components/Insights/InsightsCatalog/PromotionCard/PromotionTag/types.ts
rename to src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/PromotionTag/types.ts
diff --git a/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/UdemyCoursePromotionCard/UdemyCoursePromotionCard.stories.tsx b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/UdemyCoursePromotionCard/UdemyCoursePromotionCard.stories.tsx
new file mode 100644
index 000000000..0aabb1318
--- /dev/null
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/UdemyCoursePromotionCard/UdemyCoursePromotionCard.stories.tsx
@@ -0,0 +1,21 @@
+import { Meta, StoryObj } from "@storybook/react";
+import { UdemyCoursePromotionCard } from ".";
+
+// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction
+const meta: Meta = {
+ title:
+ "Insights/InsightsCatalog/PromotionSection/PromotionCard/UdemyCoursePromotionCard",
+ component: UdemyCoursePromotionCard,
+ 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;
+
+export const Default: Story = {
+ args: {}
+};
diff --git a/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/UdemyCoursePromotionCard/index.tsx b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/UdemyCoursePromotionCard/index.tsx
new file mode 100644
index 000000000..214b3816b
--- /dev/null
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/UdemyCoursePromotionCard/index.tsx
@@ -0,0 +1,55 @@
+import { PromotionCard } from "..";
+import { PromoText, PromoTextBold } from "../../../styles";
+import { PromotionTag } from "../PromotionTag";
+import { Centered, Description, Right } from "../styles";
+import * as s from "./styles";
+import { UdemyCoursePromotionCardProps } from "./types";
+
+const UdemyPromotionCollapsedBackground = () => (
+ <>
+
+
+
+
+
+
+ >
+);
+
+const UdemyPromotionBackground = () => (
+ <>
+
+
+
+
+ >
+);
+
+export const UdemyCoursePromotionCard = ({
+ onAccept,
+ onDiscard
+}: UdemyCoursePromotionCardProps) => {
+ return (
+
+ Get our Udemy course FREE
+
+ }
+ collapsedBackground={}
+ background={}
+ >
+
+
+ Learn how to get more out of Digma
+ issues
+
+
+ );
+};
diff --git a/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/UdemyCoursePromotionCard/styles.ts b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/UdemyCoursePromotionCard/styles.ts
new file mode 100644
index 000000000..09c95f1cc
--- /dev/null
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/UdemyCoursePromotionCard/styles.ts
@@ -0,0 +1,12 @@
+import styled, { keyframes } from "styled-components";
+
+const blurAnimation = keyframes`
+ 0% { opacity: 0; }
+ 100% { opacity: 1; }
+`;
+
+export const AnimatedPromotionBackground = styled.div`
+ position: absolute;
+ top: 0;
+ animation: 1s ${blurAnimation} linear infinite alternate;
+`;
diff --git a/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/UdemyCoursePromotionCard/types.ts b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/UdemyCoursePromotionCard/types.ts
new file mode 100644
index 000000000..10d504886
--- /dev/null
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/UdemyCoursePromotionCard/types.ts
@@ -0,0 +1,4 @@
+export interface UdemyCoursePromotionCardProps {
+ onDiscard: () => void;
+ onAccept: () => void;
+}
diff --git a/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/index.tsx b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/index.tsx
new file mode 100644
index 000000000..1560a56c6
--- /dev/null
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/index.tsx
@@ -0,0 +1,90 @@
+import { ForwardedRef, forwardRef, useState } from "react";
+import { sendUserActionTrackingEvent } from "../../../../../utils/actions/sendUserActionTrackingEvent";
+import { Link } from "../../../../common/Link";
+import { CrossIcon } from "../../../../common/icons/CrossIcon";
+import { trackingEvents } from "../../../tracking";
+import * as s from "./styles";
+import { PromotionCardProps } from "./types";
+
+const PromotionCardComponent = (
+ {
+ onAccept,
+ onDiscard,
+ acceptBtnText,
+ children,
+ title,
+ background,
+ collapsedBackground,
+ className,
+ scope
+ }: PromotionCardProps,
+ ref: ForwardedRef
+) => {
+ const [expanded, setExpanded] = useState(false);
+
+ const handleDontShowButtonClick = () => {
+ onDiscard();
+ };
+
+ const handleAcceptPromotionButtonClick = () => {
+ onAccept();
+ };
+
+ const handleCollapseClick = () => {
+ sendUserActionTrackingEvent(
+ trackingEvents.PROMOTION_CLOSE_EXPANDED_VIEW_BUTTON_CLICKED,
+ { scope }
+ );
+ setExpanded(false);
+ };
+
+ const handleExpandClick = () => {
+ sendUserActionTrackingEvent(
+ trackingEvents.PROMOTION_OPEN_EXPANDED_VIEW_BUTTON_CLICKED,
+ { scope }
+ );
+ setExpanded(true);
+ };
+
+ if (!expanded) {
+ return (
+
+ {collapsedBackground}
+
+ {title}
+ See more
+
+
+ );
+ }
+
+ return (
+
+ {background}
+
+
+ {children}
+
+
+
+
+
+
+
+
+ );
+};
+
+export const PromotionCard = forwardRef(PromotionCardComponent);
diff --git a/src/components/Insights/InsightsCatalog/PromotionCard/styles.ts b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/styles.ts
similarity index 79%
rename from src/components/Insights/InsightsCatalog/PromotionCard/styles.ts
rename to src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/styles.ts
index 524f5fce0..6ca41acb1 100644
--- a/src/components/Insights/InsightsCatalog/PromotionCard/styles.ts
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/styles.ts
@@ -1,9 +1,7 @@
import styled, { keyframes } from "styled-components";
-import {
- bodySemiboldTypography,
- subheadingSemiboldTypography
-} from "../../../common/App/typographies";
-import { Button } from "../../../common/v3/Button";
+import { subheadingSemiboldTypography } from "../../../../common/App/typographies";
+import { Button } from "../../../../common/v3/Button";
+import { NewIconButton } from "../../../../common/v3/NewIconButton";
export const CollapsedContainer = styled.div`
display: flex;
@@ -17,16 +15,7 @@ export const CollapsedContainer = styled.div`
position: relative;
`;
-export const PromoText = styled.span`
- ${bodySemiboldTypography}
-`;
-
-export const PromoTextBold = styled.span`
- ${bodySemiboldTypography};
- color: ${({ theme }) => theme.colors.v3.text.link};
-`;
-
-export const CrossButton = styled(Button)`
+export const CrossButton = styled(NewIconButton)`
padding: 0;
position: absolute;
right: 16px;
@@ -117,17 +106,17 @@ export const Holder = styled.div`
width: 100%;
`;
+export const CollapsedHolder = styled(Holder)`
+ display: flex;
+ justify-content: space-between;
+`;
+
export const Background = styled.div`
position: absolute;
top: 0;
height: 100%;
`;
-export const CollapsedHolder = styled(Holder)`
- display: flex;
- justify-content: space-between;
-`;
-
export const Right = styled(Background)`
right: 0;
overflow: hidden;
@@ -138,14 +127,3 @@ export const Centered = styled(Background)`
position: absolute;
overflow: hidden;
`;
-
-const blurAnimation = keyframes`
- 0% { opacity: 0; }
- 100% { opacity: 1; }
-`;
-
-export const AnimatedPromotionBackground = styled.div`
- position: absolute;
- top: 0;
- animation: 1s ${blurAnimation} linear infinite alternate;
-`;
diff --git a/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/types.ts b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/types.ts
new file mode 100644
index 000000000..04708b103
--- /dev/null
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/PromotionCard/types.ts
@@ -0,0 +1,17 @@
+import { ReactNode } from "react";
+
+export interface ContainersProps {
+ $expanded: boolean;
+}
+
+export interface PromotionCardProps {
+ onDiscard: () => void;
+ onAccept: () => void;
+ acceptBtnText: string;
+ children: ReactNode;
+ title: ReactNode;
+ background: ReactNode;
+ collapsedBackground: ReactNode;
+ className?: string;
+ scope: string;
+}
diff --git a/src/components/Insights/InsightsCatalog/PromotionSection/Promotions/EarlyAccessPromotion/index.tsx b/src/components/Insights/InsightsCatalog/PromotionSection/Promotions/EarlyAccessPromotion/index.tsx
new file mode 100644
index 000000000..61e7fb91e
--- /dev/null
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/Promotions/EarlyAccessPromotion/index.tsx
@@ -0,0 +1,109 @@
+import { useState } from "react";
+import { createPortal } from "react-dom";
+import { sendUserActionTrackingEvent } from "../../../../../../utils/actions/sendUserActionTrackingEvent";
+import { CancelConfirmation } from "../../../../../common/CancelConfirmation";
+import { MAIN_CONTAINER_ID } from "../../../../../Main";
+import { EarlyAccessRegistrationCard } from "../../../../../Main/RegistrationCard/EarlyAccessRegistrationCard";
+import { MainOverlay } from "../../../../../Main/styles";
+import { trackingEvents as mainTrackingEvents } from "../../../../../Main/tracking";
+import { EarlyAccessPromotionCard } from "../../PromotionCard/EarlyAccessPromotionCard";
+import { PromotionProps } from "../types";
+
+export const EarlyAccessPromotion = ({
+ onDiscard,
+ onAccept,
+ isVisible
+}: PromotionProps) => {
+ const [showDiscardConfirmation, setShowDiscardConfirmation] = useState(false);
+ const [showRegistration, setShowRegistration] = useState(false);
+
+ const mainContainer = document.getElementById(MAIN_CONTAINER_ID);
+
+ const handleRegistrationComplete = () => {
+ sendUserActionTrackingEvent(
+ mainTrackingEvents.EARLY_ACCESS_PROMOTION_REGISTRATION_FORM_SUBMITTED
+ );
+ onAccept();
+ };
+
+ const handleRegistrationClose = () => {
+ sendUserActionTrackingEvent(
+ mainTrackingEvents.EARLY_ACCESS_PROMOTION_REGISTRATION_CLOSE_BUTTON_CLICKED
+ );
+ setShowRegistration(false);
+ };
+
+ const handlePromotionAccept = () => {
+ sendUserActionTrackingEvent(
+ mainTrackingEvents.EARLY_ACCESS_PROMOTION_REGISTRATION_FORM_OPENED
+ );
+ setShowRegistration(true);
+ };
+
+ const handlePromotionDiscard = () => {
+ sendUserActionTrackingEvent(
+ mainTrackingEvents.EARLY_ACCESS_PROMOTION_DISCARDED
+ );
+ setShowDiscardConfirmation(true);
+ };
+
+ const handleConfirmationClose = () => {
+ sendUserActionTrackingEvent(
+ mainTrackingEvents.EARLY_ACCESS_PROMOTION_CANCEL_CONFIRMATION_CLOSE_CLICKED
+ );
+ setShowDiscardConfirmation(false);
+ };
+
+ const handleCancelConfirmationClose = () => {
+ sendUserActionTrackingEvent(
+ mainTrackingEvents.EARLY_ACCESS_PROMOTION_CANCEL_CONFIRMATION_CLOSE_CLICKED
+ );
+ setShowDiscardConfirmation(false);
+ };
+
+ const handleCancelConfirmationAccept = () => {
+ sendUserActionTrackingEvent(
+ mainTrackingEvents.EARLY_ACCESS_PROMOTION_CANCEL_CONFIRMATION_ACCEPT_CLICKED
+ );
+ onDiscard();
+ setShowDiscardConfirmation(false);
+ };
+
+ return (
+ <>
+ {isVisible && (
+
+ )}
+
+ {mainContainer &&
+ createPortal(
+ ,
+ mainContainer
+ )}
+
+ {mainContainer &&
+ showDiscardConfirmation &&
+ createPortal(
+
+
+ ,
+ mainContainer
+ )}
+ >
+ );
+};
diff --git a/src/components/Insights/InsightsCatalog/PromotionSection/Promotions/UdemyPromotion/index.tsx b/src/components/Insights/InsightsCatalog/PromotionSection/Promotions/UdemyPromotion/index.tsx
new file mode 100644
index 000000000..d5cd8d7fc
--- /dev/null
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/Promotions/UdemyPromotion/index.tsx
@@ -0,0 +1,105 @@
+import { useState } from "react";
+import { createPortal } from "react-dom";
+import { sendUserActionTrackingEvent } from "../../../../../../utils/actions/sendUserActionTrackingEvent";
+import { CancelConfirmation } from "../../../../../common/CancelConfirmation";
+import { MAIN_CONTAINER_ID } from "../../../../../Main";
+import { UdemyRegistrationCard } from "../../../../../Main/RegistrationCard/UdemyRegistrationCard";
+import { MainOverlay } from "../../../../../Main/styles";
+import { trackingEvents as mainTrackingEvents } from "../../../../../Main/tracking";
+import { UdemyCoursePromotionCard } from "../../PromotionCard/UdemyCoursePromotionCard";
+import { PromotionProps } from "../types";
+
+export const UdemyPromotion = ({
+ onDiscard,
+ onAccept,
+ isVisible
+}: PromotionProps) => {
+ const [showDiscardConfirmation, setShowDiscardConfirmation] = useState(false);
+ const [showRegistration, setShowRegistration] = useState(false);
+
+ const mainContainer = document.getElementById(MAIN_CONTAINER_ID);
+ const handleRegistrationComplete = () => {
+ sendUserActionTrackingEvent(
+ mainTrackingEvents.PROMOTION_REGISTRATION_FORM_SUBMITTED
+ );
+ onAccept();
+ };
+
+ const handleRegistrationClose = () => {
+ sendUserActionTrackingEvent(
+ mainTrackingEvents.PROMOTION_REGISTRATION_CLOSE_BUTTON_CLICKED
+ );
+ setShowRegistration(false);
+ };
+
+ const handlePromotionAccept = () => {
+ sendUserActionTrackingEvent(
+ mainTrackingEvents.PROMOTION_REGISTRATION_FORM_OPENED
+ );
+ setShowRegistration(true);
+ };
+
+ const handlePromotionDiscard = () => {
+ sendUserActionTrackingEvent(mainTrackingEvents.PROMOTION_DISCARDED);
+ setShowDiscardConfirmation(true);
+ };
+
+ const handleConfirmationClose = () => {
+ sendUserActionTrackingEvent(
+ mainTrackingEvents.PROMOTION_CANCEL_CONFIRMATION_CLOSE_CLICKED
+ );
+ setShowDiscardConfirmation(false);
+ };
+
+ const handleCancelConfirmationClose = () => {
+ sendUserActionTrackingEvent(
+ mainTrackingEvents.PROMOTION_CANCEL_CONFIRMATION_CLOSE_CLICKED
+ );
+ setShowDiscardConfirmation(false);
+ };
+
+ const handleCancelConfirmationAccept = () => {
+ sendUserActionTrackingEvent(
+ mainTrackingEvents.PROMOTION_CANCEL_CONFIRMATION_ACCEPT_CLICKED
+ );
+ onDiscard();
+ setShowDiscardConfirmation(false);
+ };
+ return (
+ <>
+ {isVisible && (
+
+ )}
+
+ {mainContainer &&
+ createPortal(
+ ,
+ mainContainer
+ )}
+
+ {mainContainer &&
+ showDiscardConfirmation &&
+ createPortal(
+
+
+ ,
+ mainContainer
+ )}
+ >
+ );
+};
diff --git a/src/components/Insights/InsightsCatalog/PromotionSection/Promotions/types.ts b/src/components/Insights/InsightsCatalog/PromotionSection/Promotions/types.ts
new file mode 100644
index 000000000..f6a140c56
--- /dev/null
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/Promotions/types.ts
@@ -0,0 +1,5 @@
+export interface PromotionProps {
+ onDiscard: () => void;
+ onAccept: () => void;
+ isVisible: boolean;
+}
diff --git a/src/components/Insights/InsightsCatalog/PromotionSection/index.tsx b/src/components/Insights/InsightsCatalog/PromotionSection/index.tsx
new file mode 100644
index 000000000..2efb9a3ed
--- /dev/null
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/index.tsx
@@ -0,0 +1,155 @@
+import { useEffect, useState } from "react";
+import { actions as globalActions } from "../../../../actions";
+import { dispatcher } from "../../../../dispatcher";
+import { usePersistence } from "../../../../hooks/usePersistence";
+import { PLUGIN_EVENTS } from "../../../../pluginEvents";
+import { SendPluginEventPayload } from "../../../../types";
+import { sendUserActionTrackingEvent } from "../../../../utils/actions/sendUserActionTrackingEvent";
+import { trackingEvents as mainTrackingEvents } from "../../../Main/tracking";
+import { ToolbarRow } from "../styles";
+import { EarlyAccessPromotion } from "./Promotions/EarlyAccessPromotion";
+import { UdemyPromotion } from "./Promotions/UdemyPromotion";
+import { EarlyAccessPromotionDetails, PromotionType } from "./types";
+
+const EARLY_ACCESS_PROMOTION_PERSISTENCE_KEY = "EARLY_ACCESS_PROMOTION";
+
+const PROMOTION_PERSISTENCE_KEY = "PROMOTION";
+const PROMOTION_COMPLETED_PERSISTENCE_KEY = "PROMOTION_COMPLETED";
+const PROMOTION_INTERVAL_DAYS = 30;
+const INTERVAL_BETWEEN_PROMOTIONS_DAYS = 1;
+
+const isPromotionEnabled = (dismissalDate: number | null | undefined) => {
+ return dateReachesInterval(PROMOTION_INTERVAL_DAYS, dismissalDate);
+};
+
+const dateReachesInterval = (
+ days: number,
+ dismissalDate: number | null | undefined
+) => {
+ const interval = days * 24 * 60 * 60 * 1000; // in milliseconds
+ return !dismissalDate || Math.abs(dismissalDate - Date.now()) > interval;
+};
+
+export const PromotionSection = () => {
+ const [showPromotion, setShowPromotion] = useState("udemy");
+
+ const [earlyAccessPromotionDetails, setEarlyAccessPromotionDetails] =
+ usePersistence(
+ EARLY_ACCESS_PROMOTION_PERSISTENCE_KEY,
+ "application"
+ );
+
+ const [udemyPromotionCompleted, setUdemyPromotionCompleted] =
+ usePersistence(PROMOTION_COMPLETED_PERSISTENCE_KEY, "application");
+ const [udemyDismissalDate, setUdemyDismissalDate] = usePersistence(
+ PROMOTION_PERSISTENCE_KEY,
+ "application"
+ );
+
+ useEffect(() => {
+ const handlePluginEvent = (data: unknown) => {
+ const { name } = data as SendPluginEventPayload;
+
+ if (name !== PLUGIN_EVENTS.SHOW_EARLY_ACCESS_PROMOTION) {
+ return;
+ }
+
+ if (earlyAccessPromotionDetails?.completionDate) {
+ return;
+ }
+
+ if (
+ earlyAccessPromotionDetails?.dismissalDate &&
+ !isPromotionEnabled(earlyAccessPromotionDetails.dismissalDate)
+ ) {
+ return;
+ }
+
+ setShowPromotion("early-access");
+ };
+
+ dispatcher.addActionListener(
+ globalActions.SEND_PLUGIN_EVENT,
+ handlePluginEvent
+ );
+
+ return () => {
+ dispatcher.removeActionListener(
+ globalActions.SEND_PLUGIN_EVENT,
+ handlePluginEvent
+ );
+ };
+ }, [
+ earlyAccessPromotionDetails?.completionDate,
+ earlyAccessPromotionDetails?.dismissalDate,
+ setShowPromotion
+ ]);
+
+ const handleUdemyRegistrationComplete = () => {
+ sendUserActionTrackingEvent(
+ mainTrackingEvents.PROMOTION_REGISTRATION_FORM_SUBMITTED,
+ { source: showPromotion }
+ );
+ setUdemyPromotionCompleted(true);
+ };
+
+ const handleEarlyAccessRegistrationComplete = () => {
+ sendUserActionTrackingEvent(
+ mainTrackingEvents.PROMOTION_REGISTRATION_FORM_SUBMITTED,
+ { source: showPromotion }
+ );
+ setEarlyAccessPromotionDetails({
+ ...earlyAccessPromotionDetails,
+ isCompleted: true,
+ completionDate: Date.now()
+ });
+ };
+
+ const handleCancelConfirmationAccept = () => {
+ sendUserActionTrackingEvent(
+ mainTrackingEvents.PROMOTION_CANCEL_CONFIRMATION_ACCEPT_CLICKED,
+ { source: showPromotion }
+ );
+
+ if (showPromotion === "udemy") {
+ setUdemyDismissalDate(Date.now());
+ } else if (showPromotion === "early-access") {
+ setEarlyAccessPromotionDetails({
+ isCompleted: false,
+ dismissalDate: Date.now()
+ });
+ }
+ };
+
+ const isUdemyPromotionVisible =
+ !udemyPromotionCompleted &&
+ isPromotionEnabled(udemyDismissalDate) &&
+ showPromotion === "udemy" &&
+ (!earlyAccessPromotionDetails?.isCompleted ||
+ (earlyAccessPromotionDetails.isCompleted &&
+ dateReachesInterval(
+ INTERVAL_BETWEEN_PROMOTIONS_DAYS,
+ earlyAccessPromotionDetails.completionDate
+ )));
+
+ const isEarlyAccessPromotionIsVisible =
+ !earlyAccessPromotionDetails?.isCompleted &&
+ showPromotion === "early-access" &&
+ isPromotionEnabled(earlyAccessPromotionDetails?.dismissalDate);
+
+ return (
+
+
+
+
+
+ );
+};
diff --git a/src/components/Insights/InsightsCatalog/PromotionSection/types.ts b/src/components/Insights/InsightsCatalog/PromotionSection/types.ts
new file mode 100644
index 000000000..c28c35717
--- /dev/null
+++ b/src/components/Insights/InsightsCatalog/PromotionSection/types.ts
@@ -0,0 +1,7 @@
+export type PromotionType = "udemy" | "early-access";
+
+export interface EarlyAccessPromotionDetails {
+ dismissalDate?: number;
+ isCompleted: boolean;
+ completionDate?: number;
+}
diff --git a/src/components/Insights/InsightsCatalog/index.tsx b/src/components/Insights/InsightsCatalog/index.tsx
index f2a70effc..849df8784 100644
--- a/src/components/Insights/InsightsCatalog/index.tsx
+++ b/src/components/Insights/InsightsCatalog/index.tsx
@@ -1,9 +1,7 @@
import { useEffect, useState } from "react";
-import { createPortal } from "react-dom";
import { useTheme } from "styled-components";
import { getFeatureFlagValue } from "../../../featureFlags";
import { useDebounce } from "../../../hooks/useDebounce";
-import { usePersistence } from "../../../hooks/usePersistence";
import { usePrevious } from "../../../hooks/usePrevious";
import { useConfigSelector } from "../../../store/config/useConfigSelector";
import { useInsightsSelector } from "../../../store/insights/useInsightsSelector";
@@ -13,11 +11,6 @@ import { isUndefined } from "../../../typeGuards/isUndefined";
import { FeatureFlag } from "../../../types";
import { sendUserActionTrackingEvent } from "../../../utils/actions/sendUserActionTrackingEvent";
import { formatUnit } from "../../../utils/formatUnit";
-import { MAIN_CONTAINER_ID } from "../../Main";
-import { RegistrationCard } from "../../Main/RegistrationCard";
-import { MainOverlay } from "../../Main/styles";
-import { trackingEvents as mainTrackingEvents } from "../../Main/tracking";
-import { CancelConfirmation } from "../../common/CancelConfirmation";
import { Pagination } from "../../common/Pagination";
import { SearchInput } from "../../common/SearchInput";
import { SortingSelector } from "../../common/SortingSelector";
@@ -36,7 +29,7 @@ import { SelectorEnvironment } from "./EnvironmentSelector/types";
import { FilterButton } from "./FilterButton";
import { FilterPanel } from "./FilterPanel";
import { InsightsPage } from "./InsightsPage";
-import { PromotionCard } from "./PromotionCard";
+import { PromotionSection } from "./PromotionSection";
import * as s from "./styles";
import {
InsightFilterType,
@@ -51,17 +44,6 @@ const PAGE_SIZE = 10;
const isShowUnreadOnly = (filters: InsightFilterType[]) =>
filters.length === 1 && filters[0] === "unread";
-const PROMOTION_PERSISTENCE_KEY = "PROMOTION";
-const PROMOTION_COMPLETED_PERSISTENCE_KEY = "PROMOTION_COMPLETED";
-
-const isPromotionEnabled = (dismissalDate: number | null | undefined) => {
- const PROMOTION_INTERVAL = 30 * 24 * 60 * 60 * 1000; // in milliseconds
-
- return (
- !dismissalDate || Math.abs(dismissalDate - Date.now()) > PROMOTION_INTERVAL
- );
-};
-
export const InsightsCatalog = ({
onJiraTicketCreate,
onRefresh
@@ -113,17 +95,8 @@ export const InsightsCatalog = ({
const previousIsMarkingAllAsReadInProgress = usePrevious(
isMarkingAllAsReadInProgress
);
- const [showRegistration, setShowRegistration] = useState(false);
- const [showDiscardConfirmation, setShowDiscardConfirmation] = useState(false);
const [isFiltersToolbarVisible, setIsFiltersToolbarVisible] = useState(false);
- const [dismissalDate, setDismissalDate] = usePersistence(
- PROMOTION_PERSISTENCE_KEY,
- "application"
- );
- const [promotionCompleted, setPromotionCompleted] = usePersistence(
- PROMOTION_COMPLETED_PERSISTENCE_KEY,
- "application"
- );
+
const isServicesFilterEnabled = !scopeSpanCodeObjectId;
const appliedFilterCount =
@@ -141,55 +114,8 @@ export const InsightsCatalog = ({
? insightStats?.spanEnvironments ?? []
: environments?.map((x) => ({ environment: x })) ?? [];
- const handleRegistrationComplete = () => {
- sendUserActionTrackingEvent(
- mainTrackingEvents.PROMOTION_REGISTRATION_FORM_SUBMITTED
- );
- setPromotionCompleted(true);
- };
-
- const handleRegistrationClose = () => {
- sendUserActionTrackingEvent(
- mainTrackingEvents.PROMOTION_REGISTRATION_CLOSE_BUTTON_CLICKED
- );
- setShowRegistration(false);
- };
-
- const handleCancelConfirmationClose = () => {
- sendUserActionTrackingEvent(
- mainTrackingEvents.PROMOTION_CANCEL_CONFIRMATION_CLOSE_CLICKED
- );
- setShowDiscardConfirmation(false);
- };
-
- const handleCancelConfirmationAccept = () => {
- sendUserActionTrackingEvent(
- mainTrackingEvents.PROMOTION_CANCEL_CONFIRMATION_ACCEPT_CLICKED
- );
- setDismissalDate(Date.now());
- setShowDiscardConfirmation(false);
- };
-
- const handleConfirmationClose = () => {
- setShowDiscardConfirmation(false);
- };
-
- const handlePromotionAccept = () => {
- sendUserActionTrackingEvent(
- mainTrackingEvents.PROMOTION_REGISTRATION_FORM_OPENED
- );
- setShowRegistration(true);
- };
-
- const handlePromotionDiscard = () => {
- sendUserActionTrackingEvent(mainTrackingEvents.PROMOTION_DISCARDED);
- setShowDiscardConfirmation(true);
- };
-
const isIssuesView = insightViewType === "Issues";
- const isPromotionVisible =
- isIssuesView && !promotionCompleted && isPromotionEnabled(dismissalDate);
const isDismissalViewModeButtonVisible =
isIssuesView && (isUndefined(dismissedCount) || dismissedCount > 0); // isUndefined - check for backward compatibility, always show when BE does not return this counter
const isMarkingAsReadOptionsEnabled =
@@ -206,7 +132,6 @@ export const InsightsCatalog = ({
backendInfo,
FeatureFlag.ARE_ISSUES_FILTERS_ENABLED
);
- const mainContainer = document.getElementById(MAIN_CONTAINER_ID);
const handleRefreshButtonClick = () => {
sendUserActionTrackingEvent(trackingEvents.REFRESH_BUTTON_CLICKED, {
@@ -331,14 +256,7 @@ export const InsightsCatalog = ({
>
)}
- {isPromotionVisible && (
-
-
-
- )}
+ {isIssuesView && }
{mode === ViewMode.All ? (
<>
{filters.length === 1 && (
@@ -429,31 +347,6 @@ export const InsightsCatalog = ({
/>
)}
- {mainContainer &&
- showDiscardConfirmation &&
- createPortal(
-
-
- ,
- mainContainer
- )}
- {mainContainer &&
- createPortal(
- ,
- mainContainer
- )}
>
);
};
diff --git a/src/components/Insights/InsightsCatalog/styles.ts b/src/components/Insights/InsightsCatalog/styles.ts
index d710c9c8b..ff3fb3a27 100644
--- a/src/components/Insights/InsightsCatalog/styles.ts
+++ b/src/components/Insights/InsightsCatalog/styles.ts
@@ -1,6 +1,8 @@
import styled from "styled-components";
import {
+ bodySemiboldTypography,
caption1RegularTypography,
+ subheadingSemiboldTypography,
subscriptMediumTypography,
subscriptRegularTypography
} from "../../common/App/typographies";
@@ -116,3 +118,21 @@ export const ToolbarButtonsContainer = styled.div`
align-items: center;
margin-left: auto;
`;
+
+export const Description = styled.span`
+ ${subheadingSemiboldTypography}
+
+ display:flex;
+ flex-direction: column;
+ width: 167px;
+ color: ${({ theme }) => theme.colors.v3.text.primary};
+`;
+
+export const PromoText = styled.span`
+ ${bodySemiboldTypography}
+`;
+
+export const PromoTextBold = styled.span`
+ ${bodySemiboldTypography};
+ color: ${({ theme }) => theme.colors.v3.text.link};
+`;
diff --git a/src/components/Main/RegistrationCard/EarlyAccessRegistrationCard/EarlyAccessRegistrationCard.stories.tsx b/src/components/Main/RegistrationCard/EarlyAccessRegistrationCard/EarlyAccessRegistrationCard.stories.tsx
new file mode 100644
index 000000000..5532a0430
--- /dev/null
+++ b/src/components/Main/RegistrationCard/EarlyAccessRegistrationCard/EarlyAccessRegistrationCard.stories.tsx
@@ -0,0 +1,18 @@
+import { Meta, StoryObj } from "@storybook/react";
+import { EarlyAccessRegistrationCard } from ".";
+
+// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction
+const meta: Meta = {
+ title: "Main/RegistrationCard/EarlyAccessRegistrationCard",
+ component: EarlyAccessRegistrationCard,
+ 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;
+
+export const Default: Story = {};
diff --git a/src/components/Main/RegistrationCard/EarlyAccessRegistrationCard/index.tsx b/src/components/Main/RegistrationCard/EarlyAccessRegistrationCard/index.tsx
new file mode 100644
index 000000000..f100e1372
--- /dev/null
+++ b/src/components/Main/RegistrationCard/EarlyAccessRegistrationCard/index.tsx
@@ -0,0 +1,36 @@
+import { RegistrationCard } from "..";
+import { SuccessRegistrationImage } from "../Images/SuccessRegistrationImage";
+import * as s from "./styles";
+import { EarlyAccessRegistrationCardPros } from "./types";
+
+export const EarlyAccessRegistrationCard = ({
+ onClose,
+ onComplete,
+ className,
+ show
+}: EarlyAccessRegistrationCardPros) => {
+ return (
+
+ }
+ icon={
+
+ }
+ details={
+
+ Access to Digma exclusive features
+ We have launched an innovator program to give you early access to new
+ features, issues detection, UI drilldowns, and more. Sign up before to
+ get into the list.
+
+ }
+ />
+ );
+};
diff --git a/src/components/Main/RegistrationCard/EarlyAccessRegistrationCard/styles.ts b/src/components/Main/RegistrationCard/EarlyAccessRegistrationCard/styles.ts
new file mode 100644
index 000000000..5bfc281d7
--- /dev/null
+++ b/src/components/Main/RegistrationCard/EarlyAccessRegistrationCard/styles.ts
@@ -0,0 +1,20 @@
+import styled from "styled-components";
+import {
+ subheadingSemiboldTypography,
+ subscriptRegularTypography
+} from "../../../common/App/typographies";
+
+export const Description = styled.div`
+ ${subscriptRegularTypography}
+
+ color: ${({ theme }) => theme.colors.v3.text.secondary};
+ text-align: center;
+ display: flex;
+ flex-direction: column;
+`;
+
+export const Title = styled.div`
+ ${subheadingSemiboldTypography}
+ color: ${({ theme }) => theme.colors.v3.text.primary};
+ padding: 12px 0;
+`;
diff --git a/src/components/Main/RegistrationCard/EarlyAccessRegistrationCard/types.ts b/src/components/Main/RegistrationCard/EarlyAccessRegistrationCard/types.ts
new file mode 100644
index 000000000..2938017e3
--- /dev/null
+++ b/src/components/Main/RegistrationCard/EarlyAccessRegistrationCard/types.ts
@@ -0,0 +1,6 @@
+export interface EarlyAccessRegistrationCardPros {
+ onClose: () => void;
+ onComplete: () => void;
+ className?: string;
+ show?: boolean;
+}
diff --git a/src/components/Main/RegistrationCard/Images/SuccessRegistrationImage.tsx b/src/components/Main/RegistrationCard/Images/SuccessRegistrationImage.tsx
deleted file mode 100644
index 0a3588f2e..000000000
--- a/src/components/Main/RegistrationCard/Images/SuccessRegistrationImage.tsx
+++ /dev/null
@@ -1,11 +0,0 @@
-import { useTheme } from "styled-components";
-import { getThemeKind } from "../../../common/App/styles";
-
-export const SuccessRegistrationImage = () => {
- const theme = useTheme();
- const themeKind = getThemeKind(theme);
-
- return (
-
- );
-};
diff --git a/src/components/Main/RegistrationCard/Images/SuccessRegistrationImage/index.tsx b/src/components/Main/RegistrationCard/Images/SuccessRegistrationImage/index.tsx
new file mode 100644
index 000000000..11f3c2d2d
--- /dev/null
+++ b/src/components/Main/RegistrationCard/Images/SuccessRegistrationImage/index.tsx
@@ -0,0 +1,12 @@
+import { useTheme } from "styled-components";
+import { getThemeKind } from "../../../../common/App/styles";
+import { SuccessRegistrationImageProps } from "./types";
+
+export const SuccessRegistrationImage = ({
+ basePath
+}: SuccessRegistrationImageProps) => {
+ const theme = useTheme();
+ const themeKind = getThemeKind(theme);
+
+ return
;
+};
diff --git a/src/components/Main/RegistrationCard/Images/SuccessRegistrationImage/types.ts b/src/components/Main/RegistrationCard/Images/SuccessRegistrationImage/types.ts
new file mode 100644
index 000000000..966bc5e7e
--- /dev/null
+++ b/src/components/Main/RegistrationCard/Images/SuccessRegistrationImage/types.ts
@@ -0,0 +1,3 @@
+export interface SuccessRegistrationImageProps {
+ basePath: string;
+}
diff --git a/src/components/Main/RegistrationCard/SuccessRegistration/index.tsx b/src/components/Main/RegistrationCard/SuccessRegistration/index.tsx
index ab1f16c01..d58cf65af 100644
--- a/src/components/Main/RegistrationCard/SuccessRegistration/index.tsx
+++ b/src/components/Main/RegistrationCard/SuccessRegistration/index.tsx
@@ -1,10 +1,10 @@
-import { SuccessRegistrationImage } from "../Images/SuccessRegistrationImage";
import * as s from "./styles";
+import { SuccessRegistrationProps } from "./types";
-export const SuccessRegistration = () => {
+export const SuccessRegistration = ({ image }: SuccessRegistrationProps) => {
return (
-
+ {image}
Email sent!
diff --git a/src/components/Main/RegistrationCard/SuccessRegistration/types.ts b/src/components/Main/RegistrationCard/SuccessRegistration/types.ts
new file mode 100644
index 000000000..cbb32d681
--- /dev/null
+++ b/src/components/Main/RegistrationCard/SuccessRegistration/types.ts
@@ -0,0 +1,5 @@
+import { ReactNode } from "react";
+
+export interface SuccessRegistrationProps {
+ image: ReactNode;
+}
diff --git a/src/components/Main/RegistrationCard/Images/RegistrationPromoImage.tsx b/src/components/Main/RegistrationCard/UdemyRegistrationCard/Images/RegistrationPromoImage.tsx
similarity index 54%
rename from src/components/Main/RegistrationCard/Images/RegistrationPromoImage.tsx
rename to src/components/Main/RegistrationCard/UdemyRegistrationCard/Images/RegistrationPromoImage.tsx
index 186d34fa8..7556dc18b 100644
--- a/src/components/Main/RegistrationCard/Images/RegistrationPromoImage.tsx
+++ b/src/components/Main/RegistrationCard/UdemyRegistrationCard/Images/RegistrationPromoImage.tsx
@@ -1,11 +1,13 @@
import { useTheme } from "styled-components";
-import { getThemeKind } from "../../../common/App/styles";
+import { getThemeKind } from "../../../../common/App/styles";
export const RegistrationPromoImage = () => {
const theme = useTheme();
const themeKind = getThemeKind(theme);
return (
-
+
);
};
diff --git a/src/components/Main/RegistrationCard/UdemyRegistrationCard/UdemyRegistrationCard.stories.tsx b/src/components/Main/RegistrationCard/UdemyRegistrationCard/UdemyRegistrationCard.stories.tsx
new file mode 100644
index 000000000..e7983856a
--- /dev/null
+++ b/src/components/Main/RegistrationCard/UdemyRegistrationCard/UdemyRegistrationCard.stories.tsx
@@ -0,0 +1,18 @@
+import { Meta, StoryObj } from "@storybook/react";
+import { UdemyRegistrationCard } from ".";
+
+// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction
+const meta: Meta = {
+ title: "Main/RegistrationCard/UdemyRegistrationCard",
+ component: UdemyRegistrationCard,
+ 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;
+
+export const Default: Story = {};
diff --git a/src/components/Main/RegistrationCard/UdemyRegistrationCard/index.tsx b/src/components/Main/RegistrationCard/UdemyRegistrationCard/index.tsx
new file mode 100644
index 000000000..c550797c7
--- /dev/null
+++ b/src/components/Main/RegistrationCard/UdemyRegistrationCard/index.tsx
@@ -0,0 +1,32 @@
+import { RegistrationCard } from "..";
+import { SuccessRegistrationImage } from "../Images/SuccessRegistrationImage";
+import { RegistrationPromoImage } from "./Images/RegistrationPromoImage";
+import * as s from "./styles";
+import { UdemyRegistrationCardProps } from "./types";
+
+export const UdemyRegistrationCard = ({
+ onClose,
+ onComplete,
+ className,
+ show
+}: UdemyRegistrationCardProps) => {
+ return (
+
+ }
+ scope={"promotion"}
+ icon={}
+ details={
+
+ Enter your email address below, and we will send you instructions to
+ access the exclusive Digma course on Udemy
+
+ }
+ />
+ );
+};
diff --git a/src/components/Main/RegistrationCard/UdemyRegistrationCard/styles.ts b/src/components/Main/RegistrationCard/UdemyRegistrationCard/styles.ts
new file mode 100644
index 000000000..afcd3021b
--- /dev/null
+++ b/src/components/Main/RegistrationCard/UdemyRegistrationCard/styles.ts
@@ -0,0 +1,9 @@
+import styled from "styled-components";
+import { subscriptRegularTypography } from "../../../common/App/typographies";
+
+export const Description = styled.div`
+ ${subscriptRegularTypography}
+
+ color: ${({ theme }) => theme.colors.v3.text.secondary};
+ text-align: center;
+`;
diff --git a/src/components/Main/RegistrationCard/UdemyRegistrationCard/types.ts b/src/components/Main/RegistrationCard/UdemyRegistrationCard/types.ts
new file mode 100644
index 000000000..3b194b686
--- /dev/null
+++ b/src/components/Main/RegistrationCard/UdemyRegistrationCard/types.ts
@@ -0,0 +1,6 @@
+export interface UdemyRegistrationCardProps {
+ onClose: () => void;
+ onComplete: () => void;
+ className?: string;
+ show?: boolean;
+}
diff --git a/src/components/Main/RegistrationCard/index.tsx b/src/components/Main/RegistrationCard/index.tsx
index e78b38d09..2cfad3563 100644
--- a/src/components/Main/RegistrationCard/index.tsx
+++ b/src/components/Main/RegistrationCard/index.tsx
@@ -6,9 +6,8 @@ import { sendUserActionTrackingEvent } from "../../../utils/actions/sendUserActi
import { SlackLogoIcon } from "../../common/icons/16px/SlackLogoIcon";
import { CrossIcon } from "../../common/icons/CrossIcon";
import { trackingEvents } from "../tracking";
-import { RegistrationPromoImage } from "./Images/RegistrationPromoImage";
-import { SuccessRegistration } from "./SuccessRegistration";
import * as s from "./styles";
+import { SuccessRegistration } from "./SuccessRegistration";
import { RegistrationCardProps } from "./types";
const TRANSITION_CLASS_NAME = "registration-card";
@@ -18,7 +17,12 @@ export const RegistrationCard = ({
onClose,
onComplete,
className,
- show
+ show,
+ icon,
+ details,
+ submitBtnText,
+ successLogo,
+ scope
}: RegistrationCardProps) => {
const [showOverlay, setShowOverlay] = useState(false);
const [isFormCompleted, setIsFormCompleted] = useState(false);
@@ -71,30 +75,26 @@ export const RegistrationCard = ({
ref={registrationCardRef}
>
{!isFormCompleted ? (
<>
-
-
-
+ {icon}
-
- Enter your email address below, and we will send you
- instructions to access the exclusive Digma course on Udemy
-
+ {details}
>
) : (
-
+
)}
diff --git a/src/components/Main/RegistrationCard/styles.ts b/src/components/Main/RegistrationCard/styles.ts
index 6a3ed2445..94b459f57 100644
--- a/src/components/Main/RegistrationCard/styles.ts
+++ b/src/components/Main/RegistrationCard/styles.ts
@@ -1,13 +1,10 @@
import styled, { css } from "styled-components";
import { LAYERS } from "../../common/App/styles";
-import {
- bodyMediumTypography,
- subscriptRegularTypography
-} from "../../common/App/typographies";
+import { bodyMediumTypography } from "../../common/App/typographies";
import { Overlay } from "../../common/Overlay";
import { RegisterForm } from "../../common/RegisterForm";
-import { Button } from "../../common/v3/Button";
import { Link } from "../../common/v3/Link";
+import { NewIconButton } from "../../common/v3/NewIconButton";
import { AnimatedRegistrationCardProps, StyledOverlayProps } from "./types";
export const Container = styled.div`
@@ -43,20 +40,13 @@ export const Container = styled.div`
}};
`;
-export const CrossButton = styled(Button)`
+export const CrossButton = styled(NewIconButton)`
padding: 0;
position: absolute;
top: 16px;
right: 9px;
`;
-export const Description = styled.div`
- ${subscriptRegularTypography}
-
- color: ${({ theme }) => theme.colors.v3.text.secondary};
- text-align: center;
-`;
-
export const FormContainer = styled.div`
max-width: 308px;
display: flex;
diff --git a/src/components/Main/RegistrationCard/types.ts b/src/components/Main/RegistrationCard/types.ts
index be173c6bc..757b117ce 100644
--- a/src/components/Main/RegistrationCard/types.ts
+++ b/src/components/Main/RegistrationCard/types.ts
@@ -1,8 +1,15 @@
+import { ReactNode } from "react";
+
export interface RegistrationCardProps {
onClose: () => void;
onComplete: () => void;
className?: string;
show?: boolean;
+ icon: ReactNode;
+ details: ReactNode;
+ submitBtnText?: string;
+ successLogo: ReactNode;
+ scope: string;
}
export interface AnimatedRegistrationCardProps {
diff --git a/src/components/Main/tracking.ts b/src/components/Main/tracking.ts
index bad164eef..9460b1692 100644
--- a/src/components/Main/tracking.ts
+++ b/src/components/Main/tracking.ts
@@ -20,7 +20,19 @@ export const trackingEvents = addPrefix(
LOGIN_SCREEN_VIEWED: "login screen viewed",
SCOPE_BAR_EXPAND_BUTTON_CLICKED: "span info expand button clicked",
SCOPE_BAR_COLLAPSE_BUTTON_CLICKED: "scope bar collapse button clicked",
- SPAN_INFO_COLLAPSE_BUTTON_CLICKED: "span info collapse button clicked"
+ SPAN_INFO_COLLAPSE_BUTTON_CLICKED: "span info collapse button clicked",
+
+ EARLY_ACCESS_PROMOTION_REGISTRATION_FORM_SUBMITTED:
+ "early access promotion registration form submitted",
+ EARLY_ACCESS_PROMOTION_REGISTRATION_CLOSE_BUTTON_CLICKED:
+ "early access promotion registration close button clicked",
+ EARLY_ACCESS_PROMOTION_REGISTRATION_FORM_OPENED:
+ "early access promotion registration form opened",
+ EARLY_ACCESS_PROMOTION_DISCARDED: "early access promotion discarded",
+ EARLY_ACCESS_PROMOTION_CANCEL_CONFIRMATION_CLOSE_CLICKED:
+ "early access promotion cancel confirmation close clicked",
+ EARLY_ACCESS_PROMOTION_CANCEL_CONFIRMATION_ACCEPT_CLICKED:
+ "early access promotion cancel confirmation accept clicked"
},
" "
);
diff --git a/src/pluginEvents.ts b/src/pluginEvents.ts
index 5e7678ee6..9274656b3 100644
--- a/src/pluginEvents.ts
+++ b/src/pluginEvents.ts
@@ -4,5 +4,6 @@ export const PLUGIN_EVENTS = {
FIRST_ISSUE_NOTIFICATION_LINK_CLICK: "first issue notification link click",
FIRST_IMPORTANT_ISSUE_NOTIFICATION_LINK_CLICK:
"first important issue notification link click",
- FIRST_ASSET_NOTIFICATION_LINK_CLICK: "first asset notification link click"
+ FIRST_ASSET_NOTIFICATION_LINK_CLICK: "first asset notification link click",
+ SHOW_EARLY_ACCESS_PROMOTION: "SHOW_EARLY_ACCESS_PROMOTION"
};