import { Typography, styled } from '@mui/material'; import Input from 'component/common/Input/Input'; import type { ProjectMode } from '../hooks/useProjectEnterpriseSettingsForm'; import { ReactComponent as ProjectIcon } from 'assets/icons/projectIconSmall.svg'; import { MultiselectList, SingleSelectList, TableSelect, } from './SelectionButton'; import { useEnvironments } from 'hooks/api/getters/useEnvironments/useEnvironments'; import StickinessIcon from '@mui/icons-material/FormatPaint'; import ProjectModeIcon from '@mui/icons-material/Adjust'; import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import EnvironmentsIcon from '@mui/icons-material/CloudCircle'; import { useStickinessOptions } from 'hooks/useStickinessOptions'; import { ReactComponent as ChangeRequestIcon } from 'assets/icons/merge.svg'; import type { ReactNode } from 'react'; import theme from 'themes/theme'; const StyledForm = styled('form')(({ theme }) => ({ background: theme.palette.background.default, })); const StyledFormSection = styled('div')(({ theme }) => ({ '& + *': { borderBlockStart: `1px solid ${theme.palette.divider}`, }, padding: theme.spacing(6), })); const TopGrid = styled(StyledFormSection)(({ theme }) => ({ display: 'grid', gridTemplateAreas: '"icon header" "icon project-name" "icon project-description"', gridTemplateColumns: 'auto 1fr', gap: theme.spacing(4), })); const StyledIcon = styled(ProjectIcon)(({ theme }) => ({ fill: theme.palette.primary.main, stroke: theme.palette.primary.main, })); const StyledHeader = styled(Typography)(({ theme }) => ({ gridArea: 'header', alignSelf: 'center', fontWeight: 'lighter', })); const ProjectNameContainer = styled('div')(({ theme }) => ({ gridArea: 'project-name', })); const ProjectDescriptionContainer = styled('div')(({ theme }) => ({ gridArea: 'project-description', })); const StyledInput = styled(Input)(({ theme }) => ({ width: '100%', fieldset: { border: 'none' }, })); const OptionButtons = styled(StyledFormSection)(({ theme }) => ({ display: 'flex', flexFlow: 'row wrap', gap: theme.spacing(2), })); const FormActions = styled(StyledFormSection)(({ theme }) => ({ display: 'flex', gap: theme.spacing(5), justifyContent: 'flex-end', })); type FormProps = { projectId: string; projectName: string; projectDesc: string; projectStickiness: string; featureLimit?: string; featureCount?: number; projectMode: string; projectEnvironments: Set; projectChangeRequestConfiguration: Record< string, { requiredApprovals: number } >; setProjectStickiness: React.Dispatch>; setProjectEnvironments: (envs: Set) => void; setProjectId: React.Dispatch>; setProjectName: React.Dispatch>; setProjectDesc: React.Dispatch>; setFeatureLimit?: React.Dispatch>; setProjectMode: React.Dispatch>; updateProjectChangeRequestConfig: { disableChangeRequests: (env: string) => void; enableChangeRequests: (env: string, requiredApprovals: number) => void; }; handleSubmit: (e: any) => void; errors: { [key: string]: string }; mode: 'Create' | 'Edit'; clearErrors: () => void; validateProjectId: () => void; overrideDocumentation: (args: { text: string; icon: ReactNode }) => void; clearDocumentationOverride: () => void; }; const PROJECT_NAME_INPUT = 'PROJECT_NAME_INPUT'; const PROJECT_DESCRIPTION_INPUT = 'PROJECT_DESCRIPTION_INPUT'; export const NewProjectForm: React.FC = ({ children, handleSubmit, projectName, projectDesc, projectStickiness, projectEnvironments, projectChangeRequestConfiguration, featureLimit, featureCount, projectMode, setProjectMode, setProjectEnvironments, setProjectId, setProjectName, setProjectDesc, setProjectStickiness, updateProjectChangeRequestConfig, setFeatureLimit, errors, mode, clearErrors, overrideDocumentation, clearDocumentationOverride, }) => { const { isEnterprise } = useUiConfig(); const { environments: allEnvironments } = useEnvironments(); const activeEnvironments = allEnvironments.filter((env) => env.enabled); const handleProjectNameUpdate = ( e: React.ChangeEvent, ) => { const input = e.target.value; setProjectName(input); }; const projectModeOptions = [ { value: 'open', label: 'open' }, { value: 'protected', label: 'protected' }, { value: 'private', label: 'private' }, ]; const stickinessOptions = useStickinessOptions(projectStickiness); const selectionButtonData = { environments: { icon: , text: `Each feature flag can have a separate configuration per environment. This setting configures which environments your project should start with.`, }, stickiness: { icon: , text: 'Stickiness is used to guarantee that your users see the same result when using a gradual rollout. Default stickiness allows you to choose which field is used by default in this project.', }, mode: { icon: , text: 'Mode defines who should be allowed to interact and see your project. Private mode hides the project from anyone except the project owner and members.', }, changeRequests: { icon: , text: 'Change requests can be configured per environment and require changes to go through an approval process before being applied.', }, }; return ( { handleSubmit(submitEvent); }} > ({ label: env.name, value: env.name, }))} onChange={setProjectEnvironments} button={{ label: projectEnvironments.size > 0 ? `${projectEnvironments.size} selected` : 'All environments', icon: , }} search={{ label: 'Filter project environments', placeholder: 'Select project environments', }} onOpen={() => overrideDocumentation(selectionButtonData.environments) } onClose={clearDocumentationOverride} /> ({ value: key, ...rest, }))} onChange={(value: any) => { setProjectStickiness(value); }} button={{ label: projectStickiness, icon: , }} search={{ label: 'Filter stickiness options', placeholder: 'Select default stickiness', }} onOpen={() => overrideDocumentation(selectionButtonData.stickiness) } onClose={clearDocumentationOverride} /> { setProjectMode(value); }} button={{ label: projectMode, icon: , }} search={{ label: 'Filter project mode options', placeholder: 'Select project mode', }} onOpen={() => overrideDocumentation(selectionButtonData.mode) } onClose={clearDocumentationOverride} /> } /> projectEnvironments.has(env.name), ) .map((env) => ({ name: env.name, type: env.type, }))} updateProjectChangeRequestConfiguration={ updateProjectChangeRequestConfig } button={{ label: Object.keys( projectChangeRequestConfiguration, ).length > 0 ? `${ Object.keys( projectChangeRequestConfiguration, ).length } selected` : 'Configure change requests', icon: , }} search={{ label: 'Filter environments', placeholder: 'Filter environments', }} projectChangeRequestConfiguration={ projectChangeRequestConfiguration } onOpen={() => overrideDocumentation( selectionButtonData.changeRequests, ) } onClose={clearDocumentationOverride} /> } /> {children} ); };