mirror of
https://github.com/Unleash/unleash.git
synced 2025-10-27 11:02:16 +01:00
feat: allow adding project to segment (#3290)
https://linear.app/unleash/issue/2-741/add-project-dropdown-into-creation-of-segments Allows users to bind a segment to a project when creating or editing a segment. <img width="1051" alt="image" src="https://user-images.githubusercontent.com/14320932/224103846-1fe1f849-496c-4a77-9831-53bcb36f822e.png">
This commit is contained in:
parent
9b563f60e6
commit
ff7185fe5b
@ -30,6 +30,8 @@ export const CreateSegment = () => {
|
|||||||
setName,
|
setName,
|
||||||
description,
|
description,
|
||||||
setDescription,
|
setDescription,
|
||||||
|
project,
|
||||||
|
setProject,
|
||||||
constraints,
|
constraints,
|
||||||
setConstraints,
|
setConstraints,
|
||||||
getSegmentPayload,
|
getSegmentPayload,
|
||||||
@ -91,6 +93,8 @@ export const CreateSegment = () => {
|
|||||||
setName={setName}
|
setName={setName}
|
||||||
description={description}
|
description={description}
|
||||||
setDescription={setDescription}
|
setDescription={setDescription}
|
||||||
|
project={project}
|
||||||
|
setProject={setProject}
|
||||||
constraints={constraints}
|
constraints={constraints}
|
||||||
setConstraints={setConstraints}
|
setConstraints={setConstraints}
|
||||||
errors={errors}
|
errors={errors}
|
||||||
|
|||||||
@ -33,6 +33,8 @@ export const EditSegment = () => {
|
|||||||
setName,
|
setName,
|
||||||
description,
|
description,
|
||||||
setDescription,
|
setDescription,
|
||||||
|
project,
|
||||||
|
setProject,
|
||||||
constraints,
|
constraints,
|
||||||
setConstraints,
|
setConstraints,
|
||||||
getSegmentPayload,
|
getSegmentPayload,
|
||||||
@ -41,6 +43,7 @@ export const EditSegment = () => {
|
|||||||
} = useSegmentForm(
|
} = useSegmentForm(
|
||||||
segment?.name,
|
segment?.name,
|
||||||
segment?.description,
|
segment?.description,
|
||||||
|
segment?.project,
|
||||||
segment?.constraints
|
segment?.constraints
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -94,6 +97,8 @@ export const EditSegment = () => {
|
|||||||
setName={setName}
|
setName={setName}
|
||||||
description={description}
|
description={description}
|
||||||
setDescription={setDescription}
|
setDescription={setDescription}
|
||||||
|
project={project}
|
||||||
|
setProject={setProject}
|
||||||
constraints={constraints}
|
constraints={constraints}
|
||||||
setConstraints={setConstraints}
|
setConstraints={setConstraints}
|
||||||
errors={errors}
|
errors={errors}
|
||||||
|
|||||||
@ -12,9 +12,11 @@ export type SegmentFormMode = 'create' | 'edit';
|
|||||||
interface ISegmentProps {
|
interface ISegmentProps {
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
project: string | null;
|
||||||
constraints: IConstraint[];
|
constraints: IConstraint[];
|
||||||
setName: React.Dispatch<React.SetStateAction<string>>;
|
setName: React.Dispatch<React.SetStateAction<string>>;
|
||||||
setDescription: React.Dispatch<React.SetStateAction<string>>;
|
setDescription: React.Dispatch<React.SetStateAction<string>>;
|
||||||
|
setProject: React.Dispatch<React.SetStateAction<string | null>>;
|
||||||
setConstraints: React.Dispatch<React.SetStateAction<IConstraint[]>>;
|
setConstraints: React.Dispatch<React.SetStateAction<IConstraint[]>>;
|
||||||
handleSubmit: (e: any) => void;
|
handleSubmit: (e: any) => void;
|
||||||
errors: { [key: string]: string };
|
errors: { [key: string]: string };
|
||||||
@ -32,9 +34,11 @@ export const SegmentForm: React.FC<ISegmentProps> = ({
|
|||||||
children,
|
children,
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
|
project,
|
||||||
constraints,
|
constraints,
|
||||||
setName,
|
setName,
|
||||||
setDescription,
|
setDescription,
|
||||||
|
setProject,
|
||||||
setConstraints,
|
setConstraints,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
errors,
|
errors,
|
||||||
@ -54,8 +58,10 @@ export const SegmentForm: React.FC<ISegmentProps> = ({
|
|||||||
<SegmentFormStepOne
|
<SegmentFormStepOne
|
||||||
name={name}
|
name={name}
|
||||||
description={description}
|
description={description}
|
||||||
|
project={project}
|
||||||
setName={setName}
|
setName={setName}
|
||||||
setDescription={setDescription}
|
setDescription={setDescription}
|
||||||
|
setProject={setProject}
|
||||||
errors={errors}
|
errors={errors}
|
||||||
clearErrors={clearErrors}
|
clearErrors={clearErrors}
|
||||||
setCurrentStep={setCurrentStep}
|
setCurrentStep={setCurrentStep}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { Button, styled } from '@mui/material';
|
import { Autocomplete, Button, styled, TextField } from '@mui/material';
|
||||||
import Input from 'component/common/Input/Input';
|
import Input from 'component/common/Input/Input';
|
||||||
import React from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { SegmentFormStep } from './SegmentForm';
|
import { SegmentFormStep } from './SegmentForm';
|
||||||
import {
|
import {
|
||||||
@ -8,12 +8,17 @@ import {
|
|||||||
SEGMENT_DESC_ID,
|
SEGMENT_DESC_ID,
|
||||||
SEGMENT_NEXT_BTN_ID,
|
SEGMENT_NEXT_BTN_ID,
|
||||||
} from 'utils/testIds';
|
} from 'utils/testIds';
|
||||||
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
|
import useProjects from 'hooks/api/getters/useProjects/useProjects';
|
||||||
|
|
||||||
interface ISegmentFormPartOneProps {
|
interface ISegmentFormPartOneProps {
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
project: string | null;
|
||||||
setName: React.Dispatch<React.SetStateAction<string>>;
|
setName: React.Dispatch<React.SetStateAction<string>>;
|
||||||
setDescription: React.Dispatch<React.SetStateAction<string>>;
|
setDescription: React.Dispatch<React.SetStateAction<string>>;
|
||||||
|
setProject: React.Dispatch<React.SetStateAction<string | null>>;
|
||||||
errors: { [key: string]: string };
|
errors: { [key: string]: string };
|
||||||
clearErrors: () => void;
|
clearErrors: () => void;
|
||||||
setCurrentStep: React.Dispatch<React.SetStateAction<SegmentFormStep>>;
|
setCurrentStep: React.Dispatch<React.SetStateAction<SegmentFormStep>>;
|
||||||
@ -52,13 +57,25 @@ export const SegmentFormStepOne: React.FC<ISegmentFormPartOneProps> = ({
|
|||||||
children,
|
children,
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
|
project,
|
||||||
setName,
|
setName,
|
||||||
setDescription,
|
setDescription,
|
||||||
|
setProject,
|
||||||
errors,
|
errors,
|
||||||
clearErrors,
|
clearErrors,
|
||||||
setCurrentStep,
|
setCurrentStep,
|
||||||
}) => {
|
}) => {
|
||||||
|
const { uiConfig } = useUiConfig();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { projects } = useProjects();
|
||||||
|
|
||||||
|
const [selectedProject, setSelectedProject] = React.useState(
|
||||||
|
projects.find(({ id }) => id === project) ?? null
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setSelectedProject(projects.find(({ id }) => id === project) ?? null);
|
||||||
|
}, [project, projects]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledForm>
|
<StyledForm>
|
||||||
@ -87,6 +104,28 @@ export const SegmentFormStepOne: React.FC<ISegmentFormPartOneProps> = ({
|
|||||||
errorText={errors.description}
|
errorText={errors.description}
|
||||||
data-testid={SEGMENT_DESC_ID}
|
data-testid={SEGMENT_DESC_ID}
|
||||||
/>
|
/>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={Boolean(uiConfig.flags.projectScopedSegments)}
|
||||||
|
show={
|
||||||
|
<>
|
||||||
|
<StyledInputDescription>
|
||||||
|
Is this segment tied to a specific project?
|
||||||
|
</StyledInputDescription>
|
||||||
|
<Autocomplete
|
||||||
|
size="small"
|
||||||
|
value={selectedProject}
|
||||||
|
onChange={(_, newValue) => {
|
||||||
|
setProject(newValue?.id ?? null);
|
||||||
|
}}
|
||||||
|
options={projects}
|
||||||
|
getOptionLabel={option => option.name}
|
||||||
|
renderInput={params => (
|
||||||
|
<TextField {...params} label="Project" />
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</StyledContainer>
|
</StyledContainer>
|
||||||
<StyledButtonContainer>
|
<StyledButtonContainer>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@ -5,10 +5,12 @@ import { useSegmentValidation } from 'hooks/api/getters/useSegmentValidation/use
|
|||||||
export const useSegmentForm = (
|
export const useSegmentForm = (
|
||||||
initialName = '',
|
initialName = '',
|
||||||
initialDescription = '',
|
initialDescription = '',
|
||||||
|
initialProject: string | null = null,
|
||||||
initialConstraints: IConstraint[] = []
|
initialConstraints: IConstraint[] = []
|
||||||
) => {
|
) => {
|
||||||
const [name, setName] = useState(initialName);
|
const [name, setName] = useState(initialName);
|
||||||
const [description, setDescription] = useState(initialDescription);
|
const [description, setDescription] = useState(initialDescription);
|
||||||
|
const [project, setProject] = useState<string | null>(initialProject);
|
||||||
const [constraints, setConstraints] =
|
const [constraints, setConstraints] =
|
||||||
useState<IConstraint[]>(initialConstraints);
|
useState<IConstraint[]>(initialConstraints);
|
||||||
const [errors, setErrors] = useState({});
|
const [errors, setErrors] = useState({});
|
||||||
@ -22,6 +24,10 @@ export const useSegmentForm = (
|
|||||||
setDescription(initialDescription);
|
setDescription(initialDescription);
|
||||||
}, [initialDescription]);
|
}, [initialDescription]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setProject(initialProject);
|
||||||
|
}, [initialProject]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setConstraints(initialConstraints);
|
setConstraints(initialConstraints);
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
@ -38,6 +44,7 @@ export const useSegmentForm = (
|
|||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
|
project,
|
||||||
constraints,
|
constraints,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -51,6 +58,8 @@ export const useSegmentForm = (
|
|||||||
setName,
|
setName,
|
||||||
description,
|
description,
|
||||||
setDescription,
|
setDescription,
|
||||||
|
project,
|
||||||
|
setProject,
|
||||||
constraints,
|
constraints,
|
||||||
setConstraints,
|
setConstraints,
|
||||||
getSegmentPayload,
|
getSegmentPayload,
|
||||||
|
|||||||
@ -4,6 +4,7 @@ export interface ISegment {
|
|||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
project: string | null;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
createdBy: string;
|
createdBy: string;
|
||||||
constraints: IConstraint[];
|
constraints: IConstraint[];
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user