mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-14 01:16:17 +02:00
refactor: pass feature to feature overview metadata component (#9803)
This commit is contained in:
parent
e436cf72e6
commit
916ee157ab
@ -86,6 +86,8 @@ export const FeatureOverview = () => {
|
|||||||
onEnvironmentVisibilityChange={
|
onEnvironmentVisibilityChange={
|
||||||
onEnvironmentVisibilityChange
|
onEnvironmentVisibilityChange
|
||||||
}
|
}
|
||||||
|
feature={feature}
|
||||||
|
onChange={refetchFeature}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<StyledMainContent>
|
<StyledMainContent>
|
||||||
|
@ -66,14 +66,6 @@ const setupChangeRequestApi = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const setupFeatureApi = (feature: IFeatureToggle) => {
|
|
||||||
testServerRoute(
|
|
||||||
server,
|
|
||||||
'/api/admin/projects/default/features/feature',
|
|
||||||
feature,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
setupApi();
|
setupApi();
|
||||||
});
|
});
|
||||||
@ -81,12 +73,16 @@ beforeEach(() => {
|
|||||||
const route = '/projects/default/features/feature';
|
const route = '/projects/default/features/feature';
|
||||||
|
|
||||||
test('show dependency dialogue', async () => {
|
test('show dependency dialogue', async () => {
|
||||||
setupFeatureApi(feature);
|
|
||||||
render(
|
render(
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route
|
<Route
|
||||||
path={'/projects/:projectId/features/:featureId'}
|
path={'/projects/:projectId/features/:featureId'}
|
||||||
element={<FeatureOverviewMetaData />}
|
element={
|
||||||
|
<FeatureOverviewMetaData
|
||||||
|
feature={feature}
|
||||||
|
onChange={() => {}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Routes>,
|
</Routes>,
|
||||||
{
|
{
|
||||||
@ -105,18 +101,23 @@ test('show dependency dialogue', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('show dependency dialogue for OSS with dependencies', async () => {
|
test('show dependency dialogue for OSS with dependencies', async () => {
|
||||||
setupOssWithExistingDependencies();
|
const feature = {
|
||||||
setupFeatureApi({
|
|
||||||
name: 'feature',
|
name: 'feature',
|
||||||
project: 'default',
|
project: 'default',
|
||||||
dependencies: [] as Array<{ feature: string }>,
|
dependencies: [] as Array<{ feature: string }>,
|
||||||
children: [] as string[],
|
children: [] as string[],
|
||||||
} as IFeatureToggle);
|
} as IFeatureToggle;
|
||||||
|
setupOssWithExistingDependencies();
|
||||||
render(
|
render(
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route
|
<Route
|
||||||
path={'/projects/:projectId/features/:featureId'}
|
path={'/projects/:projectId/features/:featureId'}
|
||||||
element={<FeatureOverviewMetaData />}
|
element={
|
||||||
|
<FeatureOverviewMetaData
|
||||||
|
feature={feature}
|
||||||
|
onChange={() => {}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Routes>,
|
</Routes>,
|
||||||
{
|
{
|
||||||
@ -135,17 +136,22 @@ test('show dependency dialogue for OSS with dependencies', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('show child', async () => {
|
test('show child', async () => {
|
||||||
setupFeatureApi({
|
const feature = {
|
||||||
name: 'feature',
|
name: 'feature',
|
||||||
project: 'default',
|
project: 'default',
|
||||||
dependencies: [] as Array<{ feature: string }>,
|
dependencies: [] as Array<{ feature: string }>,
|
||||||
children: ['some_child'],
|
children: ['some_child'],
|
||||||
} as IFeatureToggle);
|
} as IFeatureToggle;
|
||||||
render(
|
render(
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route
|
<Route
|
||||||
path={'/projects/:projectId/features/:featureId'}
|
path={'/projects/:projectId/features/:featureId'}
|
||||||
element={<FeatureOverviewMetaData />}
|
element={
|
||||||
|
<FeatureOverviewMetaData
|
||||||
|
feature={feature}
|
||||||
|
onChange={() => {}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Routes>,
|
</Routes>,
|
||||||
{ route },
|
{ route },
|
||||||
@ -156,17 +162,22 @@ test('show child', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('show children', async () => {
|
test('show children', async () => {
|
||||||
setupFeatureApi({
|
const feature = {
|
||||||
name: 'feature',
|
name: 'feature',
|
||||||
project: 'default',
|
project: 'default',
|
||||||
dependencies: [] as Array<{ feature: string }>,
|
dependencies: [] as Array<{ feature: string }>,
|
||||||
children: ['some_child', 'some_other_child'],
|
children: ['some_child', 'some_other_child'],
|
||||||
} as IFeatureToggle);
|
} as IFeatureToggle;
|
||||||
render(
|
render(
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route
|
<Route
|
||||||
path={'/projects/:projectId/features/:featureId'}
|
path={'/projects/:projectId/features/:featureId'}
|
||||||
element={<FeatureOverviewMetaData />}
|
element={
|
||||||
|
<FeatureOverviewMetaData
|
||||||
|
feature={feature}
|
||||||
|
onChange={() => {}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Routes>,
|
</Routes>,
|
||||||
{ route },
|
{ route },
|
||||||
@ -184,17 +195,22 @@ const feature = {
|
|||||||
} as IFeatureToggle;
|
} as IFeatureToggle;
|
||||||
|
|
||||||
test('delete dependency', async () => {
|
test('delete dependency', async () => {
|
||||||
setupFeatureApi({
|
const featureWithDeps = {
|
||||||
...feature,
|
...feature,
|
||||||
dependencies: [{ feature: 'some_parent' }],
|
dependencies: [{ feature: 'some_parent' }],
|
||||||
});
|
};
|
||||||
render(
|
render(
|
||||||
<>
|
<>
|
||||||
<ToastRenderer />
|
<ToastRenderer />
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route
|
<Route
|
||||||
path={'/projects/:projectId/features/:featureId'}
|
path={'/projects/:projectId/features/:featureId'}
|
||||||
element={<FeatureOverviewMetaData />}
|
element={
|
||||||
|
<FeatureOverviewMetaData
|
||||||
|
feature={featureWithDeps}
|
||||||
|
onChange={() => {}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Routes>
|
</Routes>
|
||||||
</>,
|
</>,
|
||||||
@ -221,18 +237,23 @@ test('delete dependency', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('delete dependency with change request', async () => {
|
test('delete dependency with change request', async () => {
|
||||||
setupChangeRequestApi();
|
const featureWithDeps = {
|
||||||
setupFeatureApi({
|
|
||||||
...feature,
|
...feature,
|
||||||
dependencies: [{ feature: 'some_parent' }],
|
dependencies: [{ feature: 'some_parent' }],
|
||||||
});
|
};
|
||||||
|
setupChangeRequestApi();
|
||||||
render(
|
render(
|
||||||
<>
|
<>
|
||||||
<ToastRenderer />
|
<ToastRenderer />
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route
|
<Route
|
||||||
path={'/projects/:projectId/features/:featureId'}
|
path={'/projects/:projectId/features/:featureId'}
|
||||||
element={<FeatureOverviewMetaData />}
|
element={
|
||||||
|
<FeatureOverviewMetaData
|
||||||
|
feature={featureWithDeps}
|
||||||
|
onChange={() => {}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Routes>
|
</Routes>
|
||||||
</>,
|
</>,
|
||||||
@ -259,15 +280,20 @@ test('delete dependency with change request', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('edit dependency', async () => {
|
test('edit dependency', async () => {
|
||||||
setupFeatureApi({
|
const featureWithDeps = {
|
||||||
...feature,
|
...feature,
|
||||||
dependencies: [{ feature: 'some_parent', enabled: false }],
|
dependencies: [{ feature: 'some_parent', enabled: false }],
|
||||||
});
|
};
|
||||||
render(
|
render(
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route
|
<Route
|
||||||
path={'/projects/:projectId/features/:featureId'}
|
path={'/projects/:projectId/features/:featureId'}
|
||||||
element={<FeatureOverviewMetaData />}
|
element={
|
||||||
|
<FeatureOverviewMetaData
|
||||||
|
feature={featureWithDeps}
|
||||||
|
onChange={() => {}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Routes>,
|
</Routes>,
|
||||||
{
|
{
|
||||||
@ -295,7 +321,7 @@ test('edit dependency', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('show variant dependencies', async () => {
|
test('show variant dependencies', async () => {
|
||||||
setupFeatureApi({
|
const featureWithDeps = {
|
||||||
...feature,
|
...feature,
|
||||||
dependencies: [
|
dependencies: [
|
||||||
{
|
{
|
||||||
@ -304,12 +330,17 @@ test('show variant dependencies', async () => {
|
|||||||
variants: ['variantA', 'variantB'],
|
variants: ['variantA', 'variantB'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
};
|
||||||
render(
|
render(
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route
|
<Route
|
||||||
path={'/projects/:projectId/features/:featureId'}
|
path={'/projects/:projectId/features/:featureId'}
|
||||||
element={<FeatureOverviewMetaData />}
|
element={
|
||||||
|
<FeatureOverviewMetaData
|
||||||
|
feature={featureWithDeps}
|
||||||
|
onChange={() => {}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Routes>,
|
</Routes>,
|
||||||
{ route },
|
{ route },
|
||||||
@ -324,7 +355,7 @@ test('show variant dependencies', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('show variant dependency', async () => {
|
test('show variant dependency', async () => {
|
||||||
setupFeatureApi({
|
const featureWithDeps = {
|
||||||
...feature,
|
...feature,
|
||||||
dependencies: [
|
dependencies: [
|
||||||
{
|
{
|
||||||
@ -333,12 +364,17 @@ test('show variant dependency', async () => {
|
|||||||
variants: ['variantA'],
|
variants: ['variantA'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
};
|
||||||
render(
|
render(
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route
|
<Route
|
||||||
path={'/projects/:projectId/features/:featureId'}
|
path={'/projects/:projectId/features/:featureId'}
|
||||||
element={<FeatureOverviewMetaData />}
|
element={
|
||||||
|
<FeatureOverviewMetaData
|
||||||
|
feature={featureWithDeps}
|
||||||
|
onChange={() => {}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Routes>,
|
</Routes>,
|
||||||
{ route },
|
{ route },
|
||||||
@ -348,7 +384,7 @@ test('show variant dependency', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('show disabled dependency', async () => {
|
test('show disabled dependency', async () => {
|
||||||
setupFeatureApi({
|
const featureWithDeps = {
|
||||||
...feature,
|
...feature,
|
||||||
dependencies: [
|
dependencies: [
|
||||||
{
|
{
|
||||||
@ -356,12 +392,17 @@ test('show disabled dependency', async () => {
|
|||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
};
|
||||||
render(
|
render(
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route
|
<Route
|
||||||
path={'/projects/:projectId/features/:featureId'}
|
path={'/projects/:projectId/features/:featureId'}
|
||||||
element={<FeatureOverviewMetaData />}
|
element={
|
||||||
|
<FeatureOverviewMetaData
|
||||||
|
feature={featureWithDeps}
|
||||||
|
onChange={() => {}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Routes>,
|
</Routes>,
|
||||||
{ route },
|
{ route },
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import { type FC, useState } from 'react';
|
import { type FC, useState } from 'react';
|
||||||
import { styled } from '@mui/material';
|
import { styled } from '@mui/material';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { useFeature } from 'hooks/api/getters/useFeature/useFeature';
|
|
||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
|
||||||
import { FeatureArchiveDialog } from 'component/common/FeatureArchiveDialog/FeatureArchiveDialog';
|
import { FeatureArchiveDialog } from 'component/common/FeatureArchiveDialog/FeatureArchiveDialog';
|
||||||
import { FeatureArchiveNotAllowedDialog } from 'component/common/FeatureArchiveDialog/FeatureArchiveNotAllowedDialog';
|
import { FeatureArchiveNotAllowedDialog } from 'component/common/FeatureArchiveDialog/FeatureArchiveNotAllowedDialog';
|
||||||
import { formatDateYMD } from 'utils/formatDate';
|
import { formatDateYMD } from 'utils/formatDate';
|
||||||
@ -17,6 +15,7 @@ import { capitalizeFirst } from 'utils/capitalizeFirst';
|
|||||||
import { Collaborators } from './Collaborators';
|
import { Collaborators } from './Collaborators';
|
||||||
import { EnvironmentVisibilityMenu } from './EnvironmentVisibilityMenu/EnvironmentVisibilityMenu';
|
import { EnvironmentVisibilityMenu } from './EnvironmentVisibilityMenu/EnvironmentVisibilityMenu';
|
||||||
import { Truncator } from 'component/common/Truncator/Truncator';
|
import { Truncator } from 'component/common/Truncator/Truncator';
|
||||||
|
import type { IFeatureToggle } from '../../../../../interfaces/featureToggle';
|
||||||
|
|
||||||
const StyledMetaDataContainer = styled('div')(({ theme }) => ({
|
const StyledMetaDataContainer = styled('div')(({ theme }) => ({
|
||||||
padding: theme.spacing(3),
|
padding: theme.spacing(3),
|
||||||
@ -69,16 +68,16 @@ export const StyledMetaDataItemValue = styled('div')(({ theme }) => ({
|
|||||||
type FeatureOverviewMetaDataProps = {
|
type FeatureOverviewMetaDataProps = {
|
||||||
hiddenEnvironments?: string[];
|
hiddenEnvironments?: string[];
|
||||||
onEnvironmentVisibilityChange?: (environment: string) => void;
|
onEnvironmentVisibilityChange?: (environment: string) => void;
|
||||||
|
feature: IFeatureToggle;
|
||||||
|
onChange: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const FeatureOverviewMetaData: FC<FeatureOverviewMetaDataProps> = ({
|
const FeatureOverviewMetaData: FC<FeatureOverviewMetaDataProps> = ({
|
||||||
hiddenEnvironments,
|
hiddenEnvironments,
|
||||||
onEnvironmentVisibilityChange,
|
onEnvironmentVisibilityChange,
|
||||||
|
feature,
|
||||||
|
onChange,
|
||||||
}) => {
|
}) => {
|
||||||
const projectId = useRequiredPathParam('projectId');
|
|
||||||
const featureId = useRequiredPathParam('featureId');
|
|
||||||
const { feature, refetchFeature } = useFeature(projectId, featureId);
|
|
||||||
|
|
||||||
const { locationSettings } = useLocationSettings();
|
const { locationSettings } = useLocationSettings();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@ -125,7 +124,7 @@ const FeatureOverviewMetaData: FC<FeatureOverviewMetaDataProps> = ({
|
|||||||
onComplete={() =>
|
onComplete={() =>
|
||||||
setMarkCompletedDialogueOpen(true)
|
setMarkCompletedDialogueOpen(true)
|
||||||
}
|
}
|
||||||
onUncomplete={refetchFeature}
|
onUncomplete={onChange}
|
||||||
/>
|
/>
|
||||||
</StyledMetaDataItem>
|
</StyledMetaDataItem>
|
||||||
) : null}
|
) : null}
|
||||||
@ -181,7 +180,7 @@ const FeatureOverviewMetaData: FC<FeatureOverviewMetaDataProps> = ({
|
|||||||
{feature.children.length > 0 ? (
|
{feature.children.length > 0 ? (
|
||||||
<FeatureArchiveNotAllowedDialog
|
<FeatureArchiveNotAllowedDialog
|
||||||
features={feature.children}
|
features={feature.children}
|
||||||
project={projectId}
|
project={feature.project}
|
||||||
isOpen={archiveDialogOpen}
|
isOpen={archiveDialogOpen}
|
||||||
onClose={() => setArchiveDialogOpen(false)}
|
onClose={() => setArchiveDialogOpen(false)}
|
||||||
/>
|
/>
|
||||||
@ -189,11 +188,11 @@ const FeatureOverviewMetaData: FC<FeatureOverviewMetaDataProps> = ({
|
|||||||
<FeatureArchiveDialog
|
<FeatureArchiveDialog
|
||||||
isOpen={archiveDialogOpen}
|
isOpen={archiveDialogOpen}
|
||||||
onConfirm={() => {
|
onConfirm={() => {
|
||||||
navigate(`/projects/${projectId}`);
|
navigate(`/projects/${feature.project}`);
|
||||||
}}
|
}}
|
||||||
onClose={() => setArchiveDialogOpen(false)}
|
onClose={() => setArchiveDialogOpen(false)}
|
||||||
projectId={projectId}
|
projectId={feature.project}
|
||||||
featureIds={[featureId]}
|
featureIds={[feature.name]}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{feature.project ? (
|
{feature.project ? (
|
||||||
@ -202,7 +201,7 @@ const FeatureOverviewMetaData: FC<FeatureOverviewMetaDataProps> = ({
|
|||||||
setIsOpen={setMarkCompletedDialogueOpen}
|
setIsOpen={setMarkCompletedDialogueOpen}
|
||||||
projectId={feature.project}
|
projectId={feature.project}
|
||||||
featureId={feature.name}
|
featureId={feature.name}
|
||||||
onComplete={refetchFeature}
|
onComplete={onChange}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</>
|
</>
|
||||||
|
Loading…
Reference in New Issue
Block a user