diff --git a/src/frontend/src/hooks/rules.hooks.ts b/src/frontend/src/hooks/rules.hooks.ts
index b0a64a64c6..fb15737504 100644
--- a/src/frontend/src/hooks/rules.hooks.ts
+++ b/src/frontend/src/hooks/rules.hooks.ts
@@ -440,6 +440,7 @@ export const useUpdateRuleset = () => {
{
onSuccess: () => {
queryClient.invalidateQueries(['rulesets']);
+ queryClient.invalidateQueries(['rules', 'rulesetTypes']);
}
}
);
@@ -454,6 +455,7 @@ export const useDeleteRuleset = () => {
{
onSuccess: () => {
queryClient.invalidateQueries(['rulesets']);
+ queryClient.invalidateQueries(['rules', 'rulesetTypes']);
}
}
);
@@ -467,7 +469,7 @@ export const useDeleteRulesetType = () => {
},
{
onSuccess: () => {
- queryClient.invalidateQueries(['rulesetTypes']);
+ queryClient.invalidateQueries(['rules', 'rulesetTypes']);
}
}
);
@@ -490,6 +492,7 @@ export const useCreateRuleset = () => {
{
onSuccess: () => {
queryClient.invalidateQueries(['rulesets']);
+ queryClient.invalidateQueries(['rules', 'rulesetTypes']);
}
}
);
diff --git a/src/frontend/src/pages/AdminToolsPage/AdminToolsProjectsConfig.tsx b/src/frontend/src/pages/AdminToolsPage/AdminToolsProjectsConfig.tsx
index 2c77332948..02c6b2187d 100644
--- a/src/frontend/src/pages/AdminToolsPage/AdminToolsProjectsConfig.tsx
+++ b/src/frontend/src/pages/AdminToolsPage/AdminToolsProjectsConfig.tsx
@@ -12,6 +12,7 @@ import ConfluenceLink from './ProjectsConfig/ConfluenceLink';
import PartReviewSampleImage from './ProjectsConfig/PartReviewSampleImage';
import CommonMistakesTable from './ProjectsConfig/CommonMistakesTable';
import PartTagsTable from './ProjectsConfig/PartTagsTable';
+import RulesetTypesTable from './ProjectsConfig/RulesetTypesTable';
const AdminToolsProjectsConfig: React.FC = () => {
return (
@@ -35,6 +36,10 @@ const AdminToolsProjectsConfig: React.FC = () => {
Cars Config
+
+ Rules Config
+
+
Links Config
diff --git a/src/frontend/src/pages/RulesPage/components/AddRulesetTypeModal.tsx b/src/frontend/src/pages/AdminToolsPage/ProjectsConfig/AddRulesetTypeModal.tsx
similarity index 61%
rename from src/frontend/src/pages/RulesPage/components/AddRulesetTypeModal.tsx
rename to src/frontend/src/pages/AdminToolsPage/ProjectsConfig/AddRulesetTypeModal.tsx
index 0e9caf9c9c..e5b20a626d 100644
--- a/src/frontend/src/pages/RulesPage/components/AddRulesetTypeModal.tsx
+++ b/src/frontend/src/pages/AdminToolsPage/ProjectsConfig/AddRulesetTypeModal.tsx
@@ -1,9 +1,9 @@
-import { FormControl, FormHelperText, FormLabel, TextField } from '@mui/material';
-import { Box } from '@mui/system';
+import { FormControl, FormHelperText, FormLabel } from '@mui/material';
import * as yup from 'yup';
import { yupResolver } from '@hookform/resolvers/yup';
-import { Controller, useForm } from 'react-hook-form';
+import { useForm } from 'react-hook-form';
import NERFormModal from '../../../components/NERFormModal';
+import ReactHookTextField from '../../../components/ReactHookTextField';
import { useToast } from '../../../hooks/toasts.hooks';
interface RulesetTypeFormData {
@@ -16,15 +16,6 @@ interface AddRulesetTypeModalProps {
onFormSubmit: (data: RulesetTypeFormData) => Promise;
}
-const sectionHeaderStyle = {
- fontWeight: 'bold',
- color: '#ef4345',
- textDecoration: 'underline',
- fontSize: '1rem',
- textUnderlineOffset: '5px',
- marginBottom: '10px'
-};
-
const schema = yup.object({
name: yup.string().required('Name is required')
});
@@ -77,26 +68,11 @@ const AddRulesetTypeModal: React.FC = ({ open, onHide,
formId={'add-ruleset-type-form'}
showCloseButton
>
-
-
- Name Ruleset:
- (
-
- )}
- />
- {errors.name?.message}
-
-
+
+ Ruleset Name
+
+ {errors.name?.message}
+
);
};
diff --git a/src/frontend/src/pages/RulesPage/components/RulesetTypeDeleteModal.tsx b/src/frontend/src/pages/AdminToolsPage/ProjectsConfig/RulesetTypeDeleteModal.tsx
similarity index 100%
rename from src/frontend/src/pages/RulesPage/components/RulesetTypeDeleteModal.tsx
rename to src/frontend/src/pages/AdminToolsPage/ProjectsConfig/RulesetTypeDeleteModal.tsx
diff --git a/src/frontend/src/pages/AdminToolsPage/ProjectsConfig/RulesetTypesTable.tsx b/src/frontend/src/pages/AdminToolsPage/ProjectsConfig/RulesetTypesTable.tsx
new file mode 100644
index 0000000000..f070e3b0ee
--- /dev/null
+++ b/src/frontend/src/pages/AdminToolsPage/ProjectsConfig/RulesetTypesTable.tsx
@@ -0,0 +1,140 @@
+import { TableRow, TableCell, Box, IconButton } from '@mui/material';
+import LoadingIndicator from '../../../components/LoadingIndicator';
+import { datePipe } from '../../../utils/pipes';
+import ErrorPage from '../../ErrorPage';
+import { NERButton } from '../../../components/NERButton';
+import NERTable from '../../../components/NERTable';
+import { useState } from 'react';
+import { useToast } from '../../../hooks/toasts.hooks';
+import { useAllRulesetTypes, useCreateRulesetType, useDeleteRulesetType } from '../../../hooks/rules.hooks';
+import { Delete } from '@mui/icons-material';
+import RulesetTypeDeleteModal from './RulesetTypeDeleteModal';
+import AddRulesetTypeModal from './AddRulesetTypeModal';
+
+const handleDeleteRulesetType = async (
+ rulesetTypeId: string,
+ name: string,
+ hasRevisionFiles: boolean,
+ deleteRulesetTypeMutation: (rulesetTypeId: string) => Promise,
+ toast: ReturnType,
+ onSuccess: () => void
+) => {
+ if (hasRevisionFiles) {
+ toast.error('Cannot delete ruleset type with existing revisions');
+ return;
+ }
+
+ try {
+ await deleteRulesetTypeMutation(rulesetTypeId);
+ toast.success(`Ruleset Type: ${name} deleted successfully!`);
+ onSuccess();
+ } catch (error: unknown) {
+ if (error instanceof Error) {
+ toast.error(error.message);
+ }
+ }
+};
+
+interface RulesetTypeDeleteButtonProps {
+ rulesetTypeId: string;
+ name: string;
+ hasRevisionFiles: boolean;
+ deleteRulesetTypeMutation: (rulesetTypeId: string) => Promise;
+ toast: ReturnType;
+}
+
+const RulesetTypeDeleteButton: React.FC = ({
+ rulesetTypeId,
+ name,
+ hasRevisionFiles,
+ deleteRulesetTypeMutation,
+ toast
+}) => {
+ const [showDeleteModal, setShowDeleteModal] = useState(false);
+
+ const handleDeleteSubmit = () =>
+ handleDeleteRulesetType(rulesetTypeId, name, hasRevisionFiles, deleteRulesetTypeMutation, toast, () =>
+ setShowDeleteModal(false)
+ );
+
+ return (
+ <>
+ setShowDeleteModal(true)}>
+
+
+ {showDeleteModal && (
+ setShowDeleteModal(false)}
+ />
+ )}
+ >
+ );
+};
+
+const RulesetTypesTable: React.FC = () => {
+ const toast = useToast();
+ const { data: rulesetTypes, isLoading, isError, error } = useAllRulesetTypes();
+ const { mutateAsync: createRulesetType } = useCreateRulesetType();
+ const { mutateAsync: deleteRulesetType } = useDeleteRulesetType();
+ const [addRulesetTypeModalShow, setAddRulesetTypeModalShow] = useState(false);
+
+ if (isError) return ;
+ if (!rulesetTypes || isLoading) return ;
+
+ const handleAddRulesetTypeConfirm = async (data: { name: string }) => {
+ await createRulesetType({ name: data.name });
+ };
+
+ const handleAddRulesetTypeCancel = () => {
+ setAddRulesetTypeModalShow(false);
+ };
+
+ const rulesetTypeTableRows = rulesetTypes.map((rulesetType, index) => (
+
+ {rulesetType.name}
+
+ {datePipe(rulesetType.lastUpdated)}
+
+
+ {rulesetType.revisionFiles.length}
+
+
+ 0}
+ deleteRulesetTypeMutation={deleteRulesetType}
+ toast={toast}
+ />
+
+
+ ));
+
+ return (
+
+
+
+
+ setAddRulesetTypeModalShow(!addRulesetTypeModalShow)}>
+ Add Ruleset Type
+
+
+
+ );
+};
+
+export default RulesetTypesTable;
diff --git a/src/frontend/src/pages/RulesPage/RulesetTypePage.tsx b/src/frontend/src/pages/RulesPage/RulesetTypePage.tsx
index f92aeaf343..8a45185fc0 100644
--- a/src/frontend/src/pages/RulesPage/RulesetTypePage.tsx
+++ b/src/frontend/src/pages/RulesPage/RulesetTypePage.tsx
@@ -2,24 +2,8 @@ import React from 'react';
import PageLayout from '../../components/PageLayout';
import { Box } from '@mui/material';
import RulesetTypeTable from './components/RulesetTypeTable';
-import { NERButton } from '../../components/NERButton';
-import AddRulesetTypeModal from './components/AddRulesetTypeModal';
-import { useState } from 'react';
-import { useCreateRulesetType } from '../../hooks/rules.hooks';
const RulesetTypePage: React.FC = () => {
- const [addRulesetTypeModalShow, setAddRulesetTypeModalShow] = useState(false);
-
- const { mutateAsync: createRulesetType } = useCreateRulesetType();
-
- const handleAddRulesetTypeConfirm = async (data: { name: string }) => {
- await createRulesetType({ name: data.name });
- };
-
- const handleAddRulesetTypeCancel = () => {
- setAddRulesetTypeModalShow(false);
- };
-
return (
<>
@@ -46,27 +30,6 @@ const RulesetTypePage: React.FC = () => {
ml: '20px'
})}
/>
-
- setAddRulesetTypeModalShow(!addRulesetTypeModalShow)}
- >
- Add Ruleset Type
-
-
-
diff --git a/src/frontend/src/pages/RulesPage/components/RulesetTypeTable.tsx b/src/frontend/src/pages/RulesPage/components/RulesetTypeTable.tsx
index daa3b9bbc4..505dcd5a27 100644
--- a/src/frontend/src/pages/RulesPage/components/RulesetTypeTable.tsx
+++ b/src/frontend/src/pages/RulesPage/components/RulesetTypeTable.tsx
@@ -12,21 +12,16 @@ import {
Card,
CardContent,
Typography,
- Stack,
- IconButton
+ Stack
} from '@mui/material';
import { useHistory } from 'react-router-dom';
import { datePipe } from '../../../utils/pipes';
import { routes } from '../../../utils/routes';
-import { useAllRulesetTypes, useDeleteRulesetType } from '../../../hooks/rules.hooks';
+import { useAllRulesetTypes } from '../../../hooks/rules.hooks';
import LoadingIndicator from '../../../components/LoadingIndicator';
import ErrorPage from '../../ErrorPage';
import { RulesetType } from 'shared';
import { NERButton } from '../../../components/NERButton';
-import { useToast } from '../../../hooks/toasts.hooks';
-import { useState } from 'react';
-import RulesetTypeDeleteModal from './RulesetTypeDeleteModal';
-import { Delete } from '@mui/icons-material';
type RulesetTypeColumnId = 'id' | 'name' | 'lastUpdated' | 'revisions' | 'actions' | 'delete';
@@ -35,20 +30,12 @@ interface RulesetTypeHeadCell {
label: string;
}
-interface RulesetTypeDeleteButtonProps {
- rulesetTypeId: string;
- name: string;
- onDelete: (rulesetTypeId: string, name: string) => void;
-}
-
const RulesetTypeTable: React.FC = () => {
const history = useHistory();
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
- const toast = useToast();
const { data: rulesetTypes = [], isLoading, error } = useAllRulesetTypes();
- const { mutateAsync: deleteRulesetType } = useDeleteRulesetType();
const headCells: readonly RulesetTypeHeadCell[] = [
{
@@ -66,10 +53,6 @@ const RulesetTypeTable: React.FC = () => {
{
id: 'actions',
label: 'Actions'
- },
- {
- id: 'delete',
- label: ''
}
];
@@ -77,47 +60,6 @@ const RulesetTypeTable: React.FC = () => {
history.push(routes.RULESET_BY_ID.replace(':rulesetTypeId', rulesetTypeId));
};
- const handleDeleteRulesetType = async (rulesetTypeId: string, name: string) => {
- const rulesetType = rulesetTypes.find((rt) => rt.rulesetTypeId === rulesetTypeId);
- if (rulesetType && rulesetType.revisionFiles.length > 0) {
- toast.error('Cannot delete ruleset type with existing revisions');
- return;
- }
-
- try {
- await deleteRulesetType(rulesetTypeId);
- toast.success(`Ruleset Type: ${name} deleted successfully!`);
- } catch (error: unknown) {
- if (error instanceof Error) {
- toast.error(error.message);
- }
- }
- };
-
- const RulesetTypeDeleteButton: React.FC = ({ rulesetTypeId, name, onDelete }) => {
- const [showDeleteModal, setShowDeleteModal] = useState(false);
-
- const handleDeleteSubmit = () => {
- onDelete(rulesetTypeId, name);
- setShowDeleteModal(false);
- };
-
- return (
- <>
- setShowDeleteModal(true)}>
-
-
- {showDeleteModal && (
- setShowDeleteModal(false)}
- />
- )}
- >
- );
- };
-
if (error) return ;
if (isLoading) return ;
@@ -163,8 +105,6 @@ const RulesetTypeTable: React.FC = () => {
'&:hover': {
backgroundColor: theme.palette.grey[700]
},
- marginRight: '10px',
- padding: '4px',
lineHeight: 1,
borderRadius: '6px'
}}
@@ -172,11 +112,6 @@ const RulesetTypeTable: React.FC = () => {
>
View Rulesets
-
@@ -228,8 +163,6 @@ const RulesetTypeTable: React.FC = () => {
'&:hover': {
backgroundColor: theme.palette.grey[700]
},
- marginRight: '10px',
- padding: '4px',
lineHeight: 1,
borderRadius: '6px'
}}
@@ -238,13 +171,6 @@ const RulesetTypeTable: React.FC = () => {
View Rulesets
-
-
-
))
)}