Skip to content

Commit

Permalink
🪟 🎨 Display free tag on release stage pills for users enrolled in the…
Browse files Browse the repository at this point in the history
… free connectors program (#21892)

* Add FeatureItem.FreeConnectorProgram

This is distinct from the LaunchDarkly-backed experiment we're
referencing within `cloud/components/experiments/FreeConnectorProgram`:
it's primary use is to prevent triggering cloud-only API calls in the
OSS build.

* Extract shareable FreeTag for various release stage pills

It does seem as though we should consolidate on a single release stage
pill implementation! That will have to wait for a follow-up, though.

* Fix typo (s/inheret/inherit/)

* Prefer useFeature to useFreeConnectorProgram in OSS components

* Use TestWrapper for more future-proof test renders
  • Loading branch information
ambirdsall authored Jan 26, 2023
1 parent 1475d6e commit 4068bbe
Show file tree
Hide file tree
Showing 14 changed files with 75 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface IProps {
const Content = styled.div<{ enabled?: boolean }>`
display: flex;
align-items: center;
color: ${({ theme, enabled }) => (!enabled ? theme.greyColor40 : "inheret")};
color: ${({ theme, enabled }) => (!enabled ? theme.greyColor40 : "inherit")};
font-weight: 500;
`;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,4 @@
&--small {
font-size: 8px;
}

&--contains-tag {
padding-right: 2px;
}
}

.freeTag {
background-color: colors.$green-300;
color: colors.$white;
border-radius: variables.$border-radius-pill;
padding: 2px 5px;
margin-left: 2px;
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import classNames from "classnames";
import { FormattedMessage, useIntl } from "react-intl";
import { FormattedMessage } from "react-intl";

import { GAIcon } from "components/icons/GAIcon";
import { Tooltip } from "components/ui/Tooltip";

import { ReleaseStage } from "core/request/AirbyteClient";
import { useFeature, FeatureItem } from "hooks/services/Feature";
import { FreeTag } from "packages/cloud/components/experiments/FreeConnectorProgram";

import styles from "./ReleaseStageBadge.module.scss";

Expand All @@ -15,16 +17,10 @@ interface ReleaseStageBadgeProps {
* Whether to show a detailed message via a tooltip. If not specified, will be {@code true}.
*/
tooltip?: boolean;
showFreeTag?: boolean;
}

export const ReleaseStageBadge: React.FC<ReleaseStageBadgeProps> = ({
stage,
small,
tooltip = true,
showFreeTag = false,
}) => {
const { formatMessage } = useIntl();
export const ReleaseStageBadge: React.FC<ReleaseStageBadgeProps> = ({ stage, small, tooltip = true }) => {
const fcpEnabled = useFeature(FeatureItem.FreeConnectorProgram);

if (!stage) {
return null;
Expand All @@ -37,13 +33,10 @@ export const ReleaseStageBadge: React.FC<ReleaseStageBadgeProps> = ({
<div
className={classNames(styles.pill, {
[styles["pill--small"]]: small,
[styles["pill--contains-tag"]]: showFreeTag,
})}
>
<FormattedMessage id={`connector.releaseStage.${stage}`} />
{showFreeTag && (
<span className={styles.freeTag}>{formatMessage({ id: "freeConnectorProgram.releaseStageBadge.free" })}</span>
)}
{fcpEnabled && <FreeTag releaseStage={stage} />}
</div>
);

Expand Down
1 change: 1 addition & 0 deletions airbyte-webapp/src/hooks/services/Feature/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ export const defaultCloudFeatures = [
FeatureItem.AllowSync,
FeatureItem.AllowChangeDataGeographies,
FeatureItem.AllowDBTCloudIntegration,
FeatureItem.FreeConnectorProgram,
];
1 change: 1 addition & 0 deletions airbyte-webapp/src/hooks/services/Feature/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export enum FeatureItem {
AllowSync = "ALLOW_SYNC",
AllowChangeDataGeographies = "ALLOW_CHANGE_DATA_GEOGRAPHIES",
AllowSyncSubOneHourCronExpressions = "ALLOW_SYNC_SUB_ONE_HOUR_CRON_EXPRESSIONS",
FreeConnectorProgram = "FREE_CONNECTOR_PROGRAM",
}

export type FeatureSet = Partial<Record<FeatureItem, boolean>>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@use "scss/colors";
@use "scss/variables";

.freeTag {
background-color: colors.$green-300;
color: colors.$white;
border-radius: variables.$border-radius-pill;
padding: 2px 5px;

// margin: 0 2px;
margin-left: 2px;
margin-right: -4px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useIntl } from "react-intl";

import { ReleaseStage } from "core/request/AirbyteClient";

import styles from "./FreeTag.module.scss";
import { useFreeConnectorProgram } from "./hooks/useFreeConnectorProgram";

interface FreeTagProps {
releaseStage: ReleaseStage;
}

// A tag labeling a release stage pill as free. Defined here for easy reuse between the
// two release stage pill implementations (which should likely be refactored!)
export const FreeTag: React.FC<FreeTagProps> = ({ releaseStage }) => {
const { enrollmentStatusQuery } = useFreeConnectorProgram();
const { isEnrolled } = enrollmentStatusQuery.data || {};
const { formatMessage } = useIntl();

return isEnrolled && ["alpha", "beta"].includes(releaseStage) ? (
<span className={styles.freeTag}>{formatMessage({ id: "freeConnectorProgram.releaseStageBadge.free" })}</span>
) : null;
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,14 @@ export const EnrollLink: React.FC<PropsWithChildren<unknown>> = ({ children }) =
);
};
export const InlineEnrollmentCallout: React.FC = () => {
const { userDidEnroll } = useFreeConnectorProgram();
const { userDidEnroll, enrollmentStatusQuery } = useFreeConnectorProgram();
const { showEnrollmentUi } = enrollmentStatusQuery.data || {};

return userDidEnroll ? null : (
if (userDidEnroll || !showEnrollmentUi) {
return null;
}

return (
<Callout variant="info" className={styles.container}>
<Text size="sm">
<FormattedMessage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,14 @@ import styles from "./LargeEnrollmentCallout.module.scss";

export const LargeEnrollmentCallout: React.FC = () => {
const { showEnrollmentModal } = useShowEnrollmentModal();
const { userDidEnroll } = useFreeConnectorProgram();
const { userDidEnroll, enrollmentStatusQuery } = useFreeConnectorProgram();
const { showEnrollmentUi } = enrollmentStatusQuery.data || {};

return userDidEnroll ? null : (
if (userDidEnroll || !showEnrollmentUi) {
return null;
}

return (
<Callout variant="boldInfo" className={styles.container}>
<FlexContainer direction="row" alignItems="center" className={styles.flexRow}>
<FlexItem grow={false} alignSelf="center">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./hooks/useFreeConnectorProgram";
export * from "./FreeTag";
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Spinner } from "components/ui/Spinner";
import { Text } from "components/ui/Text";

import { PageTrackingCodes, useTrackPage } from "hooks/services/Analytics";
import { useFreeConnectorProgram } from "packages/cloud/components/experiments/FreeConnectorProgram/hooks/useFreeConnectorProgram";
import { useFeature, FeatureItem } from "hooks/services/Feature";
import { LargeEnrollmentCallout } from "packages/cloud/components/experiments/FreeConnectorProgram/LargeEnrollmentCallout";
import { useAuthService } from "packages/cloud/services/auth/AuthService";

Expand All @@ -20,8 +20,7 @@ import styles from "./CreditsPage.module.scss";
const CreditsPage: React.FC = () => {
const { emailVerified } = useAuthService();
useTrackPage(PageTrackingCodes.CREDITS);
const { enrollmentStatusQuery } = useFreeConnectorProgram();
const { showEnrollmentUi } = enrollmentStatusQuery.data || {};
const fcpEnabled = useFeature(FeatureItem.FreeConnectorProgram);

return (
<MainPageWithScroll
Expand All @@ -31,7 +30,7 @@ const CreditsPage: React.FC = () => {
<div className={styles.content}>
{!emailVerified && <EmailVerificationHint className={styles.emailVerificationHint} />}
<RemainingCredits selfServiceCheckoutEnabled={emailVerified} />
{showEnrollmentUi && <LargeEnrollmentCallout />}
{fcpEnabled && <LargeEnrollmentCallout />}
<React.Suspense
fallback={
<div className={styles.creditUsageLoading}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { Text } from "components/ui/Text";

import { ConnectionStatus } from "core/request/AirbyteClient";
import { useConnectionEditService } from "hooks/services/ConnectionEdit/ConnectionEditService";
import { useFreeConnectorProgram } from "packages/cloud/components/experiments/FreeConnectorProgram/hooks/useFreeConnectorProgram";
import { useFeature, FeatureItem } from "hooks/services/Feature";
import { InlineEnrollmentCallout } from "packages/cloud/components/experiments/FreeConnectorProgram/InlineEnrollmentCallout";

import styles from "./ConnectionPageTitle.module.scss";
Expand All @@ -26,9 +26,6 @@ export const ConnectionPageTitle: React.FC = () => {

const { connection } = useConnectionEditService();

const { enrollmentStatusQuery } = useFreeConnectorProgram();
const { showEnrollmentUi } = enrollmentStatusQuery.data || {};

const steps = useMemo(() => {
const steps = [
{
Expand Down Expand Up @@ -65,6 +62,8 @@ export const ConnectionPageTitle: React.FC = () => {
[navigate]
);

const fcpEnabled = useFeature(FeatureItem.FreeConnectorProgram);

return (
<div className={styles.container}>
{connection.status === ConnectionStatus.deprecated && (
Expand All @@ -80,7 +79,7 @@ export const ConnectionPageTitle: React.FC = () => {
<div className={styles.statusContainer}>
<FlexContainer direction="column" gap="none">
<ConnectionInfoCard />
{showEnrollmentUi && <InlineEnrollmentCallout />}
{fcpEnabled && <InlineEnrollmentCallout />}
</FlexContainer>
</div>
<StepsMenu lightMode data={steps} onSelect={onSelectStep} activeStep={currentStep} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ import { ConnectorDefinition } from "core/domain/connector";
import { ReleaseStage } from "core/request/AirbyteClient";
import { useAvailableConnectorDefinitions } from "hooks/domain/connector/useAvailableConnectorDefinitions";
import { useExperiment } from "hooks/services/Experiment";
import { useFeature, FeatureItem } from "hooks/services/Feature";
import { useModalService } from "hooks/services/Modal";
import { useCurrentWorkspace } from "hooks/services/useWorkspace";
import { FreeTag } from "packages/cloud/components/experiments/FreeConnectorProgram";
import { useDocumentationPanelContext } from "views/Connector/ConnectorDocumentationLayout/DocumentationPanelContext";
import RequestConnectorModal from "views/Connector/RequestConnectorModal";

Expand Down Expand Up @@ -51,6 +53,8 @@ const ConnectorList: React.FC<React.PropsWithChildren<MenuWithRequestButtonProps
);

const StageLabel: React.FC<{ releaseStage?: ReleaseStage }> = ({ releaseStage }) => {
const fcpEnabled = useFeature(FeatureItem.FreeConnectorProgram);

if (!releaseStage) {
return null;
}
Expand All @@ -62,6 +66,7 @@ const StageLabel: React.FC<{ releaseStage?: ReleaseStage }> = ({ releaseStage })
return (
<div className={styles.stageLabel}>
<FormattedMessage id={`connector.releaseStage.${releaseStage}`} defaultMessage={releaseStage} />
{fcpEnabled && <FreeTag releaseStage={releaseStage} />}
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import { fireEvent, render, waitFor } from "@testing-library/react";
import { IntlProvider } from "react-intl";
import { mockDestinationsData } from "test-utils/mock-data/mockFrequentlyUsedDestinations";

import en from "locales/en.json";
import { TestWrapper } from "test-utils/testutils";

import { FrequentlyUsedConnectorsCard, FrequentlyUsedConnectorsCardProps } from "./FrequentlyUsedConnectorsCard";

const renderFrequentlyUsedConnectorsComponent = (props: FrequentlyUsedConnectorsCardProps) =>
render(
<IntlProvider locale="en" messages={en}>
<TestWrapper>
<FrequentlyUsedConnectorsCard {...props} />
</IntlProvider>
</TestWrapper>
);

describe("<mockFrequentlyUsedConnectors />", () => {
Expand Down

0 comments on commit 4068bbe

Please sign in to comment.