diff --git a/frontend/src/component/environments/EnvironmentTable/EnvironmentTable.tsx b/frontend/src/component/environments/EnvironmentTable/EnvironmentTable.tsx
index 770f9f2f9a..c9d0a8fe01 100644
--- a/frontend/src/component/environments/EnvironmentTable/EnvironmentTable.tsx
+++ b/frontend/src/component/environments/EnvironmentTable/EnvironmentTable.tsx
@@ -28,7 +28,6 @@ import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
import type { IEnvironment } from 'interfaces/environments';
import { useUiFlag } from 'hooks/useUiFlag';
import { PremiumFeature } from 'component/common/PremiumFeature/PremiumFeature';
-import { OrderEnvironments } from './OrderEnvironments/OrderEnvironments';
const StyledAlert = styled(Alert)(({ theme }) => ({
marginBottom: theme.spacing(4),
}));
@@ -38,9 +37,6 @@ export const EnvironmentTable = () => {
const { setToastApiError } = useToast();
const { environments, mutateEnvironments } = useEnvironments();
const isFeatureEnabled = useUiFlag('EEA');
- const isPurchaseAdditionalEnvironmentsEnabled = useUiFlag(
- 'purchaseAdditionalEnvironments',
- );
const moveListItem: MoveListItem = useCallback(
async (dragIndex: number, dropIndex: number, save = false) => {
@@ -116,7 +112,7 @@ export const EnvironmentTable = () => {
);
- if (!isFeatureEnabled && !isPurchaseAdditionalEnvironmentsEnabled) {
+ if (!isFeatureEnabled) {
return (
@@ -126,7 +122,6 @@ export const EnvironmentTable = () => {
return (
-
This is the order of environments that you have today in each
feature flag. Rearranging them here will change also the order
diff --git a/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironments.test.tsx b/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironments.test.tsx
deleted file mode 100644
index 49e7d95131..0000000000
--- a/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironments.test.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import { screen, fireEvent, waitFor } from '@testing-library/react';
-import { render } from 'utils/testRenderer';
-import { OrderEnvironments } from './OrderEnvironments';
-import { testServerRoute, testServerSetup } from 'utils/testServer';
-
-const server = testServerSetup();
-
-const setupServerRoutes = (changeRequestsEnabled = true) => {
- testServerRoute(server, '/api/admin/ui-config', {
- environment: 'Pro',
- flags: {
- purchaseAdditionalEnvironments: true,
- },
- });
-};
-
-describe('OrderEnvironmentsDialog Component', () => {
- test('should show error if environment name is empty', async () => {
- setupServerRoutes();
- render();
-
- await waitFor(async () => {
- const openDialogButton = await screen.queryByRole('button', {
- name: /view pricing/i,
- });
- expect(openDialogButton).toBeInTheDocument();
- fireEvent.click(openDialogButton!);
- });
-
- const checkbox = screen.getByRole('checkbox', {
- name: /i understand adding environments/i,
- });
- fireEvent.click(checkbox);
-
- const submitButton = screen.getByRole('button', { name: /order/i });
- fireEvent.click(submitButton);
-
- expect(
- screen.getByText(/environment name is required/i),
- ).toBeInTheDocument();
- });
-});
diff --git a/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironments.tsx b/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironments.tsx
deleted file mode 100644
index 12c6c17784..0000000000
--- a/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironments.tsx
+++ /dev/null
@@ -1,84 +0,0 @@
-import { useState, type FC } from 'react';
-import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
-import { useUiFlag } from 'hooks/useUiFlag';
-import { PurchasableFeature } from './PurchasableFeature/PurchasableFeature';
-import { OrderEnvironmentsDialog } from './OrderEnvironmentsDialog/OrderEnvironmentsDialog';
-import { OrderEnvironmentsConfirmation } from './OrderEnvironmentsConfirmation/OrderEnvironmentsConfirmation';
-import { useFormErrors } from 'hooks/useFormErrors';
-import useToast from 'hooks/useToast';
-import { formatUnknownError } from 'utils/formatUnknownError';
-import { useOrderEnvironmentApi } from 'hooks/api/actions/useOrderEnvironmentsApi/useOrderEnvironmentsApi';
-import type { OrderEnvironmentsSchema } from 'openapi';
-
-type OrderEnvironmentsProps = {};
-
-export const OrderEnvironments: FC = () => {
- const [purchaseDialogOpen, setPurchaseDialogOpen] = useState(false);
- const [confirmationState, setConfirmationState] = useState<{
- isOpen: boolean;
- environmentsCount?: number;
- }>({ isOpen: false });
- const { isPro } = useUiConfig();
- const isPurchaseAdditionalEnvironmentsEnabled = useUiFlag(
- 'purchaseAdditionalEnvironments',
- );
- const errors = useFormErrors();
- const { orderEnvironments } = useOrderEnvironmentApi();
- const { setToastApiError } = useToast();
-
- if (!isPro() || !isPurchaseAdditionalEnvironmentsEnabled) {
- return null;
- }
-
- const onSubmit = async (
- environments: OrderEnvironmentsSchema['environments'],
- ) => {
- let hasErrors = false;
- environments.forEach((environment, index) => {
- const field = `environment-${index}`;
- const environmentName = environment.name.trim();
- if (environmentName === '') {
- errors.setFormError(field, 'Environment name is required');
- hasErrors = true;
- } else {
- errors.removeFormError(field);
- }
- });
-
- if (hasErrors) {
- return;
- } else {
- try {
- await orderEnvironments({ environments });
- setPurchaseDialogOpen(false);
- setConfirmationState({
- isOpen: true,
- environmentsCount: environments.length,
- });
- } catch (error) {
- setToastApiError(formatUnknownError(error));
- }
- }
- };
-
- return (
- <>
- setPurchaseDialogOpen(true)}
- />
- setPurchaseDialogOpen(false)}
- onSubmit={onSubmit}
- errors={errors}
- />
- setConfirmationState({ isOpen: false })}
- />
- >
- );
-};
diff --git a/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironmentsConfirmation/OrderEnvironmentsConfirmation.tsx b/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironmentsConfirmation/OrderEnvironmentsConfirmation.tsx
deleted file mode 100644
index ba666a5f34..0000000000
--- a/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironmentsConfirmation/OrderEnvironmentsConfirmation.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-import type { FC } from 'react';
-import { Typography } from '@mui/material';
-import { Dialogue } from 'component/common/Dialogue/Dialogue';
-
-type OrderEnvironmentsConfirmationProps = {
- open: boolean;
- orderedEnvironments: number;
- onClose: () => void;
-};
-
-export const OrderEnvironmentsConfirmation: FC<
- OrderEnvironmentsConfirmationProps
-> = ({ open, orderedEnvironments, onClose }) => {
- return (
-
-
- You have ordered {orderedEnvironments}{' '}
- additional{' '}
- {orderedEnvironments === 1 ? 'environment' : 'environments'}. It
- may take up to 24 hours before you will get access.
-
-
- );
-};
diff --git a/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironmentsDialog/OrderEnvironmentsDialog.test.tsx b/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironmentsDialog/OrderEnvironmentsDialog.test.tsx
deleted file mode 100644
index 29329dc5dc..0000000000
--- a/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironmentsDialog/OrderEnvironmentsDialog.test.tsx
+++ /dev/null
@@ -1,212 +0,0 @@
-import { vi } from 'vitest';
-import { render, screen, fireEvent } from '@testing-library/react';
-import { OrderEnvironmentsDialog } from './OrderEnvironmentsDialog';
-
-describe('OrderEnvironmentsDialog Component', () => {
- const renderComponent = (props = {}) =>
- render(
- {}}
- onSubmit={() => {}}
- {...props}
- />,
- );
-
- test('should disable "Order" button until the checkbox is checked', () => {
- renderComponent();
-
- const orderButton = screen.getByRole('button', { name: /order/i });
- const checkbox = screen.getByRole('checkbox', {
- name: /i understand adding environments leads to extra costs/i,
- });
-
- expect(orderButton).toBeDisabled();
-
- fireEvent.click(checkbox);
-
- expect(orderButton).toBeEnabled();
- });
-
- test('should render correct number of environment name inputs based on selected environments', () => {
- renderComponent();
-
- let environmentInputs =
- screen.getAllByLabelText(/environment \d+ name/i);
- expect(environmentInputs).toHaveLength(1);
-
- const selectButton = screen.getByRole('combobox', {
- name: /select the number of additional environments/i,
- });
- fireEvent.mouseDown(selectButton);
-
- const option2 = screen.getByRole('option', { name: '2 environments' });
- fireEvent.click(option2);
-
- environmentInputs = screen.getAllByLabelText(/environment \d+ name/i);
- expect(environmentInputs).toHaveLength(2);
-
- fireEvent.mouseDown(selectButton);
- const option3 = screen.getByRole('option', { name: '3 environments' });
- fireEvent.click(option3);
-
- environmentInputs = screen.getAllByLabelText(/environment \d+ name/i);
- expect(environmentInputs).toHaveLength(3);
- });
-
- test('should enable "Order" button only when checkbox is checked', () => {
- renderComponent();
-
- const orderButton = screen.getByRole('button', { name: /order/i });
- const checkbox = screen.getByRole('checkbox', {
- name: /i understand adding environments leads to extra costs/i,
- });
-
- expect(orderButton).toBeDisabled();
-
- fireEvent.click(checkbox);
-
- expect(orderButton).toBeEnabled();
-
- fireEvent.click(checkbox);
-
- expect(orderButton).toBeDisabled();
- });
-
- test('should output environment names', () => {
- const onSubmitMock = vi.fn();
- renderComponent({ onSubmit: onSubmitMock });
-
- const selectButton = screen.getByRole('combobox', {
- name: /select the number of additional environments/i,
- });
- fireEvent.mouseDown(selectButton);
-
- const option2 = screen.getByRole('option', { name: '2 environments' });
- fireEvent.click(option2);
-
- const environmentInputs =
- screen.getAllByLabelText(/environment \d+ name/i);
-
- fireEvent.change(environmentInputs[0], { target: { value: 'Dev' } });
- fireEvent.change(environmentInputs[1], {
- target: { value: 'Staging' },
- });
- const checkbox = screen.getByRole('checkbox', {
- name: /i understand adding environments leads to extra costs/i,
- });
- fireEvent.click(checkbox);
-
- const submitButton = screen.getByRole('button', { name: /order/i });
- fireEvent.click(submitButton);
-
- expect(onSubmitMock).toHaveBeenCalledTimes(1);
- expect(onSubmitMock).toHaveBeenCalledWith([
- { name: 'Dev', type: 'development' },
- { name: 'Staging', type: 'development' },
- ]);
- });
-
- test('should call onClose when "Cancel" button is clicked', () => {
- const onCloseMock = vi.fn();
- renderComponent({ onClose: onCloseMock });
-
- const cancelButton = screen.getByRole('button', { name: /cancel/i });
- fireEvent.click(cancelButton);
-
- expect(onCloseMock).toHaveBeenCalledTimes(1);
- });
-
- test('should adjust environment name inputs when decreasing environments', () => {
- const onSubmitMock = vi.fn();
- renderComponent({ onSubmit: onSubmitMock });
-
- const selectButton = screen.getByRole('combobox', {
- name: /select the number of additional environments/i,
- });
- fireEvent.mouseDown(selectButton);
-
- const option3 = screen.getByRole('option', { name: '3 environments' });
- fireEvent.click(option3);
-
- let environmentInputs =
- screen.getAllByLabelText(/environment \d+ name/i);
- expect(environmentInputs).toHaveLength(3);
-
- fireEvent.change(environmentInputs[0], { target: { value: 'Dev' } });
- fireEvent.change(environmentInputs[1], {
- target: { value: 'Staging' },
- });
- fireEvent.change(environmentInputs[2], { target: { value: 'Prod' } });
-
- fireEvent.mouseDown(selectButton);
- const option2 = screen.getByRole('option', { name: '2 environments' });
- fireEvent.click(option2);
-
- environmentInputs = screen.getAllByLabelText(/environment \d+ name/i);
- expect(environmentInputs).toHaveLength(2);
-
- const checkbox = screen.getByRole('checkbox', {
- name: /i understand adding environments leads to extra costs/i,
- });
- fireEvent.click(checkbox);
-
- const submitButton = screen.getByRole('button', { name: /order/i });
- fireEvent.click(submitButton);
-
- expect(onSubmitMock).toHaveBeenCalledTimes(1);
- expect(onSubmitMock).toHaveBeenCalledWith([
- { name: 'Dev', type: 'development' },
- { name: 'Staging', type: 'development' },
- ]);
- });
-
- test('should allow for changing environment types', () => {
- const onSubmitMock = vi.fn();
- renderComponent({ onSubmit: onSubmitMock });
-
- const selectButton = screen.getByRole('combobox', {
- name: /select the number of additional environments/i,
- });
- fireEvent.mouseDown(selectButton);
- const option3 = screen.getByRole('option', { name: '2 environments' });
- fireEvent.click(option3);
-
- const checkbox = screen.getByRole('checkbox', {
- name: /i understand adding environments leads to extra costs/i,
- });
- fireEvent.click(checkbox);
-
- const environmentInputs =
- screen.getAllByLabelText(/environment \d+ name/i);
- fireEvent.change(environmentInputs[0], { target: { value: 'Test' } });
- fireEvent.change(environmentInputs[1], {
- target: { value: 'Staging' },
- });
-
- const typeSelects = screen.getAllByRole('combobox', {
- name: /type of environment/i,
- });
-
- fireEvent.mouseDown(typeSelects[0]);
- const optionTesting = screen.getByRole('option', {
- name: /testing/i,
- });
- fireEvent.click(optionTesting);
-
- fireEvent.mouseDown(typeSelects[1]);
- const optionProduction = screen.getByRole('option', {
- name: /pre\-production/i,
- });
- fireEvent.click(optionProduction);
-
- const submitButton = screen.getByRole('button', { name: /order/i });
- fireEvent.click(submitButton);
-
- expect(onSubmitMock).toHaveBeenCalledTimes(1);
- expect(onSubmitMock).toHaveBeenCalledWith([
- { name: 'Test', type: 'testing' },
- { name: 'Staging', type: 'pre-production' },
- ]);
- });
-});
diff --git a/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironmentsDialog/OrderEnvironmentsDialog.tsx b/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironmentsDialog/OrderEnvironmentsDialog.tsx
deleted file mode 100644
index c9e9625fe4..0000000000
--- a/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironmentsDialog/OrderEnvironmentsDialog.tsx
+++ /dev/null
@@ -1,253 +0,0 @@
-import { useState, type FC } from 'react';
-import {
- Box,
- Button,
- Checkbox,
- Dialog,
- styled,
- Typography,
- TextField,
-} from '@mui/material';
-import FormTemplate from 'component/common/FormTemplate/FormTemplate';
-import { OrderEnvironmentsDialogPricing } from './OrderEnvironmentsDialogPricing/OrderEnvironmentsDialogPricing';
-import GeneralSelect from 'component/common/GeneralSelect/GeneralSelect';
-import type { IFormErrors } from 'hooks/useFormErrors';
-import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
-import type { OrderEnvironmentsSchemaEnvironmentsItem } from 'openapi';
-
-type OrderEnvironmentsDialogProps = {
- open: boolean;
- onClose: () => void;
- onSubmit: (environments: OrderEnvironmentsSchemaEnvironmentsItem[]) => void;
- errors?: IFormErrors;
-};
-
-const StyledDialog = styled(Dialog)(({ theme }) => ({
- maxWidth: '940px',
- margin: 'auto',
- '& .MuiDialog-paper': {
- borderRadius: theme.shape.borderRadiusExtraLarge,
- maxWidth: theme.spacing(170),
- width: '100%',
- backgroundColor: 'transparent',
- },
- padding: 0,
- '& .MuiPaper-root > section': {
- overflowX: 'hidden',
- },
-}));
-
-const StyledTitle = styled('div')(({ theme }) => ({
- marginBottom: theme.spacing(3),
-}));
-
-const StyledFooter = styled('div')(({ theme }) => ({
- display: 'flex',
- justifyContent: 'flex-end',
- gap: theme.spacing(2),
-}));
-
-const StyledGeneralSelect = styled(GeneralSelect)(({ theme }) => ({
- margin: theme.spacing(1, 0),
-}));
-
-const StyledTypeSelect = styled(GeneralSelect)(({ theme }) => ({
- minWidth: '166px',
-}));
-
-const StyledEnvironmentInputs = styled(Box)(({ theme }) => ({
- display: 'flex',
- gap: theme.spacing(2),
- marginBottom: theme.spacing(2),
-}));
-
-const StyledFields = styled(Box)(({ theme }) => ({
- display: 'flex',
- flexDirection: 'column',
- gap: theme.spacing(2),
- paddingTop: theme.spacing(3),
-}));
-
-const StyledEnvironmentNameInputs = styled('fieldset')(({ theme }) => ({
- display: 'flex',
- flexDirection: 'column',
- border: 'none',
- padding: 0,
- margin: 0,
- gap: theme.spacing(1.5),
-}));
-
-const StyledCheckbox = styled(Checkbox)(({ theme }) => ({
- marginBottom: theme.spacing(0.4),
-}));
-
-const PRICE = 10;
-const OPTIONS = [1, 2, 3];
-const ENVIRONMENT_TYPES = [
- 'development',
- 'testing',
- 'pre-production',
- 'production',
-];
-
-export const OrderEnvironmentsDialog: FC = ({
- open,
- onClose,
- onSubmit,
- errors,
-}) => {
- const { trackEvent } = usePlausibleTracker();
- const [selectedOption, setSelectedOption] = useState(OPTIONS[0]);
- const [costCheckboxChecked, setCostCheckboxChecked] = useState(false);
- const [environments, setEnvironments] = useState<
- { name: string; type: string }[]
- >([{ name: '', type: ENVIRONMENT_TYPES[0] }]);
-
- const trackEnvironmentSelect = () => {
- trackEvent('order-environments', {
- props: {
- eventType: 'selected environment count',
- },
- });
- };
-
- const onTypeChange = (index: number, type: string) => {
- setEnvironments(
- environments.map((env, i) =>
- i === index ? { ...env, type } : { ...env },
- ),
- );
- };
-
- const onNameChange = (index: number, name: string) => {
- setEnvironments(
- environments.map((env, i) =>
- i === index ? { ...env, name } : { ...env },
- ),
- );
- };
-
- return (
-
- ({
- environments: option,
- price: option * PRICE,
- }))}
- />
- }
- footer={
-
-
-
-
- }
- >
-
-
- Order additional environments
-
-
-
- With our PRO plan, you have the flexibility to expand your
- workspace by adding environments at ${PRICE} per user per
- month.
-
-
-
-
- Select the number of additional environments
-
- ({
- key: `${option}`,
- label: `${option} environment${option > 1 ? 's' : ''}`,
- }))}
- onChange={(option) => {
- const value = Number.parseInt(option, 10);
- setSelectedOption(value);
- setEnvironments((envs) =>
- [
- ...envs,
- ...Array(value).fill({
- name: '',
- type: ENVIRONMENT_TYPES[0],
- }),
- ].slice(0, value),
- );
- trackEnvironmentSelect();
- }}
- />
-
-
-
- How would you like the environment
- {selectedOption > 1 ? 's' : ''} to be named?
-
- {[...Array(selectedOption)].map((_, i) => {
- const error = errors?.getFormError(
- `environment-${i}`,
- );
- return (
-
- ({
- key: type,
- label: type,
- }),
- )}
- onChange={(type) => {
- onTypeChange(i, type);
- }}
- />
- {
- onNameChange(i, e.target.value);
- }}
- error={!!error}
- helperText={error}
- />
-
- );
- })}
-
-
-
- setCostCheckboxChecked((state) => !state)
- }
- />
-
- I understand adding environments leads to extra
- costs
-
-
-
-
-
- );
-};
diff --git a/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironmentsDialog/OrderEnvironmentsDialogPricing/OrderEnvironmentsDialogPricing.tsx b/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironmentsDialog/OrderEnvironmentsDialogPricing/OrderEnvironmentsDialogPricing.tsx
deleted file mode 100644
index 9d6089591e..0000000000
--- a/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/OrderEnvironmentsDialog/OrderEnvironmentsDialogPricing/OrderEnvironmentsDialogPricing.tsx
+++ /dev/null
@@ -1,71 +0,0 @@
-import type { FC } from 'react';
-import { Box, Card, styled, Typography } from '@mui/material';
-import EnvironmentIcon from 'component/common/EnvironmentIcon/EnvironmentIcon';
-import { BILLING_PRO_DEFAULT_INCLUDED_SEATS } from 'component/admin/billing/BillingDashboard/BillingPlan/BillingPlan';
-
-type OrderEnvironmentsDialogPricingProps = {
- pricingOptions: Array<{ environments: number; price: number }>;
-};
-
-const StyledContainer = styled(Box)(({ theme }) => ({
- display: 'flex',
- flexDirection: 'column',
- gap: theme.spacing(1),
- justifyContent: 'center',
- height: '100%',
- [theme.breakpoints.up('lg')]: {
- marginTop: theme.spacing(7.5),
- },
-}));
-
-const StyledCard = styled(Card)(({ theme }) => ({
- borderRadius: `${theme.shape.borderRadiusMedium}px`,
- boxShadow: 'none',
-}));
-
-const StyledCardContent = styled(Box)(({ theme }) => ({
- display: 'flex',
- alignItems: 'center',
- justifyContent: 'space-between',
- flexDirection: 'row',
- padding: theme.spacing(2),
-}));
-
-const StyledExtraText = styled('div')(({ theme }) => ({
- paddingTop: theme.spacing(2),
-}));
-
-export const OrderEnvironmentsDialogPricing: FC<
- OrderEnvironmentsDialogPricingProps
-> = ({ pricingOptions }) => (
-
-
- Pricing
-
- {pricingOptions.map((option) => (
-
-
-
-
-
-
- {option.environments} additional environment
- {option.environments > 1 ? 's' : ''}
-
-
-
- ${option.price} per user per month
-
-
-
-
- ))}
-
-
- With Pro, there is a minimum of{' '}
- {BILLING_PRO_DEFAULT_INCLUDED_SEATS} users, meaning an
- additional environment will cost at least $50 per month.
-
-
-
-);
diff --git a/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/PurchasableFeature/PurchasableFeature.tsx b/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/PurchasableFeature/PurchasableFeature.tsx
deleted file mode 100644
index e63d3890e0..0000000000
--- a/frontend/src/component/environments/EnvironmentTable/OrderEnvironments/PurchasableFeature/PurchasableFeature.tsx
+++ /dev/null
@@ -1,83 +0,0 @@
-import type { FC, ReactNode } from 'react';
-import { Box, Button, styled, Typography } from '@mui/material';
-import { ThemeMode } from 'component/common/ThemeMode/ThemeMode';
-import { ReactComponent as ProPlanIcon } from 'assets/icons/pro-enterprise-feature-badge.svg';
-import { ReactComponent as ProPlanIconLight } from 'assets/icons/pro-enterprise-feature-badge-light.svg';
-import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
-
-type PurchasableFeatureProps = {
- title: ReactNode;
- description: ReactNode;
- onClick: () => void;
-};
-
-const Icon = () => (
- } lightmode={} />
-);
-
-const StyledContainer = styled(Box)(({ theme }) => ({
- padding: theme.spacing(2, 3),
- marginBottom: theme.spacing(3),
- background: theme.palette.background.elevation2,
- borderRadius: `${theme.shape.borderRadiusMedium}px`,
- display: 'flex',
- flexDirection: 'row',
- gap: theme.spacing(3),
- [theme.breakpoints.down('md')]: {
- flexDirection: 'column',
- gap: theme.spacing(2),
- },
-}));
-
-const StyledIconContainer = styled(Box)(() => ({
- width: '36px',
- flexShrink: 0,
-}));
-
-const StyledMessage = styled(Box)(() => ({
- flexGrow: 1,
- display: 'flex',
-}));
-
-const StyledButtonContainer = styled(Box)(() => ({
- display: 'flex',
- justifyContent: 'center',
- alignItems: 'center',
- whiteSpace: 'nowrap',
-}));
-
-export const PurchasableFeature: FC = ({
- title,
- description,
- onClick,
-}) => {
- const { trackEvent } = usePlausibleTracker();
-
- const onViewPricingClick = () => {
- onClick();
- trackEvent('order-environments', {
- props: {
- eventType: 'view pricing clicked',
- },
- });
- };
-
- return (
-
-
-
-
-
-
- {title}
- {description}
-
-
-
-
-
-
- );
-};
diff --git a/frontend/src/hooks/api/actions/useOrderEnvironmentsApi/useOrderEnvironmentsApi.ts b/frontend/src/hooks/api/actions/useOrderEnvironmentsApi/useOrderEnvironmentsApi.ts
deleted file mode 100644
index b941b80255..0000000000
--- a/frontend/src/hooks/api/actions/useOrderEnvironmentsApi/useOrderEnvironmentsApi.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import useAPI from '../useApi/useApi';
-import type { OrderEnvironmentsSchema } from 'openapi';
-
-export const useOrderEnvironmentApi = () => {
- const { makeRequest, createRequest, errors, loading } = useAPI({
- propagateErrors: true,
- });
-
- const orderEnvironments = async (payload: OrderEnvironmentsSchema) => {
- const req = createRequest('api/admin/order-environments', {
- method: 'POST',
- body: JSON.stringify(payload),
- });
-
- await makeRequest(req.caller, req.id);
- };
-
- return {
- orderEnvironments,
- errors,
- loading,
- };
-};
diff --git a/frontend/src/interfaces/uiConfig.ts b/frontend/src/interfaces/uiConfig.ts
index b135df6b02..e7667b4546 100644
--- a/frontend/src/interfaces/uiConfig.ts
+++ b/frontend/src/interfaces/uiConfig.ts
@@ -85,7 +85,6 @@ export type UiFlags = {
manyStrategiesPagination?: boolean;
enableLegacyVariants?: boolean;
flagCreator?: boolean;
- purchaseAdditionalEnvironments?: boolean;
unleashAI?: boolean;
releasePlans?: boolean;
'enterprise-payg'?: boolean;
diff --git a/src/lib/services/email-service.test.ts b/src/lib/services/email-service.test.ts
index 1ee62d8d9d..f8967f6693 100644
--- a/src/lib/services/email-service.test.ts
+++ b/src/lib/services/email-service.test.ts
@@ -103,47 +103,6 @@ test('should strip special characters from email subject', async () => {
expect(emailService.stripSpecialCharacters('tom-jones')).toBe('tom-jones');
});
-test('Can send order environments email', async () => {
- process.env.ORDER_ENVIRONMENTS_BCC = 'bcc@bcc.com';
- const emailService = new EmailService({
- email: {
- host: 'test',
- port: 587,
- secure: false,
- smtpuser: '',
- smtppass: '',
- sender: 'noreply@getunleash.ai',
- },
- getLogger: noLoggerProvider,
- } as unknown as IUnleashConfig);
-
- const customerId = 'customer133';
- const environments = [
- { name: 'test', type: 'development' },
- { name: 'live', type: 'production' },
- ];
-
- const content = await emailService.sendOrderEnvironmentEmail(
- 'user@user.com',
- customerId,
- environments,
- );
- expect(content.from).toBe('noreply@getunleash.ai');
- expect(content.subject).toBe('Unleash - ordered environments successfully');
- expect(
- content.html.includes(
- `Name: ${environments[0].name}, Type: ${environments[0].type}`,
- ),
- ).toBe(true);
- expect(
- content.html.includes(
- `Name: ${environments[1].name}, Type: ${environments[1].type}`,
- ),
- ).toBe(true);
- expect(content.html.includes(customerId)).toBe(true);
- expect(content.bcc).toBe('bcc@bcc.com');
-});
-
test('Can send productivity report email', async () => {
const emailService = new EmailService({
server: {
diff --git a/src/lib/services/email-service.ts b/src/lib/services/email-service.ts
index f9fd56cb59..432d7865f0 100644
--- a/src/lib/services/email-service.ts
+++ b/src/lib/services/email-service.ts
@@ -70,11 +70,6 @@ export type ChangeRequestScheduleConflictData =
environment: string;
};
-export type OrderEnvironmentData = {
- name: string;
- type: string;
-};
-
export class EmailService {
private logger: Logger;
private config: IUnleashConfig;
@@ -462,71 +457,6 @@ export class EmailService {
});
}
- async sendOrderEnvironmentEmail(
- userEmail: string,
- customerId: string,
- environments: OrderEnvironmentData[],
- ): Promise {
- if (this.configured()) {
- const context = {
- userEmail,
- customerId,
- environments: environments.map((data) => ({
- name: this.stripSpecialCharacters(data.name),
- type: this.stripSpecialCharacters(data.type),
- })),
- };
-
- const bodyHtml = await this.compileTemplate(
- 'order-environments',
- TemplateFormat.HTML,
- context,
- );
- const bodyText = await this.compileTemplate(
- 'order-environments',
- TemplateFormat.PLAIN,
- context,
- );
- const email = {
- from: this.sender,
- to: userEmail,
- bcc:
- process.env.ORDER_ENVIRONMENTS_BCC ||
- 'pro-sales@getunleash.io',
- subject: ORDER_ENVIRONMENTS_SUBJECT,
- html: bodyHtml,
- text: bodyText,
- };
- process.nextTick(() => {
- this.mailer!.sendMail(email).then(
- () =>
- this.logger.info(
- 'Successfully sent order environments email',
- ),
- (e) =>
- this.logger.warn(
- 'Failed to send order environments email',
- e,
- ),
- );
- });
- return Promise.resolve(email);
- }
- return new Promise((res) => {
- this.logger.warn(
- 'No mailer is configured. Please read the docs on how to configure an email service',
- );
- res({
- from: this.sender,
- to: userEmail,
- bcc: '',
- subject: ORDER_ENVIRONMENTS_SUBJECT,
- html: '',
- text: '',
- });
- });
- }
-
async sendProductivityReportEmail(
userEmail: string,
userName: string,
diff --git a/src/lib/types/experimental.ts b/src/lib/types/experimental.ts
index 3896f6e210..1da78c0f68 100644
--- a/src/lib/types/experimental.ts
+++ b/src/lib/types/experimental.ts
@@ -47,7 +47,6 @@ export type IFlagKey =
| 'extendedMetrics'
| 'removeUnsafeInlineStyleSrc'
| 'projectRoleAssignment'
- | 'purchaseAdditionalEnvironments'
| 'originMiddlewareRequestLogging'
| 'unleashAI'
| 'webhookDomainLogging'
@@ -239,10 +238,6 @@ const flags: IFlags = {
process.env.UNLEASH_EXPERIMENTAL_PROJECT_ROLE_ASSIGNMENT,
false,
),
- purchaseAdditionalEnvironments: parseEnvVarBoolean(
- process.env.UNLEASH_EXPERIMENTAL_PURCHASE_ADDITIONAL_ENVIRONMENTS,
- false,
- ),
originMiddlewareRequestLogging: parseEnvVarBoolean(
process.env.UNLEASH_ORIGIN_MIDDLEWARE_REQUEST_LOGGING,
false,
diff --git a/src/server-dev.ts b/src/server-dev.ts
index d4b7e36deb..69c9303a96 100644
--- a/src/server-dev.ts
+++ b/src/server-dev.ts
@@ -48,7 +48,6 @@ process.nextTick(async () => {
manyStrategiesPagination: true,
enableLegacyVariants: false,
extendedMetrics: true,
- purchaseAdditionalEnvironments: true,
originMiddlewareRequestLogging: true,
unleashAI: true,
webhookDomainLogging: true,