mirror of
https://github.com/Unleash/unleash.git
synced 2024-12-22 19:07:54 +01:00
feat: UI stub for adding dependent features (#4814)
This commit is contained in:
parent
d28e7e5a69
commit
b4742df8be
@ -0,0 +1,60 @@
|
||||
import { Box, styled } from '@mui/material';
|
||||
import { trim } from '../../common/util';
|
||||
import React, { FC, useState } from 'react';
|
||||
import Input from '../../common/Input/Input';
|
||||
import { CREATE_FEATURE } from '../../providers/AccessProvider/permissions';
|
||||
import PermissionButton from '../../common/PermissionButton/PermissionButton';
|
||||
import { useDependentFeaturesApi } from 'hooks/api/actions/useDependentFeaturesApi/useDependentFeaturesApi';
|
||||
|
||||
const StyledForm = styled('form')({});
|
||||
|
||||
const StyledInputDescription = styled('p')(({ theme }) => ({
|
||||
marginBottom: theme.spacing(1),
|
||||
}));
|
||||
|
||||
const StyledInput = styled(Input)(({ theme }) => ({
|
||||
marginBottom: theme.spacing(2),
|
||||
}));
|
||||
|
||||
interface IAddDependencyProps {
|
||||
projectId: string;
|
||||
featureId: string;
|
||||
}
|
||||
export const AddDependency: FC<IAddDependencyProps> = ({
|
||||
projectId,
|
||||
featureId,
|
||||
}) => {
|
||||
const [parent, setParent] = useState('');
|
||||
const { addDependency } = useDependentFeaturesApi();
|
||||
|
||||
return (
|
||||
<StyledForm
|
||||
onSubmit={() => {
|
||||
addDependency(featureId, { feature: parent });
|
||||
}}
|
||||
>
|
||||
<StyledInputDescription>
|
||||
What feature do you want to depend on?
|
||||
</StyledInputDescription>
|
||||
<Box sx={{ display: 'flex', gap: 1 }}>
|
||||
<StyledInput
|
||||
autoFocus
|
||||
label="Dependency"
|
||||
id="dependency-feature"
|
||||
value={parent}
|
||||
onChange={e => setParent(trim(e.target.value))}
|
||||
/>
|
||||
<PermissionButton
|
||||
permission={CREATE_FEATURE}
|
||||
projectId={projectId}
|
||||
onClick={() => {
|
||||
addDependency(featureId, { feature: parent });
|
||||
}}
|
||||
variant={'outlined'}
|
||||
>
|
||||
Add{' '}
|
||||
</PermissionButton>
|
||||
</Box>
|
||||
</StyledForm>
|
||||
);
|
||||
};
|
@ -12,6 +12,9 @@ import { usePageTitle } from 'hooks/usePageTitle';
|
||||
import { FeatureOverviewSidePanel } from 'component/feature/FeatureView/FeatureOverview/FeatureOverviewSidePanel/FeatureOverviewSidePanel';
|
||||
import { useHiddenEnvironments } from 'hooks/useHiddenEnvironments';
|
||||
import { styled } from '@mui/material';
|
||||
import { AddDependency } from '../../Dependencies/AddDependency';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
|
||||
const StyledContainer = styled('div')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
@ -39,6 +42,7 @@ const FeatureOverview = () => {
|
||||
useHiddenEnvironments();
|
||||
const onSidebarClose = () => navigate(featurePath);
|
||||
usePageTitle(featureId);
|
||||
const dependentFeatures = useUiFlag('dependentFeatures');
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
@ -50,6 +54,16 @@ const FeatureOverview = () => {
|
||||
/>
|
||||
</div>
|
||||
<StyledMainContent>
|
||||
<ConditionallyRender
|
||||
condition={dependentFeatures}
|
||||
show={
|
||||
<AddDependency
|
||||
projectId={projectId}
|
||||
featureId={featureId}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
|
||||
<FeatureOverviewEnvironments />
|
||||
</StyledMainContent>
|
||||
<Routes>
|
||||
|
@ -0,0 +1,35 @@
|
||||
import useAPI from '../useApi/useApi';
|
||||
|
||||
// TODO: generate from orval
|
||||
interface IParentFeaturePayload {
|
||||
feature: string;
|
||||
}
|
||||
export const useDependentFeaturesApi = () => {
|
||||
const { makeRequest, createRequest, errors, loading } = useAPI({
|
||||
propagateErrors: true,
|
||||
});
|
||||
|
||||
const addDependency = async (
|
||||
childFeature: string,
|
||||
parentFeaturePayload: IParentFeaturePayload
|
||||
) => {
|
||||
const req = createRequest(
|
||||
`/api/admin/projects/default/features/${childFeature}/dependencies`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify(parentFeaturePayload),
|
||||
}
|
||||
);
|
||||
try {
|
||||
await makeRequest(req.caller, req.id);
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
addDependency,
|
||||
errors,
|
||||
loading,
|
||||
};
|
||||
};
|
@ -65,6 +65,7 @@ export type UiFlags = {
|
||||
variantTypeNumber?: boolean;
|
||||
privateProjects?: boolean;
|
||||
accessOverview?: boolean;
|
||||
dependentFeatures?: boolean;
|
||||
[key: string]: boolean | Variant | undefined;
|
||||
};
|
||||
|
||||
|
@ -32,13 +32,13 @@ afterAll(async () => {
|
||||
});
|
||||
|
||||
const addFeatureDependency = async (
|
||||
parentFeature: string,
|
||||
childFeature: string,
|
||||
payload: CreateDependentFeatureSchema,
|
||||
expectedCode = 200,
|
||||
) => {
|
||||
return app.request
|
||||
.post(
|
||||
`/api/admin/projects/default/features/${parentFeature}/dependencies`,
|
||||
`/api/admin/projects/default/features/${childFeature}/dependencies`,
|
||||
)
|
||||
.send(payload)
|
||||
.expect(expectedCode);
|
||||
@ -51,13 +51,13 @@ test('should add feature dependency', async () => {
|
||||
await app.createFeature(child);
|
||||
|
||||
// save explicit enabled and variants
|
||||
await addFeatureDependency(parent, {
|
||||
feature: child,
|
||||
await addFeatureDependency(child, {
|
||||
feature: parent,
|
||||
enabled: false,
|
||||
});
|
||||
// overwrite with implicit enabled: true and variants
|
||||
await addFeatureDependency(parent, {
|
||||
feature: child,
|
||||
await addFeatureDependency(child, {
|
||||
feature: parent,
|
||||
variants: ['variantB'],
|
||||
});
|
||||
});
|
||||
|
@ -44,6 +44,7 @@ process.nextTick(async () => {
|
||||
privateProjects: true,
|
||||
accessOverview: true,
|
||||
datadogJsonTemplate: true,
|
||||
dependentFeatures: true,
|
||||
},
|
||||
},
|
||||
authentication: {
|
||||
|
Loading…
Reference in New Issue
Block a user