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, useProjectFeatureSearchActions,
} from './useProjectFeatureSearch.ts'; } from './useProjectFeatureSearch.ts';
import { AvatarCell } from './AvatarCell.tsx'; 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 useProjectOverview from 'hooks/api/getters/useProjectOverview/useProjectOverview';
import { ConnectSdkDialog } from '../../../onboarding/dialog/ConnectSdkDialog.tsx'; import { ConnectSdkDialog } from '../../../onboarding/dialog/ConnectSdkDialog.tsx';
import { ProjectOnboarding } from '../../../onboarding/flow/ProjectOnboarding.tsx'; import { ProjectOnboarding } from '../../../onboarding/flow/ProjectOnboarding.tsx';
@ -101,8 +101,25 @@ const ButtonGroup = styled('div')(({ theme }) => ({
paddingInline: theme.spacing(1.5), 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 = ({ export const ProjectFeatureToggles = ({
environments, environments: availableEnvironments,
}: ProjectFeatureTogglesProps) => { }: ProjectFeatureTogglesProps) => {
const { trackEvent } = usePlausibleTracker(); const { trackEvent } = usePlausibleTracker();
const projectId = useRequiredPathParam('projectId'); 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( const columns = useMemo(
() => [ () => [
columnHelper.display({ columnHelper.display({
@ -493,8 +521,6 @@ export const ProjectFeatureToggles = ({
const selectedData = useSelectedData(features, rowSelection); const selectedData = useSelectedData(features, rowSelection);
const showCleanupReminder = !tableState.lastSeenAt && !tableState.lifecycle;
return ( return (
<Container> <Container>
<ConditionallyRender <ConditionallyRender
@ -527,6 +553,23 @@ export const ProjectFeatureToggles = ({
isLoading={initialLoad} isLoading={initialLoad}
totalItems={total} totalItems={total}
environmentsToExport={environments} 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 <LegacyProjectFeatureTogglesHeader
@ -559,12 +602,22 @@ export const ProjectFeatureToggles = ({
{flagsUiFilterRefactorEnabled ? ( {flagsUiFilterRefactorEnabled ? (
<FiltersContainer> <FiltersContainer>
<FilterRow> <FilterRow>
{showArchived ? (
<Box sx={{ marginRight: 'auto' }}>
<ProjectOverviewFilters
project={projectId}
onChange={setTableState}
state={filterState}
/>
</Box>
) : (
<ProjectLifecycleFilters <ProjectLifecycleFilters
projectId={projectId} projectId={projectId}
state={filterState} state={filterState}
onChange={setTableState} onChange={setTableState}
total={loading ? undefined : total} total={loading ? undefined : total}
/> />
)}
{isSmallScreen ? null : ( {isSmallScreen ? null : (
<ProjectFlagsSearch <ProjectFlagsSearch
searchQuery={tableState.query || ''} searchQuery={tableState.query || ''}
@ -580,6 +633,7 @@ export const ProjectFeatureToggles = ({
onToggle={onToggleColumnVisibility} onToggle={onToggleColumnVisibility}
/> />
</FilterRow> </FilterRow>
{showArchived ? null : (
<FilterRow> <FilterRow>
<ProjectOverviewFilters <ProjectOverviewFilters
project={projectId} project={projectId}
@ -587,6 +641,7 @@ export const ProjectFeatureToggles = ({
state={filterState} state={filterState}
/> />
</FilterRow> </FilterRow>
)}
{isSmallScreen ? ( {isSmallScreen ? (
<ProjectFlagsSearch <ProjectFlagsSearch
searchQuery={tableState.query || ''} 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 { Box, IconButton, Tooltip } from '@mui/material';
import useLoading from 'hooks/useLoading'; import useLoading from 'hooks/useLoading';
import { PageHeader } from 'component/common/PageHeader/PageHeader'; import { PageHeader } from 'component/common/PageHeader/PageHeader';
@ -12,11 +12,19 @@ type ProjectFeatureTogglesHeaderProps = {
isLoading?: boolean; isLoading?: boolean;
totalItems?: number; totalItems?: number;
environmentsToExport?: string[]; environmentsToExport?: string[];
actions?: ReactNode;
title?: string;
}; };
export const ProjectFeatureTogglesHeader: FC< export const ProjectFeatureTogglesHeader: FC<
ProjectFeatureTogglesHeaderProps ProjectFeatureTogglesHeaderProps
> = ({ isLoading, totalItems, environmentsToExport }) => { > = ({
isLoading,
totalItems,
environmentsToExport,
actions,
title = 'Feature flags',
}) => {
const projectId = useRequiredPathParam('projectId'); const projectId = useRequiredPathParam('projectId');
const headerLoadingRef = useLoading(isLoading || false); const headerLoadingRef = useLoading(isLoading || false);
const [showExportDialog, setShowExportDialog] = useState(false); const [showExportDialog, setShowExportDialog] = useState(false);
@ -24,11 +32,12 @@ export const ProjectFeatureTogglesHeader: FC<
return ( return (
<Box ref={headerLoadingRef} aria-busy={isLoading} aria-live='polite'> <Box ref={headerLoadingRef} aria-busy={isLoading} aria-live='polite'>
<PageHeader <PageHeader
titleElement={`Feature flags ${ titleElement={`${title} ${
totalItems !== undefined ? `(${totalItems})` : '' totalItems !== undefined ? `(${totalItems})` : ''
}`} }`}
actions={ actions={
<> <>
{actions}
<Tooltip title='Export all project flags' arrow> <Tooltip title='Export all project flags' arrow>
<IconButton <IconButton
data-loading data-loading

View File

@ -120,6 +120,8 @@ export const ProjectOverviewFilters: FC<ProjectOverviewFiltersProps> = ({
singularOperators: ['IS', 'IS_NOT'], singularOperators: ['IS', 'IS_NOT'],
pluralOperators: ['IS_ANY_OF', 'IS_NONE_OF'], pluralOperators: ['IS_ANY_OF', 'IS_NONE_OF'],
}, },
...(!flagsUiFilterRefactorEnabled
? [
{ {
label: 'Show only archived', label: 'Show only archived',
icon: 'inventory', icon: 'inventory',
@ -127,7 +129,9 @@ export const ProjectOverviewFilters: FC<ProjectOverviewFiltersProps> = ({
filterKey: 'archived', filterKey: 'archived',
singularOperators: ['IS'], singularOperators: ['IS'],
pluralOperators: ['IS_ANY_OF'], pluralOperators: ['IS_ANY_OF'],
}, } satisfies IFilterItem,
]
: []),
]; ];
setAvailableFilters(availableFilters); setAvailableFilters(availableFilters);