mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-31 13:47:02 +02:00
feat: adjust search page columns (#9722)
New columns for search page - improved "name" with filtering by type and tag - lifecycle - created by (avatars) with filtering
This commit is contained in:
parent
e876e6438d
commit
5647fc916e
@ -90,13 +90,13 @@ const CappedDescription: FC<{ text: string; searchQuery: string }> = ({
|
|||||||
placement='bottom-start'
|
placement='bottom-start'
|
||||||
arrow
|
arrow
|
||||||
>
|
>
|
||||||
<StyledDescription>
|
<StyledDescription data-loading>
|
||||||
<Highlighter search={searchQuery}>{text}</Highlighter>
|
<Highlighter search={searchQuery}>{text}</Highlighter>
|
||||||
</StyledDescription>
|
</StyledDescription>
|
||||||
</HtmlTooltip>
|
</HtmlTooltip>
|
||||||
}
|
}
|
||||||
elseShow={
|
elseShow={
|
||||||
<StyledDescription>
|
<StyledDescription data-loading>
|
||||||
<Highlighter search={searchQuery}>{text}</Highlighter>
|
<Highlighter search={searchQuery}>{text}</Highlighter>
|
||||||
</StyledDescription>
|
</StyledDescription>
|
||||||
}
|
}
|
||||||
|
@ -35,9 +35,9 @@ interface IFeatureLifecycleProps {
|
|||||||
project: string;
|
project: string;
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
onComplete: () => void;
|
onComplete?: () => void;
|
||||||
onUncomplete: () => void;
|
onUncomplete?: () => void;
|
||||||
onArchive: () => void;
|
onArchive?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FeatureLifecycleCell: VFC<IFeatureLifecycleProps> = ({
|
export const FeatureLifecycleCell: VFC<IFeatureLifecycleProps> = ({
|
||||||
|
@ -20,7 +20,10 @@ import { useEnvironments } from 'hooks/api/getters/useEnvironments/useEnvironmen
|
|||||||
import { ExportDialog } from './ExportDialog';
|
import { ExportDialog } from './ExportDialog';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
import { useUiFlag } from 'hooks/useUiFlag';
|
||||||
import { focusable } from 'themes/themeStyles';
|
import { focusable } from 'themes/themeStyles';
|
||||||
import { FeatureEnvironmentSeenCell } from 'component/common/Table/cells/FeatureSeenCell/FeatureEnvironmentSeenCell';
|
import {
|
||||||
|
FeatureEnvironmentSeenCell,
|
||||||
|
FeatureLifecycleCell,
|
||||||
|
} from 'component/common/Table/cells/FeatureSeenCell/FeatureEnvironmentSeenCell';
|
||||||
import useToast from 'hooks/useToast';
|
import useToast from 'hooks/useToast';
|
||||||
import { FeatureToggleFilters } from './FeatureToggleFilters/FeatureToggleFilters';
|
import { FeatureToggleFilters } from './FeatureToggleFilters/FeatureToggleFilters';
|
||||||
import { withTableState } from 'utils/withTableState';
|
import { withTableState } from 'utils/withTableState';
|
||||||
@ -29,18 +32,36 @@ import { FeatureSegmentCell } from 'component/common/Table/cells/FeatureSegmentC
|
|||||||
import { FeatureToggleListActions } from './FeatureToggleListActions/FeatureToggleListActions';
|
import { FeatureToggleListActions } from './FeatureToggleListActions/FeatureToggleListActions';
|
||||||
import useLoading from 'hooks/useLoading';
|
import useLoading from 'hooks/useLoading';
|
||||||
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||||
import { useGlobalFeatureSearch } from './useGlobalFeatureSearch';
|
import {
|
||||||
|
useGlobalFeatureSearch,
|
||||||
|
useTableStateFilter,
|
||||||
|
} from './useGlobalFeatureSearch';
|
||||||
import useProjects from 'hooks/api/getters/useProjects/useProjects';
|
import useProjects from 'hooks/api/getters/useProjects/useProjects';
|
||||||
import { LifecycleFilters } from './FeatureToggleFilters/LifecycleFilters';
|
import { LifecycleFilters } from './FeatureToggleFilters/LifecycleFilters';
|
||||||
import { ExportFlags } from './ExportFlags';
|
import { ExportFlags } from './ExportFlags';
|
||||||
|
import { createFeatureOverviewCell } from 'component/common/Table/cells/FeatureOverviewCell/FeatureOverviewCell';
|
||||||
|
import { AvatarCell } from 'component/project/Project/PaginatedProjectFeatureToggles/AvatarCell';
|
||||||
|
|
||||||
export const featuresPlaceholder = Array(15).fill({
|
export const featuresPlaceholder = Array(15).fill({
|
||||||
name: 'Name of the feature',
|
name: 'Name of the feature',
|
||||||
description: 'Short description of the feature',
|
description: 'Short description of the feature',
|
||||||
type: '-',
|
type: '-',
|
||||||
createdAt: new Date(2022, 1, 1),
|
createdAt: new Date(2022, 1, 1).toISOString(),
|
||||||
project: 'projectID',
|
project: 'projectID',
|
||||||
});
|
createdBy: {
|
||||||
|
id: 0,
|
||||||
|
name: 'admin',
|
||||||
|
imageUrl: '',
|
||||||
|
},
|
||||||
|
archivedAt: null,
|
||||||
|
favorite: false,
|
||||||
|
stale: false,
|
||||||
|
dependencyType: null,
|
||||||
|
tags: [],
|
||||||
|
environments: [],
|
||||||
|
impressionData: false,
|
||||||
|
segments: [],
|
||||||
|
} as FeatureSearchResponseSchema);
|
||||||
|
|
||||||
const columnHelper = createColumnHelper<FeatureSearchResponseSchema>();
|
const columnHelper = createColumnHelper<FeatureSearchResponseSchema>();
|
||||||
|
|
||||||
@ -70,6 +91,22 @@ export const FeatureToggleListTable: FC = () => {
|
|||||||
setTableState,
|
setTableState,
|
||||||
filterState,
|
filterState,
|
||||||
} = useGlobalFeatureSearch();
|
} = useGlobalFeatureSearch();
|
||||||
|
const onFlagTypeClick = useTableStateFilter(
|
||||||
|
['type', 'IS'],
|
||||||
|
tableState,
|
||||||
|
setTableState,
|
||||||
|
);
|
||||||
|
const onTagClick = useTableStateFilter(
|
||||||
|
['tag', 'INCLUDE'],
|
||||||
|
tableState,
|
||||||
|
setTableState,
|
||||||
|
);
|
||||||
|
const onAvatarClick = useTableStateFilter(
|
||||||
|
['createdBy', 'IS'],
|
||||||
|
tableState,
|
||||||
|
setTableState,
|
||||||
|
);
|
||||||
|
|
||||||
const { projects } = useProjects();
|
const { projects } = useProjects();
|
||||||
const bodyLoadingRef = useLoading(loading);
|
const bodyLoadingRef = useLoading(loading);
|
||||||
const { favorite, unfavorite } = useFavoriteFeaturesApi();
|
const { favorite, unfavorite } = useFavoriteFeaturesApi();
|
||||||
@ -92,65 +129,147 @@ export const FeatureToggleListTable: FC = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const columns = useMemo(
|
const columns = useMemo(
|
||||||
() => [
|
() =>
|
||||||
columnHelper.accessor('favorite', {
|
flagsReleaseManagementUIEnabled
|
||||||
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: (cell) => <FeatureNameCell value={cell.row} />,
|
|
||||||
cell: ({ row }) => (
|
|
||||||
<LinkCell
|
|
||||||
title={row.original.name}
|
|
||||||
subtitle={row.original.description || undefined}
|
|
||||||
to={`/projects/${row.original.project}/features/${row.original.name}`}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
meta: {
|
|
||||||
width: '50%',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
...(!flagsReleaseManagementUIEnabled
|
|
||||||
? [
|
? [
|
||||||
|
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: 48 },
|
||||||
|
}),
|
||||||
|
columnHelper.accessor('name', {
|
||||||
|
header: 'Name',
|
||||||
|
cell: createFeatureOverviewCell(
|
||||||
|
onTagClick,
|
||||||
|
onFlagTypeClick,
|
||||||
|
),
|
||||||
|
meta: { width: '50%' },
|
||||||
|
}),
|
||||||
|
columnHelper.accessor('createdAt', {
|
||||||
|
header: 'Created',
|
||||||
|
cell: ({ getValue }) => (
|
||||||
|
<DateCell value={getValue()} />
|
||||||
|
),
|
||||||
|
meta: { width: '1%' },
|
||||||
|
}),
|
||||||
|
columnHelper.accessor('createdBy', {
|
||||||
|
id: 'createdBy',
|
||||||
|
header: 'By',
|
||||||
|
cell: AvatarCell(onAvatarClick),
|
||||||
|
meta: { width: '1%', align: 'center' },
|
||||||
|
enableSorting: false,
|
||||||
|
}),
|
||||||
|
|
||||||
|
columnHelper.accessor('lifecycle', {
|
||||||
|
id: 'lifecycle',
|
||||||
|
header: 'Lifecycle',
|
||||||
|
cell: ({ row: { original } }) => (
|
||||||
|
<FeatureLifecycleCell
|
||||||
|
feature={original}
|
||||||
|
data-loading
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
enableSorting: false, // FIXME: enable sorting by lifecycle
|
||||||
|
size: 50,
|
||||||
|
meta: { align: 'center', width: '1%' },
|
||||||
|
}),
|
||||||
|
columnHelper.accessor('project', {
|
||||||
|
header: 'Project',
|
||||||
|
cell: ({ getValue }) => {
|
||||||
|
const projectId = getValue();
|
||||||
|
const projectName = projects.find(
|
||||||
|
(project) => project.id === projectId,
|
||||||
|
)?.name;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LinkCell
|
||||||
|
title={projectName || projectId}
|
||||||
|
to={`/projects/${projectId}`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
: [
|
||||||
|
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(
|
columnHelper.accessor(
|
||||||
(row) => row.segments?.join('\n') || '',
|
(row) => row.segments?.join('\n') || '',
|
||||||
{
|
{
|
||||||
@ -181,42 +300,30 @@ export const FeatureToggleListTable: FC = () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
]
|
columnHelper.accessor('createdAt', {
|
||||||
: ([] as never[])),
|
header: 'Created',
|
||||||
columnHelper.accessor('createdAt', {
|
cell: ({ getValue }) => (
|
||||||
header: 'Created',
|
<DateCell value={getValue()} />
|
||||||
cell: ({ getValue }) => <DateCell value={getValue()} />,
|
),
|
||||||
meta: {
|
meta: {
|
||||||
width: '1%',
|
width: '1%',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
columnHelper.accessor('project', {
|
columnHelper.accessor('project', {
|
||||||
header: flagsReleaseManagementUIEnabled
|
header: 'Project ID',
|
||||||
? 'Project'
|
cell: ({ getValue }) => {
|
||||||
: 'Project ID',
|
const value = getValue();
|
||||||
cell: ({ getValue }) => {
|
return (
|
||||||
const value = getValue();
|
<LinkCell
|
||||||
const project = projects.find(
|
title={value}
|
||||||
(project) => project.id === value,
|
to={`/projects/${value}`}
|
||||||
);
|
/>
|
||||||
|
);
|
||||||
return (
|
},
|
||||||
<LinkCell
|
meta: {
|
||||||
title={
|
width: '1%',
|
||||||
flagsReleaseManagementUIEnabled
|
},
|
||||||
? project?.name || value
|
}),
|
||||||
: value
|
|
||||||
}
|
|
||||||
to={`/projects/${getValue()}`}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
meta: {
|
|
||||||
width: '1%',
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
...(!flagsReleaseManagementUIEnabled
|
|
||||||
? [
|
|
||||||
columnHelper.accessor('stale', {
|
columnHelper.accessor('stale', {
|
||||||
header: 'State',
|
header: 'State',
|
||||||
cell: ({ getValue }) => (
|
cell: ({ getValue }) => (
|
||||||
@ -226,12 +333,9 @@ export const FeatureToggleListTable: FC = () => {
|
|||||||
width: '1%',
|
width: '1%',
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]
|
],
|
||||||
: ([] as never[])),
|
|
||||||
],
|
|
||||||
[tableState.favoritesFirst],
|
[tableState.favoritesFirst],
|
||||||
);
|
);
|
||||||
|
|
||||||
const data = useMemo(
|
const data = useMemo(
|
||||||
() =>
|
() =>
|
||||||
features?.length === 0 && loading ? featuresPlaceholder : features,
|
features?.length === 0 && loading ? featuresPlaceholder : features,
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { useCallback } from 'react';
|
||||||
import {
|
import {
|
||||||
encodeQueryParams,
|
encodeQueryParams,
|
||||||
NumberParam,
|
NumberParam,
|
||||||
@ -32,6 +33,7 @@ export const useGlobalFeatureSearch = (pageLimit = DEFAULT_PAGE_LIMIT) => {
|
|||||||
createdAt: FilterItemParam,
|
createdAt: FilterItemParam,
|
||||||
type: FilterItemParam,
|
type: FilterItemParam,
|
||||||
lifecycle: FilterItemParam,
|
lifecycle: FilterItemParam,
|
||||||
|
createdBy: FilterItemParam,
|
||||||
};
|
};
|
||||||
const [tableState, setTableState] = usePersistentTableState(
|
const [tableState, setTableState] = usePersistentTableState(
|
||||||
`${storageKey}`,
|
`${storageKey}`,
|
||||||
@ -71,3 +73,57 @@ export const useGlobalFeatureSearch = (pageLimit = DEFAULT_PAGE_LIMIT) => {
|
|||||||
filterState,
|
filterState,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: refactor
|
||||||
|
// This is similar to `useProjectFeatureSearchActions`, but more generic
|
||||||
|
// Reuse wasn't possible because the prior one is constrained to the project hook
|
||||||
|
export const useTableStateFilter = <K extends string>(
|
||||||
|
[key, operator]: [K, string],
|
||||||
|
state:
|
||||||
|
| Record<
|
||||||
|
K,
|
||||||
|
| {
|
||||||
|
operator: string;
|
||||||
|
values: string[];
|
||||||
|
}
|
||||||
|
| undefined
|
||||||
|
| null
|
||||||
|
>
|
||||||
|
| undefined
|
||||||
|
| null,
|
||||||
|
setState: (state: {
|
||||||
|
[key: string]: {
|
||||||
|
operator: string;
|
||||||
|
values: string[];
|
||||||
|
};
|
||||||
|
}) => void,
|
||||||
|
) =>
|
||||||
|
useCallback(
|
||||||
|
(value: string | number) => {
|
||||||
|
const currentState = state ? state[key] : undefined;
|
||||||
|
console.log({ key, operator, state: currentState, value });
|
||||||
|
|
||||||
|
if (
|
||||||
|
currentState &&
|
||||||
|
currentState.values.length > 0 &&
|
||||||
|
!currentState.values.includes(`${value}`)
|
||||||
|
) {
|
||||||
|
setState({
|
||||||
|
...state,
|
||||||
|
[key]: {
|
||||||
|
operator: currentState.operator,
|
||||||
|
values: [...currentState.values, value],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else if (!currentState) {
|
||||||
|
setState({
|
||||||
|
...state,
|
||||||
|
[key]: {
|
||||||
|
operator: operator,
|
||||||
|
values: [value],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[state, setState, key, operator],
|
||||||
|
);
|
||||||
|
@ -19,9 +19,9 @@ export interface LifecycleFeature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const FeatureLifecycle: FC<{
|
export const FeatureLifecycle: FC<{
|
||||||
onArchive: () => void;
|
onArchive?: () => void;
|
||||||
onComplete: () => void;
|
onComplete?: () => void;
|
||||||
onUncomplete: () => void;
|
onUncomplete?: () => void;
|
||||||
feature: LifecycleFeature;
|
feature: LifecycleFeature;
|
||||||
}> = ({ feature, onComplete, onUncomplete, onArchive }) => {
|
}> = ({ feature, onComplete, onUncomplete, onArchive }) => {
|
||||||
const currentStage = populateCurrentStage(feature);
|
const currentStage = populateCurrentStage(feature);
|
||||||
@ -30,7 +30,7 @@ export const FeatureLifecycle: FC<{
|
|||||||
|
|
||||||
const onUncompleteHandler = async () => {
|
const onUncompleteHandler = async () => {
|
||||||
await markFeatureUncompleted(feature.name, feature.project);
|
await markFeatureUncompleted(feature.name, feature.project);
|
||||||
onUncomplete();
|
onUncomplete?.();
|
||||||
trackEvent('feature-lifecycle', {
|
trackEvent('feature-lifecycle', {
|
||||||
props: {
|
props: {
|
||||||
eventType: 'uncomplete',
|
eventType: 'uncomplete',
|
||||||
@ -44,7 +44,7 @@ export const FeatureLifecycle: FC<{
|
|||||||
project={feature.project}
|
project={feature.project}
|
||||||
onArchive={onArchive}
|
onArchive={onArchive}
|
||||||
onComplete={onComplete}
|
onComplete={onComplete}
|
||||||
onUncomplete={onUncompleteHandler}
|
onUncomplete={onUncomplete ? onUncompleteHandler : undefined}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
>
|
>
|
||||||
<FeatureLifecycleStageIcon stage={currentStage} />
|
<FeatureLifecycleStageIcon stage={currentStage} />
|
||||||
|
@ -348,9 +348,9 @@ export const FeatureLifecycleTooltip: FC<{
|
|||||||
children: React.ReactElement<any, any>;
|
children: React.ReactElement<any, any>;
|
||||||
stage: LifecycleStage;
|
stage: LifecycleStage;
|
||||||
project: string;
|
project: string;
|
||||||
onArchive: () => void;
|
onArchive?: () => void;
|
||||||
onComplete: () => void;
|
onComplete?: () => void;
|
||||||
onUncomplete: () => void;
|
onUncomplete?: () => void;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
}> = ({
|
}> = ({
|
||||||
children,
|
children,
|
||||||
@ -399,7 +399,7 @@ export const FeatureLifecycleTooltip: FC<{
|
|||||||
{stage.name !== 'archived' ? (
|
{stage.name !== 'archived' ? (
|
||||||
<StyledFooter>
|
<StyledFooter>
|
||||||
<EnvironmentsInfo stage={stage} />
|
<EnvironmentsInfo stage={stage} />
|
||||||
{stage.name === 'live' && (
|
{stage.name === 'live' && onComplete ? (
|
||||||
<LiveStageAction
|
<LiveStageAction
|
||||||
onComplete={onComplete}
|
onComplete={onComplete}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
@ -409,8 +409,10 @@ export const FeatureLifecycleTooltip: FC<{
|
|||||||
environments={stage.environments!}
|
environments={stage.environments!}
|
||||||
/>
|
/>
|
||||||
</LiveStageAction>
|
</LiveStageAction>
|
||||||
)}
|
) : null}
|
||||||
{stage.name === 'completed' && (
|
{stage.name === 'completed' &&
|
||||||
|
onArchive &&
|
||||||
|
onUncomplete ? (
|
||||||
<CompletedStageDescription
|
<CompletedStageDescription
|
||||||
environments={stage.environments!}
|
environments={stage.environments!}
|
||||||
onArchive={onArchive}
|
onArchive={onArchive}
|
||||||
@ -418,7 +420,7 @@ export const FeatureLifecycleTooltip: FC<{
|
|||||||
loading={loading}
|
loading={loading}
|
||||||
project={project}
|
project={project}
|
||||||
/>
|
/>
|
||||||
)}
|
) : null}
|
||||||
</StyledFooter>
|
</StyledFooter>
|
||||||
) : null}
|
) : null}
|
||||||
</Box>
|
</Box>
|
||||||
|
Loading…
Reference in New Issue
Block a user