1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-11-10 01:19:53 +01:00

feat: change "archived" flags filter placement on project flags list (#10710)

Archived flags link will now it will show up on the right side, next to
import/export, which makes it more in line with flags overview.

Co-authored-by: Thomas Heartman <thomas@getunleash.io>
This commit is contained in:
Tymoteusz Czech 2025-10-02 11:44:57 +02:00 committed by GitHub
parent da22cb0d65
commit f5af92b5ee
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 96 additions and 28 deletions

View File

@ -41,7 +41,7 @@ import {
useProjectFeatureSearchActions,
} from './useProjectFeatureSearch.ts';
import { AvatarCell } from './AvatarCell.tsx';
import { styled, useMediaQuery, useTheme } from '@mui/material';
import { Box, styled, useMediaQuery, useTheme } from '@mui/material';
import useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectOverview';
import { ConnectSdkDialog } from '../../../onboarding/dialog/ConnectSdkDialog.tsx';
import { ProjectOnboarding } from '../../../onboarding/flow/ProjectOnboarding.tsx';
@ -101,8 +101,25 @@ const ButtonGroup = styled('div')(({ theme }) => ({
paddingInline: theme.spacing(1.5),
}));
const LinkToggle = styled('button')(({ theme }) => ({
background: 'none',
border: 'none',
padding: 0,
margin: theme.spacing(0, 1.5),
marginLeft: 'auto',
cursor: 'pointer',
color: theme.palette.primary.main,
textDecoration: 'underline',
font: 'inherit',
display: 'inline-flex',
alignItems: 'center',
'&:hover': {
textDecoration: 'none',
},
}));
export const ProjectFeatureToggles = ({
environments,
environments: availableEnvironments,
}: ProjectFeatureTogglesProps) => {
const { trackEvent } = usePlausibleTracker();
const projectId = useRequiredPathParam('projectId');
@ -192,6 +209,17 @@ export const ProjectFeatureToggles = ({
}
};
const showCleanupReminder = !tableState.lastSeenAt && !tableState.lifecycle;
const showArchived = Boolean(tableState.archived);
const toggleArchived = () => {
if (showArchived) {
setTableState({ archived: undefined });
} else {
setTableState({ archived: { operator: 'IS', values: ['true'] } });
}
};
const environments = showArchived ? [] : availableEnvironments;
const columns = useMemo(
() => [
columnHelper.display({
@ -493,8 +521,6 @@ export const ProjectFeatureToggles = ({
const selectedData = useSelectedData(features, rowSelection);
const showCleanupReminder = !tableState.lastSeenAt && !tableState.lifecycle;
return (
<Container>
<ConditionallyRender
@ -527,6 +553,23 @@ export const ProjectFeatureToggles = ({
isLoading={initialLoad}
totalItems={total}
environmentsToExport={environments}
actions={
flagsUiFilterRefactorEnabled ? (
<LinkToggle
type='button'
onClick={toggleArchived}
>
{showArchived
? 'View active flags'
: 'View archived flags'}
</LinkToggle>
) : null
}
title={
showArchived
? 'Archived feature flags'
: 'Feature flags'
}
/>
) : (
<LegacyProjectFeatureTogglesHeader
@ -559,12 +602,22 @@ export const ProjectFeatureToggles = ({
{flagsUiFilterRefactorEnabled ? (
<FiltersContainer>
<FilterRow>
<ProjectLifecycleFilters
projectId={projectId}
state={filterState}
onChange={setTableState}
total={loading ? undefined : total}
/>
{showArchived ? (
<Box sx={{ marginRight: 'auto' }}>
<ProjectOverviewFilters
project={projectId}
onChange={setTableState}
state={filterState}
/>
</Box>
) : (
<ProjectLifecycleFilters
projectId={projectId}
state={filterState}
onChange={setTableState}
total={loading ? undefined : total}
/>
)}
{isSmallScreen ? null : (
<ProjectFlagsSearch
searchQuery={tableState.query || ''}
@ -580,13 +633,15 @@ export const ProjectFeatureToggles = ({
onToggle={onToggleColumnVisibility}
/>
</FilterRow>
<FilterRow>
<ProjectOverviewFilters
project={projectId}
onChange={setTableState}
state={filterState}
/>
</FilterRow>
{showArchived ? null : (
<FilterRow>
<ProjectOverviewFilters
project={projectId}
onChange={setTableState}
state={filterState}
/>
</FilterRow>
)}
{isSmallScreen ? (
<ProjectFlagsSearch
searchQuery={tableState.query || ''}

View File

@ -1,4 +1,4 @@
import { type FC, useState } from 'react';
import { type FC, type ReactNode, useState } from 'react';
import { Box, IconButton, Tooltip } from '@mui/material';
import useLoading from 'hooks/useLoading';
import { PageHeader } from 'component/common/PageHeader/PageHeader';
@ -12,11 +12,19 @@ type ProjectFeatureTogglesHeaderProps = {
isLoading?: boolean;
totalItems?: number;
environmentsToExport?: string[];
actions?: ReactNode;
title?: string;
};
export const ProjectFeatureTogglesHeader: FC<
ProjectFeatureTogglesHeaderProps
> = ({ isLoading, totalItems, environmentsToExport }) => {
> = ({
isLoading,
totalItems,
environmentsToExport,
actions,
title = 'Feature flags',
}) => {
const projectId = useRequiredPathParam('projectId');
const headerLoadingRef = useLoading(isLoading || false);
const [showExportDialog, setShowExportDialog] = useState(false);
@ -24,11 +32,12 @@ export const ProjectFeatureTogglesHeader: FC<
return (
<Box ref={headerLoadingRef} aria-busy={isLoading} aria-live='polite'>
<PageHeader
titleElement={`Feature flags ${
titleElement={`${title} ${
totalItems !== undefined ? `(${totalItems})` : ''
}`}
actions={
<>
{actions}
<Tooltip title='Export all project flags' arrow>
<IconButton
data-loading

View File

@ -120,14 +120,18 @@ export const ProjectOverviewFilters: FC<ProjectOverviewFiltersProps> = ({
singularOperators: ['IS', 'IS_NOT'],
pluralOperators: ['IS_ANY_OF', 'IS_NONE_OF'],
},
{
label: 'Show only archived',
icon: 'inventory',
options: [{ label: 'True', value: 'true' }],
filterKey: 'archived',
singularOperators: ['IS'],
pluralOperators: ['IS_ANY_OF'],
},
...(!flagsUiFilterRefactorEnabled
? [
{
label: 'Show only archived',
icon: 'inventory',
options: [{ label: 'True', value: 'true' }],
filterKey: 'archived',
singularOperators: ['IS'],
pluralOperators: ['IS_ANY_OF'],
} satisfies IFilterItem,
]
: []),
];
setAvailableFilters(availableFilters);