mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-14 01:16:17 +02:00
chore: remove flagsReleaseManagementUI and flagsOverviewSearch flags (#10011)
Removing the `flagsReleaseManagementUI` and `flagsOverviewSearch` feature flags - we're keeping these enabled.
This commit is contained in:
parent
8afaf7e88b
commit
b0954f213c
@ -18,15 +18,6 @@ type APIProject = {
|
|||||||
id: string;
|
id: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type UIFeature = {
|
|
||||||
name: string;
|
|
||||||
segments: string;
|
|
||||||
tags: string;
|
|
||||||
createdAt: string;
|
|
||||||
project: string;
|
|
||||||
state: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const server = testServerSetup();
|
const server = testServerSetup();
|
||||||
|
|
||||||
const setupNoFeaturesReturned = () =>
|
const setupNoFeaturesReturned = () =>
|
||||||
@ -74,27 +65,6 @@ const setupApi = (features: APIFeature[], projects: APIProject[]) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const verifyTableFeature = async (feature: Partial<UIFeature>) => {
|
|
||||||
await screen.findByText('Search');
|
|
||||||
await screen.findByText('Filter');
|
|
||||||
await Promise.all(
|
|
||||||
Object.values(feature).map((value) => screen.findByText(value)),
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const filterFeaturesByProject = async (projectName: string) => {
|
|
||||||
const addFilterButton = screen.getByText('Filter');
|
|
||||||
addFilterButton.click();
|
|
||||||
|
|
||||||
const projectItem = await screen.findByText('Project');
|
|
||||||
fireEvent.click(projectItem);
|
|
||||||
|
|
||||||
await screen.findByPlaceholderText('Search');
|
|
||||||
const anotherProjectCheckbox = await screen.findByText(projectName);
|
|
||||||
|
|
||||||
anotherProjectCheckbox.click();
|
|
||||||
};
|
|
||||||
|
|
||||||
test('Filter table by project', async () => {
|
test('Filter table by project', async () => {
|
||||||
setupApi(
|
setupApi(
|
||||||
[
|
[
|
||||||
@ -124,17 +94,33 @@ test('Filter table by project', async () => {
|
|||||||
</FeedbackProvider>,
|
</FeedbackProvider>,
|
||||||
);
|
);
|
||||||
|
|
||||||
await verifyTableFeature({
|
await screen.findByPlaceholderText(/Search/);
|
||||||
name: 'Operational Feature',
|
await screen.getByRole('button', {
|
||||||
createdAt: '11/03/2023',
|
name: /Filter/i,
|
||||||
segments: '1 segment',
|
|
||||||
tags: '1 tag',
|
|
||||||
project: 'project-a',
|
|
||||||
state: 'Active',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
Object.values({
|
||||||
|
name: 'Operational Feature',
|
||||||
|
createdAt: '11/03/2023',
|
||||||
|
project: 'project-a',
|
||||||
|
}).map((value) => screen.findByText(value)),
|
||||||
|
);
|
||||||
|
|
||||||
setupNoFeaturesReturned();
|
setupNoFeaturesReturned();
|
||||||
await filterFeaturesByProject('Project B');
|
|
||||||
|
const addFilterButton = screen.getByText('Filter');
|
||||||
|
addFilterButton.click();
|
||||||
|
|
||||||
|
const projectItem = await screen.findByRole('menuitem', {
|
||||||
|
name: 'Project',
|
||||||
|
});
|
||||||
|
fireEvent.click(projectItem);
|
||||||
|
|
||||||
|
await screen.findByPlaceholderText('Search');
|
||||||
|
const anotherProjectCheckbox = await screen.findByText('Project B');
|
||||||
|
|
||||||
|
anotherProjectCheckbox.click();
|
||||||
|
|
||||||
await screen.findByText('No feature flags found matching your criteria.');
|
await screen.findByText('No feature flags found matching your criteria.');
|
||||||
expect(window.location.href).toContain(
|
expect(window.location.href).toContain(
|
||||||
|
@ -6,31 +6,22 @@ import { PaginatedTable, TablePlaceholder } from 'component/common/Table';
|
|||||||
import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
||||||
import { DateCell } from 'component/common/Table/cells/DateCell/DateCell';
|
import { DateCell } from 'component/common/Table/cells/DateCell/DateCell';
|
||||||
import { LinkCell } from 'component/common/Table/cells/LinkCell/LinkCell';
|
import { LinkCell } from 'component/common/Table/cells/LinkCell/LinkCell';
|
||||||
import { FeatureTypeCell } from 'component/common/Table/cells/FeatureTypeCell/FeatureTypeCell';
|
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||||
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
||||||
import type { FeatureSchema, FeatureSearchResponseSchema } from 'openapi';
|
import type { FeatureSchema, FeatureSearchResponseSchema } from 'openapi';
|
||||||
import { FeatureStaleCell } from './FeatureStaleCell/FeatureStaleCell.tsx';
|
|
||||||
import { Search } from 'component/common/Search/Search';
|
import { Search } from 'component/common/Search/Search';
|
||||||
import { useFavoriteFeaturesApi } from 'hooks/api/actions/useFavoriteFeaturesApi/useFavoriteFeaturesApi';
|
import { useFavoriteFeaturesApi } from 'hooks/api/actions/useFavoriteFeaturesApi/useFavoriteFeaturesApi';
|
||||||
import { FavoriteIconCell } from 'component/common/Table/cells/FavoriteIconCell/FavoriteIconCell';
|
import { FavoriteIconCell } from 'component/common/Table/cells/FavoriteIconCell/FavoriteIconCell';
|
||||||
import { FavoriteIconHeader } from 'component/common/Table/FavoriteIconHeader/FavoriteIconHeader';
|
import { FavoriteIconHeader } from 'component/common/Table/FavoriteIconHeader/FavoriteIconHeader';
|
||||||
import { useEnvironments } from 'hooks/api/getters/useEnvironments/useEnvironments';
|
import { useEnvironments } from 'hooks/api/getters/useEnvironments/useEnvironments';
|
||||||
import { ExportDialog } from './ExportDialog.tsx';
|
import { ExportDialog } from './ExportDialog.tsx';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
import { focusable } from 'themes/themeStyles';
|
import { focusable } from 'themes/themeStyles';
|
||||||
import {
|
import { FeatureLifecycleCell } from 'component/common/Table/cells/FeatureSeenCell/FeatureEnvironmentSeenCell';
|
||||||
FeatureEnvironmentSeenCell,
|
|
||||||
FeatureLifecycleCell,
|
|
||||||
} from 'component/common/Table/cells/FeatureSeenCell/FeatureEnvironmentSeenCell';
|
|
||||||
import useToast from 'hooks/useToast';
|
import useToast from 'hooks/useToast';
|
||||||
import { FeatureToggleFilters } from './FeatureToggleFilters/FeatureToggleFilters.tsx';
|
import { FeatureToggleFilters } from './FeatureToggleFilters/FeatureToggleFilters.tsx';
|
||||||
import { withTableState } from 'utils/withTableState';
|
import { withTableState } from 'utils/withTableState';
|
||||||
import { FeatureTagCell } from 'component/common/Table/cells/FeatureTagCell/FeatureTagCell';
|
|
||||||
import { FeatureSegmentCell } from 'component/common/Table/cells/FeatureSegmentCell/FeatureSegmentCell';
|
|
||||||
import { FeatureToggleListActions } from './FeatureToggleListActions/FeatureToggleListActions.tsx';
|
|
||||||
import useLoading from 'hooks/useLoading';
|
import useLoading from 'hooks/useLoading';
|
||||||
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||||
import {
|
import {
|
||||||
@ -80,9 +71,6 @@ export const FeatureToggleListTable: FC = () => {
|
|||||||
const [showExportDialog, setShowExportDialog] = useState(false);
|
const [showExportDialog, setShowExportDialog] = useState(false);
|
||||||
|
|
||||||
const { setToastApiError } = useToast();
|
const { setToastApiError } = useToast();
|
||||||
const flagsReleaseManagementUIEnabled = useUiFlag(
|
|
||||||
'flagsReleaseManagementUI',
|
|
||||||
);
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
features,
|
features,
|
||||||
@ -126,18 +114,17 @@ export const FeatureToggleListTable: FC = () => {
|
|||||||
[favorite, refetchFeatures, unfavorite, setToastApiError],
|
[favorite, refetchFeatures, unfavorite, setToastApiError],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const showStatusColumn = !isOss();
|
||||||
|
|
||||||
const columns = useMemo(
|
const columns = useMemo(
|
||||||
() =>
|
() => [
|
||||||
flagsReleaseManagementUIEnabled
|
|
||||||
? [
|
|
||||||
columnHelper.accessor('favorite', {
|
columnHelper.accessor('favorite', {
|
||||||
header: () => (
|
header: () => (
|
||||||
<FavoriteIconHeader
|
<FavoriteIconHeader
|
||||||
isActive={tableState.favoritesFirst}
|
isActive={tableState.favoritesFirst}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setTableState({
|
setTableState({
|
||||||
favoritesFirst:
|
favoritesFirst: !tableState.favoritesFirst,
|
||||||
!tableState.favoritesFirst,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@ -153,17 +140,12 @@ export const FeatureToggleListTable: FC = () => {
|
|||||||
}),
|
}),
|
||||||
columnHelper.accessor('name', {
|
columnHelper.accessor('name', {
|
||||||
header: 'Name',
|
header: 'Name',
|
||||||
cell: createFeatureOverviewCell(
|
cell: createFeatureOverviewCell(onTagClick, onFlagTypeClick),
|
||||||
onTagClick,
|
|
||||||
onFlagTypeClick,
|
|
||||||
),
|
|
||||||
meta: { width: '40%' },
|
meta: { width: '40%' },
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor('createdAt', {
|
columnHelper.accessor('createdAt', {
|
||||||
header: 'Created',
|
header: 'Created',
|
||||||
cell: ({ getValue }) => (
|
cell: ({ getValue }) => <DateCell value={getValue()} />,
|
||||||
<DateCell value={getValue()} />
|
|
||||||
),
|
|
||||||
meta: { width: '1%' },
|
meta: { width: '1%' },
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor('createdBy', {
|
columnHelper.accessor('createdBy', {
|
||||||
@ -187,7 +169,7 @@ export const FeatureToggleListTable: FC = () => {
|
|||||||
size: 50,
|
size: 50,
|
||||||
meta: { width: '1%' },
|
meta: { width: '1%' },
|
||||||
}),
|
}),
|
||||||
...(!isOss()
|
...(showStatusColumn
|
||||||
? [
|
? [
|
||||||
columnHelper.accessor('environments', {
|
columnHelper.accessor('environments', {
|
||||||
id: 'status',
|
id: 'status',
|
||||||
@ -218,136 +200,8 @@ export const FeatureToggleListTable: FC = () => {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]
|
|
||||||
: [
|
|
||||||
columnHelper.accessor('favorite', {
|
|
||||||
header: () => (
|
|
||||||
<FavoriteIconHeader
|
|
||||||
isActive={tableState.favoritesFirst}
|
|
||||||
onClick={() =>
|
|
||||||
setTableState({
|
|
||||||
favoritesFirst:
|
|
||||||
!tableState.favoritesFirst,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
cell: ({ getValue, row }) => (
|
|
||||||
<>
|
|
||||||
<FavoriteIconCell
|
|
||||||
value={getValue()}
|
|
||||||
onClick={() => onFavorite(row.original)}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
enableSorting: false,
|
|
||||||
meta: {
|
|
||||||
width: '1%',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
columnHelper.accessor('lastSeenAt', {
|
|
||||||
header: 'Seen',
|
|
||||||
cell: ({ row }) => (
|
|
||||||
<FeatureEnvironmentSeenCell
|
|
||||||
feature={row.original}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
meta: {
|
|
||||||
align: 'center',
|
|
||||||
width: '1%',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
columnHelper.accessor('type', {
|
|
||||||
header: 'Type',
|
|
||||||
cell: ({ getValue }) => (
|
|
||||||
<FeatureTypeCell value={getValue()} />
|
|
||||||
),
|
|
||||||
meta: {
|
|
||||||
align: 'center',
|
|
||||||
width: '1%',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
|
|
||||||
columnHelper.accessor('name', {
|
|
||||||
header: 'Name',
|
|
||||||
cell: ({ row }) => (
|
|
||||||
<LinkCell
|
|
||||||
title={row.original.name}
|
|
||||||
subtitle={
|
|
||||||
row.original.description || undefined
|
|
||||||
}
|
|
||||||
to={`/projects/${row.original.project}/features/${row.original.name}`}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
meta: {
|
|
||||||
width: '50%',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
columnHelper.accessor(
|
|
||||||
(row) => row.segments?.join('\n') || '',
|
|
||||||
{
|
|
||||||
header: 'Segments',
|
|
||||||
cell: ({ getValue, row }) => (
|
|
||||||
<FeatureSegmentCell
|
|
||||||
value={getValue()}
|
|
||||||
row={row}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
enableSorting: false,
|
|
||||||
meta: {
|
|
||||||
width: '1%',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
),
|
|
||||||
columnHelper.accessor(
|
|
||||||
(row) =>
|
|
||||||
row.tags
|
|
||||||
?.map(({ type, value }) => `${type}:${value}`)
|
|
||||||
.join('\n') || '',
|
|
||||||
{
|
|
||||||
header: 'Tags',
|
|
||||||
cell: FeatureTagCell,
|
|
||||||
enableSorting: false,
|
|
||||||
meta: {
|
|
||||||
width: '1%',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
),
|
|
||||||
columnHelper.accessor('createdAt', {
|
|
||||||
header: 'Created',
|
|
||||||
cell: ({ getValue }) => (
|
|
||||||
<DateCell value={getValue()} />
|
|
||||||
),
|
|
||||||
meta: {
|
|
||||||
width: '1%',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
columnHelper.accessor('project', {
|
|
||||||
header: 'Project ID',
|
|
||||||
cell: ({ getValue }) => {
|
|
||||||
const value = getValue();
|
|
||||||
return (
|
|
||||||
<LinkCell
|
|
||||||
title={value}
|
|
||||||
to={`/projects/${value}`}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
meta: {
|
|
||||||
width: '1%',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
columnHelper.accessor('stale', {
|
|
||||||
header: 'State',
|
|
||||||
cell: ({ getValue }) => (
|
|
||||||
<FeatureStaleCell value={getValue()} />
|
|
||||||
),
|
|
||||||
meta: {
|
|
||||||
width: '1%',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
],
|
],
|
||||||
[tableState.favoritesFirst],
|
[tableState.favoritesFirst, showStatusColumn],
|
||||||
);
|
);
|
||||||
const data = useMemo<FeatureSearchResponseSchema[]>(
|
const data = useMemo<FeatureSearchResponseSchema[]>(
|
||||||
() =>
|
() =>
|
||||||
@ -402,26 +256,9 @@ export const FeatureToggleListTable: FC = () => {
|
|||||||
bodyClass='no-padding'
|
bodyClass='no-padding'
|
||||||
header={
|
header={
|
||||||
<PageHeader
|
<PageHeader
|
||||||
title={
|
title='Flags overview'
|
||||||
flagsReleaseManagementUIEnabled
|
|
||||||
? 'Flags overview'
|
|
||||||
: 'Search'
|
|
||||||
}
|
|
||||||
actions={
|
actions={
|
||||||
<>
|
<>
|
||||||
{!flagsReleaseManagementUIEnabled &&
|
|
||||||
!isSmallScreen ? (
|
|
||||||
<>
|
|
||||||
<Search
|
|
||||||
placeholder='Search'
|
|
||||||
expandable
|
|
||||||
initialValue={tableState.query || ''}
|
|
||||||
onChange={setSearchValue}
|
|
||||||
id='globalFeatureFlags'
|
|
||||||
/>
|
|
||||||
<PageHeader.Divider />
|
|
||||||
</>
|
|
||||||
) : null}
|
|
||||||
<Link
|
<Link
|
||||||
component={RouterLink}
|
component={RouterLink}
|
||||||
to='/archive'
|
to='/archive'
|
||||||
@ -437,36 +274,14 @@ export const FeatureToggleListTable: FC = () => {
|
|||||||
>
|
>
|
||||||
View archive
|
View archive
|
||||||
</Link>
|
</Link>
|
||||||
{flagsReleaseManagementUIEnabled ? (
|
|
||||||
<ExportFlags
|
<ExportFlags
|
||||||
onClick={() => setShowExportDialog(true)}
|
onClick={() => setShowExportDialog(true)}
|
||||||
/>
|
/>
|
||||||
) : (
|
|
||||||
<FeatureToggleListActions
|
|
||||||
onExportClick={() =>
|
|
||||||
setShowExportDialog(true)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={
|
|
||||||
isSmallScreen && !flagsReleaseManagementUIEnabled
|
|
||||||
}
|
|
||||||
show={
|
|
||||||
<Search
|
|
||||||
initialValue={tableState.query || ''}
|
|
||||||
onChange={setSearchValue}
|
|
||||||
id='globalFeatureFlags'
|
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
|
||||||
</PageHeader>
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{flagsReleaseManagementUIEnabled ? (
|
|
||||||
<LifecycleFilters
|
<LifecycleFilters
|
||||||
state={filterState}
|
state={filterState}
|
||||||
onChange={setTableState}
|
onChange={setTableState}
|
||||||
@ -481,7 +296,6 @@ export const FeatureToggleListTable: FC = () => {
|
|||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</LifecycleFilters>
|
</LifecycleFilters>
|
||||||
) : null}
|
|
||||||
<FeatureToggleFilters
|
<FeatureToggleFilters
|
||||||
onChange={setTableState}
|
onChange={setTableState}
|
||||||
state={filterState}
|
state={filterState}
|
||||||
|
@ -14,7 +14,6 @@ import ServiceAccountIcon from '@mui/icons-material/Computer';
|
|||||||
import GroupsIcon from '@mui/icons-material/GroupsOutlined';
|
import GroupsIcon from '@mui/icons-material/GroupsOutlined';
|
||||||
import RoleIcon from '@mui/icons-material/AdminPanelSettingsOutlined';
|
import RoleIcon from '@mui/icons-material/AdminPanelSettingsOutlined';
|
||||||
import SettingsIcon from '@mui/icons-material/Settings';
|
import SettingsIcon from '@mui/icons-material/Settings';
|
||||||
import SearchIcon from '@mui/icons-material/Search';
|
|
||||||
import InsightsIcon from '@mui/icons-material/Insights';
|
import InsightsIcon from '@mui/icons-material/Insights';
|
||||||
import ApiAccessIcon from '@mui/icons-material/KeyOutlined';
|
import ApiAccessIcon from '@mui/icons-material/KeyOutlined';
|
||||||
import SingleSignOnIcon from '@mui/icons-material/AssignmentOutlined';
|
import SingleSignOnIcon from '@mui/icons-material/AssignmentOutlined';
|
||||||
@ -35,14 +34,13 @@ import PersonalDashboardIcon from '@mui/icons-material/DashboardOutlined';
|
|||||||
import { ProjectIcon } from 'component/common/ProjectIcon/ProjectIcon';
|
import { ProjectIcon } from 'component/common/ProjectIcon/ProjectIcon';
|
||||||
import PlaygroundIcon from '@mui/icons-material/AutoFixNormal';
|
import PlaygroundIcon from '@mui/icons-material/AutoFixNormal';
|
||||||
import FlagOutlinedIcon from '@mui/icons-material/FlagOutlined';
|
import FlagOutlinedIcon from '@mui/icons-material/FlagOutlined';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
|
|
||||||
// TODO: move to routes
|
// TODO: move to routes
|
||||||
const icons: Record<
|
const icons: Record<
|
||||||
string,
|
string,
|
||||||
typeof SvgIcon | FC<ComponentProps<typeof SvgIcon>>
|
typeof SvgIcon | FC<ComponentProps<typeof SvgIcon>>
|
||||||
> = {
|
> = {
|
||||||
'/search': SearchIcon,
|
'/search': FlagOutlinedIcon,
|
||||||
'/insights': InsightsIcon,
|
'/insights': InsightsIcon,
|
||||||
'/applications': ApplicationsIcon,
|
'/applications': ApplicationsIcon,
|
||||||
'/context': ContextFieldsIcon,
|
'/context': ContextFieldsIcon,
|
||||||
@ -89,12 +87,7 @@ const icons: Record<
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const IconRenderer: FC<{ path: string }> = ({ path }) => {
|
export const IconRenderer: FC<{ path: string }> = ({ path }) => {
|
||||||
const flagsReleaseManagementUI = useUiFlag('flagsReleaseManagementUI');
|
|
||||||
const IconComponent = useMemo(() => icons[path] || EmptyIcon, [path]); // Fallback to 'default' if the type is not found
|
const IconComponent = useMemo(() => icons[path] || EmptyIcon, [path]); // Fallback to 'default' if the type is not found
|
||||||
|
|
||||||
if (flagsReleaseManagementUI && path === '/search') {
|
|
||||||
return <FlagOutlinedIcon />;
|
|
||||||
}
|
|
||||||
|
|
||||||
return <IconComponent />;
|
return <IconComponent />;
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,6 @@ import {
|
|||||||
SignOutItem,
|
SignOutItem,
|
||||||
} from './ListItems.tsx';
|
} from './ListItems.tsx';
|
||||||
import { Box, List, Typography } from '@mui/material';
|
import { Box, List, Typography } from '@mui/material';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
|
||||||
import { IconRenderer } from './IconRenderer.tsx';
|
import { IconRenderer } from './IconRenderer.tsx';
|
||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
import Accordion from '@mui/material/Accordion';
|
import Accordion from '@mui/material/Accordion';
|
||||||
@ -127,7 +126,6 @@ export const PrimaryNavigationList: FC<{
|
|||||||
}> = ({ mode, onClick, activeItem }) => {
|
}> = ({ mode, onClick, activeItem }) => {
|
||||||
const DynamicListItem = mode === 'mini' ? MiniListItem : FullListItem;
|
const DynamicListItem = mode === 'mini' ? MiniListItem : FullListItem;
|
||||||
const { isOss } = useUiConfig();
|
const { isOss } = useUiConfig();
|
||||||
const flagsReleaseManagementUI = useUiFlag('flagsReleaseManagementUI');
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<List>
|
<List>
|
||||||
@ -150,7 +148,7 @@ export const PrimaryNavigationList: FC<{
|
|||||||
</DynamicListItem>
|
</DynamicListItem>
|
||||||
<DynamicListItem
|
<DynamicListItem
|
||||||
href='/search'
|
href='/search'
|
||||||
text={flagsReleaseManagementUI ? 'Flags overview' : 'Search'}
|
text='Flags overview'
|
||||||
onClick={() => onClick('/search')}
|
onClick={() => onClick('/search')}
|
||||||
selected={activeItem === '/search'}
|
selected={activeItem === '/search'}
|
||||||
>
|
>
|
||||||
|
@ -69,7 +69,7 @@ test('select active item', async () => {
|
|||||||
{ route: '/search' },
|
{ route: '/search' },
|
||||||
);
|
);
|
||||||
|
|
||||||
const searchLink = screen.getByRole('link', { name: 'Search' });
|
const searchLink = screen.getByRole('link', { name: 'Flags overview' });
|
||||||
|
|
||||||
expect(searchLink).toHaveClass(classes.selected);
|
expect(searchLink).toHaveClass(classes.selected);
|
||||||
});
|
});
|
||||||
|
@ -15,8 +15,8 @@ exports[`order of items in navigation > menu for enterprise plan 1`] = `
|
|||||||
"text": "Projects",
|
"text": "Projects",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"icon": "SearchIcon",
|
"icon": "FlagOutlinedIcon",
|
||||||
"text": "Search",
|
"text": "Flags overview",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"icon": "AutoFixNormalIcon",
|
"icon": "AutoFixNormalIcon",
|
||||||
@ -80,8 +80,8 @@ exports[`order of items in navigation > menu for open-source 1`] = `
|
|||||||
"text": "Projects",
|
"text": "Projects",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"icon": "SearchIcon",
|
"icon": "FlagOutlinedIcon",
|
||||||
"text": "Search",
|
"text": "Flags overview",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"icon": "AutoFixNormalIcon",
|
"icon": "AutoFixNormalIcon",
|
||||||
@ -137,8 +137,8 @@ exports[`order of items in navigation > menu for pro plan 1`] = `
|
|||||||
"text": "Projects",
|
"text": "Projects",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"icon": "SearchIcon",
|
"icon": "FlagOutlinedIcon",
|
||||||
"text": "Search",
|
"text": "Flags overview",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"icon": "AutoFixNormalIcon",
|
"icon": "AutoFixNormalIcon",
|
||||||
|
@ -104,17 +104,6 @@ exports[`returns all baseRoutes 1`] = `
|
|||||||
"menu": {
|
"menu": {
|
||||||
"primary": true,
|
"primary": true,
|
||||||
},
|
},
|
||||||
"notFlag": "flagsReleaseManagementUI",
|
|
||||||
"path": "/search",
|
|
||||||
"title": "Search",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"flag": "flagsReleaseManagementUI",
|
|
||||||
"menu": {
|
|
||||||
"primary": true,
|
|
||||||
},
|
|
||||||
"path": "/search",
|
"path": "/search",
|
||||||
"title": "Flags overview",
|
"title": "Flags overview",
|
||||||
"type": "protected",
|
"type": "protected",
|
||||||
|
@ -130,21 +130,12 @@ export const routes: IRoute[] = [
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Flags overview
|
// Flags overview
|
||||||
{
|
|
||||||
path: '/search',
|
|
||||||
title: 'Search',
|
|
||||||
component: FeatureToggleListTable,
|
|
||||||
type: 'protected',
|
|
||||||
menu: { primary: true },
|
|
||||||
notFlag: 'flagsReleaseManagementUI',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/search',
|
path: '/search',
|
||||||
title: 'Flags overview',
|
title: 'Flags overview',
|
||||||
component: FeatureToggleListTable,
|
component: FeatureToggleListTable,
|
||||||
type: 'protected',
|
type: 'protected',
|
||||||
menu: { primary: true },
|
menu: { primary: true },
|
||||||
flag: 'flagsReleaseManagementUI',
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Playground
|
// Playground
|
||||||
|
@ -5,11 +5,11 @@ import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip';
|
|||||||
import { UserAvatar } from 'component/common/UserAvatar/UserAvatar';
|
import { UserAvatar } from 'component/common/UserAvatar/UserAvatar';
|
||||||
|
|
||||||
type AvatarCellProps = {
|
type AvatarCellProps = {
|
||||||
row: {
|
row?: {
|
||||||
original: {
|
original?: {
|
||||||
createdBy: {
|
createdBy?: {
|
||||||
id: number;
|
id?: number;
|
||||||
name: string;
|
name?: string;
|
||||||
imageUrl?: string;
|
imageUrl?: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -42,35 +42,39 @@ const StyledAvatar = styled(UserAvatar)(({ theme }) => ({
|
|||||||
|
|
||||||
export const AvatarCell =
|
export const AvatarCell =
|
||||||
(onAvatarClick?: (userId: number) => void): FC<AvatarCellProps> =>
|
(onAvatarClick?: (userId: number) => void): FC<AvatarCellProps> =>
|
||||||
({ row: { original } }) => {
|
({ row }) => {
|
||||||
const ariaDisabled = original.createdBy.id === 0;
|
const createdBy = {
|
||||||
|
id: 0,
|
||||||
|
name: '',
|
||||||
|
imageUrl: '',
|
||||||
|
...row?.original?.createdBy,
|
||||||
|
};
|
||||||
|
const ariaDisabled = createdBy.id === 0;
|
||||||
const clickAction = ariaDisabled
|
const clickAction = ariaDisabled
|
||||||
? () => {}
|
? () => {}
|
||||||
: () => onAvatarClick?.(original.createdBy.id);
|
: () => onAvatarClick?.(createdBy.id);
|
||||||
const tooltipContent = ariaDisabled ? (
|
const tooltipContent = ariaDisabled ? (
|
||||||
<>
|
<>
|
||||||
<p>{original.createdBy.name}</p>
|
<p>{createdBy.name}</p>
|
||||||
<StyledSecondaryText>
|
<StyledSecondaryText>
|
||||||
You can't filter by unknown users.
|
You can't filter by unknown users.
|
||||||
</StyledSecondaryText>
|
</StyledSecondaryText>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<p>{original.createdBy.name}</p>
|
<p>{createdBy.name}</p>
|
||||||
);
|
);
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<>
|
<>
|
||||||
<ScreenReaderOnly>
|
<ScreenReaderOnly>
|
||||||
<span>
|
<span>Show only flags created by {createdBy.name}</span>
|
||||||
Show only flags created by {original.createdBy.name}
|
|
||||||
</span>
|
|
||||||
</ScreenReaderOnly>
|
</ScreenReaderOnly>
|
||||||
<StyledAvatar
|
<StyledAvatar
|
||||||
disableTooltip
|
disableTooltip
|
||||||
user={{
|
user={{
|
||||||
id: original.createdBy.id,
|
id: createdBy.id,
|
||||||
name: original.createdBy.name,
|
name: createdBy.name,
|
||||||
imageUrl: original.createdBy.imageUrl,
|
imageUrl: createdBy.imageUrl,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
@ -87,7 +87,6 @@ export type UiFlags = {
|
|||||||
consumptionModel?: boolean;
|
consumptionModel?: boolean;
|
||||||
edgeObservability?: boolean;
|
edgeObservability?: boolean;
|
||||||
addEditStrategy?: boolean;
|
addEditStrategy?: boolean;
|
||||||
flagsReleaseManagementUI?: boolean;
|
|
||||||
cleanupReminder?: boolean;
|
cleanupReminder?: boolean;
|
||||||
registerFrontendClient?: boolean;
|
registerFrontendClient?: boolean;
|
||||||
featureLinks?: boolean;
|
featureLinks?: boolean;
|
||||||
|
@ -268,7 +268,6 @@ class FeatureSearchStore implements IFeatureSearchStore {
|
|||||||
'lifecycle.stage_feature',
|
'lifecycle.stage_feature',
|
||||||
);
|
);
|
||||||
|
|
||||||
if (this.flagResolver.isEnabled('flagsOverviewSearch')) {
|
|
||||||
const parsedLifecycle = lifecycle
|
const parsedLifecycle = lifecycle
|
||||||
? parseSearchOperatorValue(
|
? parseSearchOperatorValue(
|
||||||
'lifecycle.latest_stage',
|
'lifecycle.latest_stage',
|
||||||
@ -278,7 +277,6 @@ class FeatureSearchStore implements IFeatureSearchStore {
|
|||||||
if (parsedLifecycle) {
|
if (parsedLifecycle) {
|
||||||
applyGenericQueryParams(query, [parsedLifecycle]);
|
applyGenericQueryParams(query, [parsedLifecycle]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const rankingSql = this.buildRankingSql(
|
const rankingSql = this.buildRankingSql(
|
||||||
favoritesFirst,
|
favoritesFirst,
|
||||||
@ -342,10 +340,8 @@ class FeatureSearchStore implements IFeatureSearchStore {
|
|||||||
.whereBetween('final_rank', [offset + 1, offset + limit])
|
.whereBetween('final_rank', [offset + 1, offset + limit])
|
||||||
.orderBy('final_rank');
|
.orderBy('final_rank');
|
||||||
|
|
||||||
if (this.flagResolver.isEnabled('flagsOverviewSearch')) {
|
|
||||||
this.buildChangeRequestSql(finalQuery);
|
this.buildChangeRequestSql(finalQuery);
|
||||||
this.buildReleasePlanSql(finalQuery);
|
this.buildReleasePlanSql(finalQuery);
|
||||||
}
|
|
||||||
|
|
||||||
this.queryExtraData(finalQuery);
|
this.queryExtraData(finalQuery);
|
||||||
const rows = await finalQuery;
|
const rows = await finalQuery;
|
||||||
|
@ -31,7 +31,6 @@ beforeAll(async () => {
|
|||||||
flags: {
|
flags: {
|
||||||
strictSchemaValidation: true,
|
strictSchemaValidation: true,
|
||||||
anonymiseEventLog: true,
|
anonymiseEventLog: true,
|
||||||
flagsOverviewSearch: true,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -58,8 +58,6 @@ export type IFlagKey =
|
|||||||
| 'teamsIntegrationChangeRequests'
|
| 'teamsIntegrationChangeRequests'
|
||||||
| 'edgeObservability'
|
| 'edgeObservability'
|
||||||
| 'addEditStrategy'
|
| 'addEditStrategy'
|
||||||
| 'flagsOverviewSearch'
|
|
||||||
| 'flagsReleaseManagementUI'
|
|
||||||
| 'cleanupReminder'
|
| 'cleanupReminder'
|
||||||
| 'removeInactiveApplications'
|
| 'removeInactiveApplications'
|
||||||
| 'registerFrontendClient'
|
| 'registerFrontendClient'
|
||||||
@ -280,14 +278,7 @@ const flags: IFlags = {
|
|||||||
process.env.UNLEASH_EXPERIMENTAL_ADD_EDIT_STRATEGY,
|
process.env.UNLEASH_EXPERIMENTAL_ADD_EDIT_STRATEGY,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
flagsOverviewSearch: parseEnvVarBoolean(
|
|
||||||
process.env.UNLEASH_EXPERIMENTAL_FLAGS_OVERVIEW_SEARCH,
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
flagsReleaseManagementUI: parseEnvVarBoolean(
|
|
||||||
process.env.UNLEASH_EXPERIMENTAL_FLAGS_RELEASE_MANAGEMENT_UI,
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
cleanupReminder: parseEnvVarBoolean(
|
cleanupReminder: parseEnvVarBoolean(
|
||||||
process.env.UNLEASH_EXPERIMENTAL_CLEANUP_REMINDER,
|
process.env.UNLEASH_EXPERIMENTAL_CLEANUP_REMINDER,
|
||||||
false,
|
false,
|
||||||
|
@ -52,7 +52,6 @@ process.nextTick(async () => {
|
|||||||
uniqueSdkTracking: true,
|
uniqueSdkTracking: true,
|
||||||
teamsIntegrationChangeRequests: true,
|
teamsIntegrationChangeRequests: true,
|
||||||
addEditStrategy: true,
|
addEditStrategy: true,
|
||||||
flagsOverviewSearch: true,
|
|
||||||
cleanupReminder: true,
|
cleanupReminder: true,
|
||||||
strictSchemaValidation: true,
|
strictSchemaValidation: true,
|
||||||
registerFrontendClient: true,
|
registerFrontendClient: true,
|
||||||
|
Loading…
Reference in New Issue
Block a user