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}
+ >
+
+ } />
+ }
+ />
+ }
+ />
+ }
+ />
+
+
+ );
+};