diff --git a/frontend/src/component/onboarding/flow/ProjectOnboarding.tsx b/frontend/src/component/onboarding/flow/ProjectOnboarding.tsx index 310853f17b..74a74803b7 100644 --- a/frontend/src/component/onboarding/flow/ProjectOnboarding.tsx +++ b/frontend/src/component/onboarding/flow/ProjectOnboarding.tsx @@ -4,7 +4,7 @@ import { UPDATE_PROJECT, CREATE_PROJECT_API_TOKEN, } from 'component/providers/AccessProvider/permissions'; -import { FlagCreationButton } from '../../project/Project/PaginatedProjectFeatureToggles/ProjectFeatureTogglesHeader/ProjectFeatureTogglesHeader.tsx'; +import { FlagCreationButton } from '../../project/Project/PaginatedProjectFeatureToggles/ProjectFeatureTogglesHeader/FlagCreationButton/FlagCreationButton.tsx'; import ResponsiveButton from 'component/common/ResponsiveButton/ResponsiveButton'; import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectOverview'; import { SdkExample } from './SdkExample.tsx'; diff --git a/frontend/src/component/project/Project/ProjectFeatureToggles/ColumnsMenu/ColumnsMenu.styles.ts b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ColumnsMenu/ColumnsMenu.styles.ts similarity index 100% rename from frontend/src/component/project/Project/ProjectFeatureToggles/ColumnsMenu/ColumnsMenu.styles.ts rename to frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ColumnsMenu/ColumnsMenu.styles.ts diff --git a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ExperimentalColumnsMenu/ExperimentalColumnsMenu.tsx b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ColumnsMenu/ColumnsMenu.tsx similarity index 95% rename from frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ExperimentalColumnsMenu/ExperimentalColumnsMenu.tsx rename to frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ColumnsMenu/ColumnsMenu.tsx index 2886355cf1..d6798f2459 100644 --- a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ExperimentalColumnsMenu/ExperimentalColumnsMenu.tsx +++ b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ColumnsMenu/ColumnsMenu.tsx @@ -1,4 +1,4 @@ -import { useState, type VFC } from 'react'; +import { useState, type FC } from 'react'; import { IconButton, ListItemIcon, @@ -17,7 +17,7 @@ import { StyledDivider, StyledIconButton, StyledMenuItem, -} from './ExperimentalColumnsMenu.styles'; +} from './ColumnsMenu.styles'; interface IColumnsMenuProps { columns: { @@ -29,10 +29,7 @@ interface IColumnsMenuProps { onToggle?: (id: string) => void; } -export const ExperimentalColumnsMenu: VFC = ({ - columns, - onToggle, -}) => { +export const ColumnsMenu: FC = ({ columns, onToggle }) => { const [anchorEl, setAnchorEl] = useState(null); const onIconClick = (event: React.MouseEvent) => { diff --git a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ExperimentalColumnsMenu/ExperimentalColumnsMenu.styles.ts b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ExperimentalColumnsMenu/ExperimentalColumnsMenu.styles.ts deleted file mode 100644 index c688a3def3..0000000000 --- a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ExperimentalColumnsMenu/ExperimentalColumnsMenu.styles.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { - Box, - Checkbox, - Divider, - IconButton, - MenuItem, - styled, -} from '@mui/material'; - -import { flexRow } from 'themes/themeStyles'; - -export const StyledBoxContainer = styled(Box)(() => ({ - ...flexRow, - justifyContent: 'center', -})); - -export const StyledIconButton = styled(IconButton)(({ theme }) => ({ - margin: theme.spacing(-1, 0), -})); - -export const StyledBoxMenuHeader = styled(Box)(({ theme }) => ({ - ...flexRow, - justifyContent: 'space-between', - padding: theme.spacing(1, 1, 0, 4), -})); - -export const StyledMenuItem = styled(MenuItem)(({ theme }) => ({ - padding: theme.spacing(0, 2), - margin: theme.spacing(0, 2), - borderRadius: theme.shape.borderRadius, -})); - -export const StyledDivider = styled(Divider)(({ theme }) => ({ - '&.MuiDivider-root.MuiDivider-fullWidth': { - margin: theme.spacing(0.75, 0), - }, -})); - -export const StyledCheckbox = styled(Checkbox)(({ theme }) => ({ - padding: theme.spacing(0.75, 1), -})); diff --git a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx index fb69b74d38..0df18899c0 100644 --- a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx +++ b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureToggles.tsx @@ -9,7 +9,6 @@ import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightC import { FavoriteIconHeader } from 'component/common/Table/FavoriteIconHeader/FavoriteIconHeader'; import { FavoriteIconCell } from 'component/common/Table/cells/FavoriteIconCell/FavoriteIconCell'; import { ActionsCell } from '../ProjectFeatureToggles/ActionsCell/ActionsCell.tsx'; -import { ExperimentalColumnsMenu as ColumnsMenu } from './ExperimentalColumnsMenu/ExperimentalColumnsMenu.tsx'; import { useFavoriteFeaturesApi } from 'hooks/api/actions/useFavoriteFeaturesApi/useFavoriteFeaturesApi'; import { MemoizedRowSelectCell } from '../ProjectFeatureToggles/RowSelectCell/RowSelectCell.tsx'; import { BatchSelectionActionsBar } from 'component/common/BatchSelectionActionsBar/BatchSelectionActionsBar'; @@ -56,14 +55,13 @@ import { UPDATE_FEATURE } from '@server/types/permissions'; import { ImportModal } from '../Import/ImportModal.tsx'; import { IMPORT_BUTTON } from 'utils/testIds'; import { ProjectCleanupReminder } from './ProjectCleanupReminder/ProjectCleanupReminder.tsx'; +import { formatEnvironmentColumnId } from './formatEnvironmentColumnId.ts'; +import { ProjectFeaturesColumnsMenu } from './ProjectFeaturesColumnsMenu/ProjectFeaturesColumnsMenu.tsx'; type ProjectFeatureTogglesProps = { environments: string[]; }; -const formatEnvironmentColumnId = (environment: string) => - `environment:${environment}`; - const columnHelper = createColumnHelper(); const getRowId = (row: { name: string }) => row.name; @@ -514,50 +512,9 @@ export const ProjectFeatureToggles = ({ dataToExport={data} environmentsToExport={environments} actions={ - ({ - header: environment, - id: formatEnvironmentColumnId( - environment, - ), - isVisible: - columnVisibility[ - formatEnvironmentColumnId( - environment, - ) - ], - })), - ]} + } diff --git a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureTogglesHeader/FlagCreationButton/FlagCreationButton.tsx b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureTogglesHeader/FlagCreationButton/FlagCreationButton.tsx new file mode 100644 index 0000000000..9baf29000b --- /dev/null +++ b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureTogglesHeader/FlagCreationButton/FlagCreationButton.tsx @@ -0,0 +1,66 @@ +import { useState } from 'react'; +import Add from '@mui/icons-material/Add'; +import { styled } from '@mui/material'; +import ResponsiveButton from 'component/common/ResponsiveButton/ResponsiveButton'; +import { useSearchParams } from 'react-router-dom'; +import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; +import { CREATE_FEATURE } from 'component/providers/AccessProvider/permissions'; +import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; +import { CreateFeatureDialog } from '../CreateFeatureDialog.tsx'; +import type { OverridableStringUnion } from '@mui/types'; +import type { ButtonPropsVariantOverrides } from '@mui/material/Button/Button'; +import { NAVIGATE_TO_CREATE_FEATURE } from 'utils/testIds'; + +interface IFlagCreationButtonProps { + text?: string; + variant?: OverridableStringUnion< + 'text' | 'outlined' | 'contained', + ButtonPropsVariantOverrides + >; + skipNavigationOnComplete?: boolean; + isLoading?: boolean; + onSuccess?: () => void; +} + +const StyledResponsiveButton = styled(ResponsiveButton)(() => ({ + whiteSpace: 'nowrap', +})); + +export const FlagCreationButton = ({ + variant, + text = 'New feature flag', + skipNavigationOnComplete, + isLoading, + onSuccess, +}: IFlagCreationButtonProps) => { + const { loading } = useUiConfig(); + const [searchParams] = useSearchParams(); + const projectId = useRequiredPathParam('projectId'); + const showCreateDialog = Boolean(searchParams.get('create')); + const [openCreateDialog, setOpenCreateDialog] = useState(showCreateDialog); + + return ( + <> + setOpenCreateDialog(true)} + maxWidth='960px' + Icon={Add} + projectId={projectId} + disabled={loading || isLoading} + variant={variant} + permission={CREATE_FEATURE} + data-testid={ + loading || isLoading ? '' : NAVIGATE_TO_CREATE_FEATURE + } + > + {text} + + setOpenCreateDialog(false)} + skipNavigationOnComplete={skipNavigationOnComplete} + onSuccess={onSuccess} + /> + + ); +}; diff --git a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureTogglesHeader/ImportButton/ImportButton.tsx b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureTogglesHeader/ImportButton/ImportButton.tsx new file mode 100644 index 0000000000..1369de9b9e --- /dev/null +++ b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureTogglesHeader/ImportButton/ImportButton.tsx @@ -0,0 +1,35 @@ +import { type FC, useState } from 'react'; +import { ReactComponent as ImportSvg } from 'assets/icons/import.svg'; +import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; +import PermissionIconButton from 'component/common/PermissionIconButton/PermissionIconButton'; +import { UPDATE_FEATURE } from '@server/types/permissions'; + +import { ImportModal } from '../../../Import/ImportModal.tsx'; +import { IMPORT_BUTTON } from 'utils/testIds'; + +type ImportButtonProps = {}; + +export const ImportButton: FC = () => { + const projectId = useRequiredPathParam('projectId'); + const [modalOpen, setModalOpen] = useState(false); + + return ( + <> + setModalOpen(true)} + tooltipProps={{ title: 'Import' }} + data-testid={IMPORT_BUTTON} + data-loading-project + > + + + + + ); +}; diff --git a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureTogglesHeader/ProjectFeatureTogglesHeader.tsx b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureTogglesHeader/ProjectFeatureTogglesHeader.tsx index 0492c90724..6513c33aa1 100644 --- a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureTogglesHeader/ProjectFeatureTogglesHeader.tsx +++ b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeatureTogglesHeader/ProjectFeatureTogglesHeader.tsx @@ -1,7 +1,6 @@ import { type ReactNode, type FC, useState } from 'react'; import { Box, - Button, IconButton, Tooltip, useMediaQuery, @@ -11,24 +10,12 @@ import useLoading from 'hooks/useLoading'; import { PageHeader } from 'component/common/PageHeader/PageHeader'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { Search } from 'component/common/Search/Search'; -import { useUiFlag } from 'hooks/useUiFlag'; -import Add from '@mui/icons-material/Add'; -import { styled } from '@mui/material'; -import ResponsiveButton from 'component/common/ResponsiveButton/ResponsiveButton'; -import { useSearchParams } from 'react-router-dom'; import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; -import { CREATE_FEATURE } from 'component/providers/AccessProvider/permissions'; import { ExportDialog } from 'component/feature/FeatureToggleList/ExportDialog'; import type { FeatureSchema } from 'openapi'; import { usePlausibleTracker } from 'hooks/usePlausibleTracker'; -import ReviewsOutlined from '@mui/icons-material/ReviewsOutlined'; -import { useFeedback } from 'component/feedbackNew/useFeedback'; -import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; -import { CreateFeatureDialog } from './CreateFeatureDialog.tsx'; import IosShare from '@mui/icons-material/IosShare'; -import type { OverridableStringUnion } from '@mui/types'; -import type { ButtonPropsVariantOverrides } from '@mui/material/Button/Button'; -import { NAVIGATE_TO_CREATE_FEATURE } from 'utils/testIds'; +import { FlagCreationButton } from './FlagCreationButton/FlagCreationButton.tsx'; interface IProjectFeatureTogglesHeaderProps { isLoading?: boolean; @@ -40,60 +27,6 @@ interface IProjectFeatureTogglesHeaderProps { actions?: ReactNode; } -interface IFlagCreationButtonProps { - text?: string; - variant?: OverridableStringUnion< - 'text' | 'outlined' | 'contained', - ButtonPropsVariantOverrides - >; - skipNavigationOnComplete?: boolean; - isLoading?: boolean; - onSuccess?: () => void; -} - -const StyledResponsiveButton = styled(ResponsiveButton)(() => ({ - whiteSpace: 'nowrap', -})); - -export const FlagCreationButton = ({ - variant, - text = 'New feature flag', - skipNavigationOnComplete, - isLoading, - onSuccess, -}: IFlagCreationButtonProps) => { - const { loading } = useUiConfig(); - const [searchParams] = useSearchParams(); - const projectId = useRequiredPathParam('projectId'); - const showCreateDialog = Boolean(searchParams.get('create')); - const [openCreateDialog, setOpenCreateDialog] = useState(showCreateDialog); - - return ( - <> - setOpenCreateDialog(true)} - maxWidth='960px' - Icon={Add} - projectId={projectId} - disabled={loading || isLoading} - variant={variant} - permission={CREATE_FEATURE} - data-testid={ - loading || isLoading ? '' : NAVIGATE_TO_CREATE_FEATURE - } - > - {text} - - setOpenCreateDialog(false)} - skipNavigationOnComplete={skipNavigationOnComplete} - onSuccess={onSuccess} - /> - - ); -}; - export const ProjectFeatureTogglesHeader: FC< IProjectFeatureTogglesHeaderProps > = ({ @@ -111,10 +44,6 @@ export const ProjectFeatureTogglesHeader: FC< const isSmallScreen = useMediaQuery(theme.breakpoints.down('md')); const [showExportDialog, setShowExportDialog] = useState(false); const { trackEvent } = usePlausibleTracker(); - const projectOverviewRefactorFeedback = useUiFlag( - 'projectOverviewRefactorFeedback', - ); - const { openFeedback } = useFeedback('newProjectOverview', 'automatic'); const handleSearch = (query: string) => { onChangeSearchQuery?.(query); trackEvent('search-bar', { @@ -125,16 +54,6 @@ export const ProjectFeatureTogglesHeader: FC< }); }; - const createFeedbackContext = () => { - openFeedback({ - title: 'How easy was it to work with the project overview in Unleash?', - positiveLabel: - 'What do you like most about the updated project overview?', - areasForImprovementsLabel: - 'What improvements are needed in the project overview?', - }); - }; - return ( } /> - } - onClick={createFeedbackContext} - variant='outlined' - data-loading - > - Provide feedback - - } - /> } diff --git a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeaturesColumnsMenu/ProjectFeaturesColumnsMenu.tsx b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeaturesColumnsMenu/ProjectFeaturesColumnsMenu.tsx new file mode 100644 index 0000000000..17e829aa12 --- /dev/null +++ b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFeaturesColumnsMenu/ProjectFeaturesColumnsMenu.tsx @@ -0,0 +1,58 @@ +import type { FC } from 'react'; +import { ColumnsMenu } from '../ColumnsMenu/ColumnsMenu.tsx'; +import { formatEnvironmentColumnId } from '../formatEnvironmentColumnId.ts'; + +type ProjectFeaturesColumnsMenuProps = { + columnVisibility: Record; + environments: string[]; + onToggle: (id: string) => void; +}; + +export const ProjectFeaturesColumnsMenu: FC< + ProjectFeaturesColumnsMenuProps +> = ({ columnVisibility, environments, onToggle }) => { + return ( + ({ + header: environment, + id: formatEnvironmentColumnId(environment), + isVisible: + columnVisibility[ + formatEnvironmentColumnId(environment) + ], + })), + ]} + onToggle={onToggle} + /> + ); +}; diff --git a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFlagsSearch/ProjectFlagsSearch.tsx b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFlagsSearch/ProjectFlagsSearch.tsx new file mode 100644 index 0000000000..5b4323c099 --- /dev/null +++ b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/ProjectFlagsSearch/ProjectFlagsSearch.tsx @@ -0,0 +1,42 @@ +import type { FC } from 'react'; +import { Box } from '@mui/material'; +import { Search } from 'component/common/Search/Search'; +import useLoading from 'hooks/useLoading'; +import { usePlausibleTracker } from 'hooks/usePlausibleTracker'; + +interface IProjectFlagsSearchProps { + isLoading?: boolean; + searchQuery?: string; + onChangeSearchQuery?: (query: string) => void; +} + +export const ProjectFlagsSearch: FC = ({ + isLoading, + searchQuery, + onChangeSearchQuery, +}) => { + const headerLoadingRef = useLoading(isLoading || false); + const { trackEvent } = usePlausibleTracker(); + const handleSearch = (query: string) => { + onChangeSearchQuery?.(query); + trackEvent('search-bar', { + props: { + screen: 'project', + length: query.length, + }, + }); + }; + + return ( + + + + ); +}; diff --git a/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/formatEnvironmentColumnId.ts b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/formatEnvironmentColumnId.ts new file mode 100644 index 0000000000..035d2f1e3a --- /dev/null +++ b/frontend/src/component/project/Project/PaginatedProjectFeatureToggles/formatEnvironmentColumnId.ts @@ -0,0 +1,2 @@ +export const formatEnvironmentColumnId = (environment: string) => + `environment:${environment}`; diff --git a/frontend/src/component/project/Project/ProjectFeatureToggles/ColumnsMenu/ColumnsMenu.tsx b/frontend/src/component/project/Project/ProjectFeatureToggles/ColumnsMenu/ColumnsMenu.tsx deleted file mode 100644 index 952314a2b1..0000000000 --- a/frontend/src/component/project/Project/ProjectFeatureToggles/ColumnsMenu/ColumnsMenu.tsx +++ /dev/null @@ -1,212 +0,0 @@ -import { useEffect, useState, type VFC } from 'react'; -import { - IconButton, - ListItemIcon, - ListItemText, - MenuList, - Popover, - Tooltip, - Typography, - useMediaQuery, - useTheme, -} from '@mui/material'; -import ColumnIcon from '@mui/icons-material/ViewWeek'; -import CloseIcon from '@mui/icons-material/Close'; -import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; -import { - StyledBoxContainer, - StyledBoxMenuHeader, - StyledCheckbox, - StyledDivider, - StyledIconButton, - StyledMenuItem, -} from './ColumnsMenu.styles'; - -interface IColumnsMenuProps { - allColumns: { - Header?: string | any; - id: string; - isVisible: boolean; - toggleHidden: (state: boolean) => void; - hideInMenu?: boolean; - }[]; - staticColumns?: string[]; - dividerBefore?: string[]; - dividerAfter?: string[]; - isCustomized?: boolean; - setHiddenColumns: (hiddenColumns: string[]) => void; - onCustomize?: () => void; -} - -const columnNameMap: Record = { - favorite: 'Favorite', -}; - -export const ColumnsMenu: VFC = ({ - allColumns, - staticColumns = [], - dividerBefore = [], - dividerAfter = [], - isCustomized = false, - onCustomize, - setHiddenColumns, -}) => { - const [anchorEl, setAnchorEl] = useState(null); - const theme = useTheme(); - const isTinyScreen = useMediaQuery(theme.breakpoints.down('sm')); - const isSmallScreen = useMediaQuery(theme.breakpoints.down('md')); - const isMediumScreen = useMediaQuery(theme.breakpoints.down('lg')); - - useEffect(() => { - if (isCustomized) { - return; - } - - const setVisibleColumns = ( - columns: string[], - environmentsToShow: number = 0, - ) => { - const visibleEnvColumns = allColumns - .filter(({ id }) => id.startsWith('environment:') !== false) - .map(({ id }) => id) - .slice(0, environmentsToShow); - const hiddenColumns = allColumns - .map(({ id }) => id) - .filter((id) => !columns.includes(id)) - .filter((id) => !staticColumns.includes(id)) - .filter((id) => !visibleEnvColumns.includes(id)); - setHiddenColumns(hiddenColumns); - }; - - if (isTinyScreen) { - return setVisibleColumns(['createdAt']); - } - if (isSmallScreen) { - return setVisibleColumns(['createdAt'], 1); - } - if (isMediumScreen) { - return setVisibleColumns(['type', 'createdAt'], 1); - } - setVisibleColumns(['lastSeenAt', 'type', 'createdAt'], 3); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isTinyScreen, isSmallScreen, isMediumScreen]); - - const handleClick = (event: React.MouseEvent) => { - setAnchorEl(event.currentTarget); - }; - - const handleClose = () => { - setAnchorEl(null); - }; - - const isOpen = Boolean(anchorEl); - const id = `columns-menu`; - const menuId = `columns-menu-list-${id}`; - - return ( - - - - - - - - ({ - borderRadius: theme.shape.borderRadius, - paddingBottom: theme.spacing(2), - }), - }} - > - - - Columns - - - - - - - {allColumns - .filter(({ hideInMenu }) => !hideInMenu) - .map((column) => [ - } - />, - { - column.toggleHidden(column.isVisible); - onCustomize?.(); - }} - disabled={staticColumns.includes(column.id)} - > - - - - - ( - <>{column.Header} - )} - elseShow={() => ( - <> - {columnNameMap[ - column.id - ] || column.id} - - )} - /> - - } - /> - , - } - />, - ])} - - - - ); -}; diff --git a/frontend/src/interfaces/uiConfig.ts b/frontend/src/interfaces/uiConfig.ts index d82840c60b..9864bb3e9f 100644 --- a/frontend/src/interfaces/uiConfig.ts +++ b/frontend/src/interfaces/uiConfig.ts @@ -74,7 +74,6 @@ export type UiFlags = { outdatedSdksBanner?: boolean; estimateTrafficDataCost?: boolean; disableShowContextFieldSelectionValues?: boolean; - projectOverviewRefactorFeedback?: boolean; featureLifecycle?: boolean; manyStrategiesPagination?: boolean; enableLegacyVariants?: boolean;