diff --git a/frontend/src/component/project/Project/Project.tsx b/frontend/src/component/project/Project/Project.tsx index d5362a29c1..d6ebf237e1 100644 --- a/frontend/src/component/project/Project/Project.tsx +++ b/frontend/src/component/project/Project/Project.tsx @@ -29,6 +29,7 @@ import { DraftBanner } from 'component/changeRequest/DraftBanner/DraftBanner'; import { MainLayout } from 'component/layout/MainLayout/MainLayout'; import { ProjectChangeRequests } from '../../changeRequest/ProjectChangeRequests/ProjectChangeRequests'; import { useChangeRequestsEnabled } from 'hooks/useChangeRequestsEnabled'; +import { ProjectSettings } from './ProjectSettings/ProjectSettings'; const StyledDiv = styled('div')(() => ({ display: 'flex', @@ -58,7 +59,7 @@ const Project = () => { const { classes: styles } = useStyles(); const navigate = useNavigate(); const { pathname } = useLocation(); - const { isOss } = useUiConfig(); + const { isOss, uiConfig } = useUiConfig(); const basePath = `/projects/${projectId}`; const projectName = project?.name || projectId; @@ -78,21 +79,34 @@ const Project = () => { path: `${basePath}/health`, name: 'health', }, - { - title: 'Access', - path: `${basePath}/access`, - name: 'access', - }, - { - title: 'Environments', - path: `${basePath}/environments`, - name: 'environments', - }, + ...(!uiConfig?.flags?.changeRequests + ? [ + { + title: 'Access', + path: `${basePath}/access`, + name: 'access', + }, + { + title: 'Environments', + path: `${basePath}/environments`, + name: 'environments', + }, + ] + : []), { title: 'Archive', path: `${basePath}/archive`, name: 'archive', }, + ...(uiConfig?.flags?.changeRequests + ? [ + { + title: 'Project settings', + path: `${basePath}/settings`, + name: 'settings', + }, + ] + : []), { title: 'Event log', path: `${basePath}/logs`, @@ -263,6 +277,7 @@ const Project = () => { /> } /> + } /> } /> diff --git a/frontend/src/component/project/Project/ProjectSettings/ChangeRequestConfiguration/ChangeRequestConfiguration.tsx b/frontend/src/component/project/Project/ProjectSettings/ChangeRequestConfiguration/ChangeRequestConfiguration.tsx new file mode 100644 index 0000000000..80a8a0681c --- /dev/null +++ b/frontend/src/component/project/Project/ProjectSettings/ChangeRequestConfiguration/ChangeRequestConfiguration.tsx @@ -0,0 +1,166 @@ +import { useMemo, useState, VFC } from 'react'; +import { HeaderGroup, Row } from 'react-table'; +import { Alert, Box, Typography } from '@mui/material'; +import { + SortableTableHeader, + Table, + TableCell, + TableBody, + TableRow, +} from 'component/common/Table'; +import { useGlobalFilter, useTable } from 'react-table'; +import { sortTypes } from 'utils/sortTypes'; +import { PageContent } from 'component/common/PageContent/PageContent'; +import { PageHeader } from 'component/common/PageHeader/PageHeader'; +import { TextCell } from 'component/common/Table/cells/TextCell/TextCell'; +import PermissionSwitch from 'component/common/PermissionSwitch/PermissionSwitch'; +import { UPDATE_FEATURE_ENVIRONMENT } from 'component/providers/AccessProvider/permissions'; +import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; +import { Dialogue } from 'component/common/Dialogue/Dialogue'; +import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; + +export const ChangeRequestConfiguration: VFC = () => { + const [dialogState, setDialogState] = useState<{ + isOpen: boolean; + enableEnvironment?: string; + }>({ + isOpen: false, + enableEnvironment: '', + }); + const projectId = useRequiredPathParam('projectId'); + const data = [ + { + environment: 'dev', + type: 'test', + isEnabled: false, + }, + ] as any[]; // FIXME: type + + const onClick = (enableEnvironment: string) => () => { + setDialogState({ isOpen: true, enableEnvironment }); + }; + + const columns = useMemo( + () => [ + { + Header: 'Environment', + accessor: 'environment', + disableSortBy: true, + }, + { + Header: 'Type', + accessor: 'type', + disableGlobalFilter: true, + disableSortBy: true, + }, + { + Header: 'Status', + accessor: 'isEnabled', + align: 'center', + + Cell: ({ value, row: { original } }: any) => ( + + + + ), + width: 100, + disableGlobalFilter: true, + disableSortBy: true, + }, + ], + [] + ); + + const { getTableProps, getTableBodyProps, headerGroups, rows, prepareRow } = + useTable( + { + columns, + data, + sortTypes, + autoResetGlobalFilter: false, + disableSortRemove: true, + defaultColumn: { + Cell: TextCell, + }, + }, + useGlobalFilter + ); + + return ( + } + // isLoading={loading} + > + + If change request is enabled for an environment, then any change + in that environment needs to be approved before it will be + applied + + + + []} + /> + + {rows.map(row => { + prepareRow(row); + return ( + + {row.cells.map(cell => ( + + {cell.render('Cell')} + + ))} + + ); + })} + +
+ + { + alert('clicked'); + /* FIXME: API action */ + }} + open={dialogState.isOpen} + onClose={() => + setDialogState(state => ({ ...state, isOpen: false })) + } + primaryButtonText="Enable" + secondaryButtonText="Cancel" + title="Enable change request" + > + + You are about to enable “Change request” + + {' '} + for{' '} + {dialogState.enableEnvironment} + + } + /> + . + + + When enabling change request for an environment, you need to + be sure that your Unleash Admin already have created the + custom project roles in your Unleash instance so you can + assign your project members from the project access page. + + +
+ ); +}; diff --git a/frontend/src/component/project/Project/ProjectSettings/ProjectSettings.tsx b/frontend/src/component/project/Project/ProjectSettings/ProjectSettings.tsx new file mode 100644 index 0000000000..d194cb64d7 --- /dev/null +++ b/frontend/src/component/project/Project/ProjectSettings/ProjectSettings.tsx @@ -0,0 +1,54 @@ +import { + Route, + Routes, + useLocation, + useNavigate, + Navigate, +} from 'react-router-dom'; +import { ITab, VerticalTabs } from 'component/common/VerticalTabs/VerticalTabs'; +import { ProjectAccess } from 'component/project/ProjectAccess/ProjectAccess'; +import ProjectEnvironmentList from 'component/project/ProjectEnvironment/ProjectEnvironment'; +import { ChangeRequestConfiguration } from './ChangeRequestConfiguration/ChangeRequestConfiguration'; + +export const ProjectSettings = () => { + const location = useLocation(); + const navigate = useNavigate(); + + const tabs = [ + { id: 'access', label: 'Access' }, + { id: 'environments', label: 'Environments' }, + { id: 'change-requests', label: 'Change request configuration' }, + ]; + + const onChange = (tab: ITab) => { + navigate(tab.id); + }; + + return ( + id && location.pathname?.includes(`/${id}`) + )?.id || tabs[0].id + } + onChange={onChange} + > + + } /> + } + /> + } + /> + } + /> + + + ); +};