diff --git a/frontend/src/component/environments/EnvironmentTable/EnvironmentActionCell/EnvironmentActionCell.tsx b/frontend/src/component/environments/EnvironmentTable/EnvironmentActionCell/EnvironmentActionCell.tsx
index 2a2dab69b9..847c3b5c35 100644
--- a/frontend/src/component/environments/EnvironmentTable/EnvironmentActionCell/EnvironmentActionCell.tsx
+++ b/frontend/src/component/environments/EnvironmentTable/EnvironmentActionCell/EnvironmentActionCell.tsx
@@ -1,9 +1,5 @@
import { ActionCell } from 'component/common/Table/cells/ActionCell/ActionCell';
-import {
- DELETE_ENVIRONMENT,
- UPDATE_ENVIRONMENT,
-} from 'component/providers/AccessProvider/permissions';
-import { Edit, Delete } from '@mui/icons-material';
+import { UPDATE_ENVIRONMENT } from 'component/providers/AccessProvider/permissions';
import { useNavigate } from 'react-router-dom';
import { useState } from 'react';
import { IEnvironment } from 'interfaces/environments';
@@ -15,7 +11,7 @@ import useProjectRolePermissions from 'hooks/api/getters/useProjectRolePermissio
import { useEnvironments } from 'hooks/api/getters/useEnvironments/useEnvironments';
import useToast from 'hooks/useToast';
import PermissionSwitch from 'component/common/PermissionSwitch/PermissionSwitch';
-import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton';
+import { EnvironmentActionCellPopover } from './EnvironmentActionCellPopover/EnvironmentActionCellPopover';
interface IEnvironmentTableActionsProps {
environment: IEnvironment;
@@ -103,32 +99,12 @@ export const EnvironmentActionCell = ({
onClick={() => setToggleModal(true)}
/>
- navigate(`/environments/${environment.name}`)}
- >
-
-
- setDeleteModal(true)}
- >
-
-
+ navigate(`/environments/${environment.name}`)}
+ onClone={() => console.log('TODO: CLONE')}
+ onDelete={() => setDeleteModal(true)}
+ />
({
+ padding: theme.spacing(1),
+}));
+
+const StyledMenuItem = styled(MenuItem)(({ theme }) => ({
+ borderRadius: theme.shape.borderRadius,
+}));
+
+interface IEnvironmentActionCellPopoverProps {
+ environment: IEnvironment;
+ onEdit: () => void;
+ onClone: () => void;
+ onDelete: () => void;
+}
+
+export const EnvironmentActionCellPopover = ({
+ environment,
+ onEdit,
+ onClone,
+ onDelete,
+}: IEnvironmentActionCellPopoverProps) => {
+ const { uiConfig } = useUiConfig();
+
+ const [anchorEl, setAnchorEl] = useState(null);
+
+ const open = Boolean(anchorEl);
+ const handleClick = (event: React.MouseEvent) => {
+ setAnchorEl(event.currentTarget);
+ };
+ const handleClose = () => {
+ setAnchorEl(null);
+ };
+
+ const id = `environment-${environment.name}-actions`;
+ const menuId = `${id}-menu`;
+
+ return (
+ <>
+
+
+
+
+
+
+ >
+ );
+};
diff --git a/frontend/src/interfaces/uiConfig.ts b/frontend/src/interfaces/uiConfig.ts
index d63e4db00c..895fd9e0ac 100644
--- a/frontend/src/interfaces/uiConfig.ts
+++ b/frontend/src/interfaces/uiConfig.ts
@@ -44,6 +44,7 @@ export interface IFlags {
personalAccessTokens?: boolean;
syncSSOGroups?: boolean;
suggestChanges?: boolean;
+ cloneEnvironment?: boolean;
}
export interface IVersionInfo {
diff --git a/src/lib/__snapshots__/create-config.test.ts.snap b/src/lib/__snapshots__/create-config.test.ts.snap
index df078cf2c6..7559a12f89 100644
--- a/src/lib/__snapshots__/create-config.test.ts.snap
+++ b/src/lib/__snapshots__/create-config.test.ts.snap
@@ -69,6 +69,7 @@ exports[`should create default config 1`] = `
"ENABLE_DARK_MODE_SUPPORT": false,
"anonymiseEventLog": false,
"batchMetrics": false,
+ "cloneEnvironment": false,
"embedProxy": false,
"embedProxyFrontend": false,
"personalAccessTokens": false,
@@ -82,6 +83,7 @@ exports[`should create default config 1`] = `
"ENABLE_DARK_MODE_SUPPORT": false,
"anonymiseEventLog": false,
"batchMetrics": false,
+ "cloneEnvironment": false,
"embedProxy": false,
"embedProxyFrontend": false,
"personalAccessTokens": false,
diff --git a/src/lib/types/experimental.ts b/src/lib/types/experimental.ts
index 95a69bba02..e8af3c9538 100644
--- a/src/lib/types/experimental.ts
+++ b/src/lib/types/experimental.ts
@@ -34,6 +34,10 @@ export const defaultExperimentalOptions = {
process.env.UNLEASH_EXPERIMENTAL_RESPONSE_TIME_WITH_APP_NAME,
false,
),
+ cloneEnvironment: parseEnvVarBoolean(
+ process.env.UNLEASH_EXPERIMENTAL_CLONE_ENVIRONMENT,
+ false,
+ ),
},
externalResolver: { isEnabled: (): boolean => false },
};
@@ -48,6 +52,7 @@ export interface IExperimentalOptions {
anonymiseEventLog?: boolean;
personalAccessTokens?: boolean;
syncSSOGroups?: boolean;
+ cloneEnvironment?: boolean;
};
externalResolver: IExternalFlagResolver;
}
diff --git a/src/server-dev.ts b/src/server-dev.ts
index 35d9a41990..4d7673a8fa 100644
--- a/src/server-dev.ts
+++ b/src/server-dev.ts
@@ -41,6 +41,7 @@ process.nextTick(async () => {
personalAccessTokens: true,
syncSSOGroups: true,
suggestChanges: true,
+ cloneEnvironment: true,
},
},
authentication: {
diff --git a/src/test/config/test-config.ts b/src/test/config/test-config.ts
index 33a7ca50e6..b2618d634a 100644
--- a/src/test/config/test-config.ts
+++ b/src/test/config/test-config.ts
@@ -29,6 +29,7 @@ export function createTestConfig(config?: IUnleashOptions): IUnleashConfig {
batchMetrics: true,
personalAccessTokens: true,
syncSSOGroups: true,
+ cloneEnvironment: true,
},
},
};