diff --git a/packages/client/public/locales/en/translation.json b/packages/client/public/locales/en/translation.json
index 404144b9..a1606a50 100644
--- a/packages/client/public/locales/en/translation.json
+++ b/packages/client/public/locales/en/translation.json
@@ -127,5 +127,23 @@
"tagView": {
"originalEntry": "Original Entry"
}
+ },
+ "errors": {
+ "datasetCreate": "Failed to create dataset, please try again or report this issue",
+ "uploadSessionCreate": "Could not start the upload process, please try again",
+ "csvUpload": "Could not upload the CSV, please try again",
+ "entryUpload": "Could not upload entry, please try again",
+ "entryUploadComplete": "Could not complete the upload process, please try again",
+ "entryQuery": "Failed to get entries for the dataset",
+ "studyExists": "Could not check if a study with that name exists",
+ "datasetsForProject": "Failed to get possible datasets",
+ "tagComplete": "Failed to submit tag, please try again",
+ "datasetPermissionUpdate": "Could not give project permission",
+ "projectCreate": "Could not create the project, please try again",
+ "projectDelete": "An issue took place deleting the project",
+ "projectAdminUpdate": "Could not update the user's permssions",
+ "studyDelete": "Failed to delete the target study",
+ "studyCreate": "Failed to create the new study",
+ "tagsQuery": "Failed to get tags"
}
}
diff --git a/packages/client/src/App.tsx b/packages/client/src/App.tsx
index 74234797..cf4417bb 100644
--- a/packages/client/src/App.tsx
+++ b/packages/client/src/App.tsx
@@ -29,6 +29,7 @@ import { DatasetProvider } from './context/Dataset.context';
import { EntryControls } from './pages/studies/EntryControls';
import { PermissionProvider } from './context/Permission.context';
import { TagTrainingView } from './pages/studies/TagTrainingView';
+import { SnackbarProvider } from './context/Snackbar.context';
const drawerWidth = 256;
const Main = styled('main', { shouldForwardProp: (prop) => prop !== 'open' })<{
@@ -74,8 +75,10 @@ const App: FC = () => {
-
-
+
+
+
+
diff --git a/packages/client/src/components/AddDataset.component.tsx b/packages/client/src/components/AddDataset.component.tsx
index de2bc443..8d7f8113 100644
--- a/packages/client/src/components/AddDataset.component.tsx
+++ b/packages/client/src/components/AddDataset.component.tsx
@@ -8,6 +8,8 @@ import { materialRenderers, materialCells } from '@jsonforms/material-renderers'
import { useCreateDatasetMutation, useDatasetExistsLazyQuery } from '../graphql/dataset/dataset';
import { Button } from '@mui/material';
import { ErrorObject } from 'ajv';
+import { useSnackbar } from '../context/Snackbar.context';
+import { useTranslation } from 'react-i18next';
interface ShowProps {
show: boolean;
@@ -53,7 +55,11 @@ export const AddDataset: React.FC = (props: ShowProps) => {
const initialData = {} as { name: string; description: string };
const [data, setData] = useState(initialData);
- const [createDataset, { data: createDatasetResults, loading }] = useCreateDatasetMutation();
+ const [createDataset, { data: createDatasetResults, loading, error: createDatasetError }] =
+ useCreateDatasetMutation();
+
+ const { t } = useTranslation();
+ const { pushSnackbarMessage } = useSnackbar();
useEffect(() => {
if (datasetExistsResults.data?.datasetExists) {
@@ -74,9 +80,11 @@ export const AddDataset: React.FC = (props: ShowProps) => {
useEffect(() => {
if (createDatasetResults?.createDataset) {
props.toggleModal(true);
+ } else if (createDatasetError) {
+ pushSnackbarMessage(t('errors.datasetCreate'), 'error');
+ console.error(createDatasetError);
}
- //TODO handle creation server error with snackbar
- }, [createDatasetResults]);
+ }, [createDatasetResults, createDatasetError]);
const handleChange = (data: any, errors: ErrorObject[] | undefined) => {
setData(data);
diff --git a/packages/client/src/components/DatasetTable.component.tsx b/packages/client/src/components/DatasetTable.component.tsx
index 4fc93808..c21dbb2d 100644
--- a/packages/client/src/components/DatasetTable.component.tsx
+++ b/packages/client/src/components/DatasetTable.component.tsx
@@ -4,6 +4,7 @@ import { Dataset, Entry } from '../graphql/graphql';
import { useEntryForDatasetLazyQuery } from '../graphql/entry/entry';
import { EntryView } from './EntryView.component';
import { useTranslation } from 'react-i18next';
+import { useSnackbar } from '../context/Snackbar.context';
export interface DatasetTableProps {
dataset: Dataset;
@@ -12,6 +13,7 @@ export interface DatasetTableProps {
export const DatasetTable: React.FC = (props) => {
const { t } = useTranslation();
+ const { pushSnackbarMessage } = useSnackbar();
const defaultColumns: GridColDef[] = [
{
@@ -41,6 +43,9 @@ export const DatasetTable: React.FC = (props) => {
useEffect(() => {
if (entryForDatasetResult.data) {
setEntries(entryForDatasetResult.data.entryForDataset);
+ } else if (entryForDatasetResult.error) {
+ pushSnackbarMessage(t('errors.entryQuery'), 'error');
+ console.error(entryForDatasetResult.error);
}
}, [entryForDatasetResult]);
diff --git a/packages/client/src/components/NewStudyJsonForm.component.tsx b/packages/client/src/components/NewStudyJsonForm.component.tsx
index 34634d87..1ae412a7 100644
--- a/packages/client/src/components/NewStudyJsonForm.component.tsx
+++ b/packages/client/src/components/NewStudyJsonForm.component.tsx
@@ -7,6 +7,7 @@ import { StudyExistsQuery, StudyExistsQueryVariables, StudyExistsDocument } from
import { useProject } from '../context/Project.context';
import { useTranslation } from 'react-i18next';
import { useApolloClient } from '@apollo/client';
+import { useSnackbar } from '../context/Snackbar.context';
export interface NewStudyFormProps {
newStudy: PartialStudyCreate | null;
@@ -15,6 +16,7 @@ export interface NewStudyFormProps {
export const NewStudyJsonForm: React.FC = (props) => {
const { t } = useTranslation();
+ const { pushSnackbarMessage } = useSnackbar();
const schema = {
type: 'object',
@@ -110,6 +112,10 @@ export const NewStudyJsonForm: React.FC = (props) => {
]);
props.setNewStudy(null);
return;
+ } else if (exists.error) {
+ pushSnackbarMessage(t('errors.studyExists'), 'error');
+ props.setNewStudy(null);
+ return;
}
// No errors
diff --git a/packages/client/src/components/TagTraining.component.tsx b/packages/client/src/components/TagTraining.component.tsx
index 21500ab1..7afc0a0a 100644
--- a/packages/client/src/components/TagTraining.component.tsx
+++ b/packages/client/src/components/TagTraining.component.tsx
@@ -5,6 +5,8 @@ import { Dataset, Entry } from '../graphql/graphql';
import { GridColDef } from '@mui/x-data-grid';
import { Switch } from '@mui/material';
import { useProject } from '../context/Project.context';
+import { useTranslation } from 'react-i18next';
+import { useSnackbar } from '../context/Snackbar.context';
export interface TagTrainingComponentProps {
setTrainingSet: Dispatch>;
@@ -17,6 +19,8 @@ export const TagTrainingComponent: React.FC = (props)
const [getDatasetsQuery, getDatasetsResults] = useGetDatasetsByProjectLazyQuery();
const [trainingSet, setTrainingSet] = useState([]);
const [taggingSet, setTaggingSet] = useState([]);
+ const { t } = useTranslation();
+ const { pushSnackbarMessage } = useSnackbar();
useEffect(() => {
if (project) {
@@ -76,8 +80,11 @@ export const TagTrainingComponent: React.FC = (props)
useEffect(() => {
if (getDatasetsResults.data) {
setDatasets(getDatasetsResults.data.getDatasetsByProject);
+ } else if (getDatasetsResults.error) {
+ pushSnackbarMessage(t('errors.datasetsForProject'), 'error');
+ console.error(getDatasetsResults.error);
}
- }, [getDatasetsResults.data]);
+ }, [getDatasetsResults]);
return (
<>
diff --git a/packages/client/src/components/upload/CSVUpload.component.tsx b/packages/client/src/components/upload/CSVUpload.component.tsx
index a438540c..0a6c3e0c 100644
--- a/packages/client/src/components/upload/CSVUpload.component.tsx
+++ b/packages/client/src/components/upload/CSVUpload.component.tsx
@@ -10,6 +10,8 @@ import { useApolloClient } from '@apollo/client';
import axios from 'axios';
import { Box, Button } from '@mui/material';
import UploadIcon from '@mui/icons-material/Upload';
+import { useSnackbar } from '../../context/Snackbar.context';
+import { useTranslation } from 'react-i18next';
export interface CSVUploadProps {
dataset: Dataset | null;
@@ -26,6 +28,8 @@ export const CSVUpload: React.FC = ({
setCsvValid
}) => {
const apolloClient = useApolloClient();
+ const { pushSnackbarMessage } = useSnackbar();
+ const { t } = useTranslation();
// Implemented with using the apollo client directly instead of the useMutation hook
// to reduce the need for multiple use effects to handle each step change
@@ -42,7 +46,8 @@ export const CSVUpload: React.FC = ({
});
if (!sessionCreation.data?.createUploadSession) {
- console.error('Failed to create upload session');
+ pushSnackbarMessage(t('errors.uploadSessionCreate'), 'error');
+ console.error(sessionCreation.errors);
return;
}
@@ -56,7 +61,8 @@ export const CSVUpload: React.FC = ({
});
if (!uploadUrlQuery.data?.getCSVUploadURL) {
- console.error('Failed to get upload url');
+ pushSnackbarMessage(t('errors.csvUpload'), 'error');
+ console.error(uploadUrlQuery.error);
return;
}
@@ -70,7 +76,8 @@ export const CSVUpload: React.FC = ({
});
if (upload.status != 200) {
- console.error('Failed to upload CSV');
+ pushSnackbarMessage(t('errors.csvUpload'), 'error');
+ console.error(uploadUrlQuery.error);
return;
}
diff --git a/packages/client/src/components/upload/EntryUpload.component.tsx b/packages/client/src/components/upload/EntryUpload.component.tsx
index ffa2e67f..44f23186 100644
--- a/packages/client/src/components/upload/EntryUpload.component.tsx
+++ b/packages/client/src/components/upload/EntryUpload.component.tsx
@@ -6,6 +6,8 @@ import { UploadSession, UploadStatus } from '../../graphql/graphql';
import axios from 'axios';
import { Dispatch, SetStateAction, useState } from 'react';
import { StatusMessage } from '../../models/StatusMessage';
+import { useTranslation } from 'react-i18next';
+import { useSnackbar } from '../../context/Snackbar.context';
export interface EntryUploadProps {
uploadSession: UploadSession | null;
@@ -24,6 +26,9 @@ export const EntryUpload: React.FC = ({
const [uploadProgress, setUploadProgress] = useState(0);
const [uploadComplete, setUploadComplete] = useState(false);
+ const { t } = useTranslation();
+ const { pushSnackbarMessage } = useSnackbar();
+
const handleChange = async (event: React.ChangeEvent) => {
if (!uploadSession) {
console.error('No upload session');
@@ -47,7 +52,8 @@ export const EntryUpload: React.FC = ({
});
if (!uploadUrlQuery.data?.getEntryUploadURL) {
- console.error('Failed to get upload url');
+ pushSnackbarMessage(t('errors.entryUpload'), 'error');
+ console.error(uploadUrlQuery.errors);
return;
}
@@ -71,7 +77,8 @@ export const EntryUpload: React.FC = ({
const completionData = completionResult.data?.completeUploadSession;
if (!completionData) {
- console.error('Failed to complete upload session');
+ pushSnackbarMessage(t('errors.entryUploadComplete'), 'error');
+ console.error(completionData.errors);
return;
}
diff --git a/packages/client/src/context/Snackbar.context.tsx b/packages/client/src/context/Snackbar.context.tsx
new file mode 100644
index 00000000..9c7db744
--- /dev/null
+++ b/packages/client/src/context/Snackbar.context.tsx
@@ -0,0 +1,70 @@
+import { Alert, Snackbar, Stack } from '@mui/material';
+import { createContext, FC, useState, useContext } from 'react';
+
+type SnackbarType = 'success' | 'error' | 'warning' | 'info';
+
+export interface SnackbarContextProps {
+ pushSnackbarMessage: (message: string, type?: SnackbarType) => void;
+}
+
+const SnackbarContext = createContext({} as SnackbarContextProps);
+
+export interface SnackbarProviderProps {
+ children: React.ReactNode;
+}
+
+export interface SnackbarMessage {
+ id: string;
+ message: string;
+ type: SnackbarType;
+}
+
+export const SnackbarProvider: FC = ({ children, ...props }) => {
+ const [messages, setMessages] = useState([]);
+
+ const pushSnackbarMessage = (message: string, type: SnackbarType = 'error') => {
+ setMessages([
+ ...messages,
+ {
+ message,
+ type,
+ id: Math.random().toString(36)
+ }
+ ]);
+ };
+
+ const handleClose = (id: string, reason?: string) => {
+ if (reason === 'clickaway') {
+ return;
+ }
+ setMessages(messages.filter((message) => message.id !== id));
+ };
+
+ return (
+
+ {children}
+
+ {messages.map((message) => (
+ handleClose(message.id)}
+ >
+ handleClose(message.id)}
+ sx={{ width: '100%' }}
+ >
+ {message.message}
+
+
+ ))}
+
+
+ );
+};
+
+export const useSnackbar = () => useContext(SnackbarContext);
diff --git a/packages/client/src/pages/contribute/TaggingInterface.tsx b/packages/client/src/pages/contribute/TaggingInterface.tsx
index edb6f3bd..5d27675f 100644
--- a/packages/client/src/pages/contribute/TaggingInterface.tsx
+++ b/packages/client/src/pages/contribute/TaggingInterface.tsx
@@ -7,6 +7,8 @@ import { useCompleteTagMutation } from '../../graphql/tag/tag';
import { Study } from '../../graphql/graphql';
import { TagProvider, useTag } from '../../context/Tag.context';
import { NoTagNotification } from '../../components/contribute/NoTagNotification.component';
+import { useTranslation } from 'react-i18next';
+import { useSnackbar } from '../../context/Snackbar.context';
export const TaggingInterface: React.FC = () => {
const { study } = useStudy();
@@ -31,6 +33,9 @@ const MainView: React.FC = (props) => {
const [completeTag, completeTagResult] = useCompleteTagMutation();
const [tagData, setTagData] = useState({});
+ const { t } = useTranslation();
+ const { pushSnackbarMessage } = useSnackbar();
+
// Changes made to the tag data
useEffect(() => {
if (tagData && tag) {
@@ -45,8 +50,11 @@ const MainView: React.FC = (props) => {
if (completeTagResult.data) {
// Assign a new tag
requestTag();
+ } else if (completeTagResult.error) {
+ pushSnackbarMessage(t('errors.tagComplete'), 'error');
+ console.error(completeTagResult.error);
}
- }, [completeTagResult.data]);
+ }, [completeTagResult]);
return (
<>
diff --git a/packages/client/src/pages/datasets/ProjectAccess.tsx b/packages/client/src/pages/datasets/ProjectAccess.tsx
index c0fc8a48..32f78fc2 100644
--- a/packages/client/src/pages/datasets/ProjectAccess.tsx
+++ b/packages/client/src/pages/datasets/ProjectAccess.tsx
@@ -6,6 +6,7 @@ import { useEffect, useState } from 'react';
import { DatasetProjectPermission, Project } from '../../graphql/graphql';
import { useGrantProjectDatasetAccessMutation } from '../../graphql/permission/permission';
import { useTranslation } from 'react-i18next';
+import { useSnackbar } from '../../context/Snackbar.context';
export const ProjectAccess: React.FC = () => {
const { project } = useProject();
@@ -13,6 +14,7 @@ export const ProjectAccess: React.FC = () => {
const [projectAccess, setProjectAccess] = useState([]);
const [grantProjectDatasetAccess, grantProjectDatasetAccessResults] = useGrantProjectDatasetAccessMutation();
const { t } = useTranslation();
+ const { pushSnackbarMessage } = useSnackbar();
// For querying for the permissions
useEffect(() => {
@@ -25,6 +27,9 @@ export const ProjectAccess: React.FC = () => {
useEffect(() => {
if (datasetProjectPermissionResults.data) {
setProjectAccess(datasetProjectPermissionResults.data.getDatasetProjectPermissions);
+ } else if (datasetProjectPermissionResults.error) {
+ pushSnackbarMessage(t('errors.datasetPermissionUpdate'), 'error');
+ console.error(datasetProjectPermissionResults.error);
}
}, [datasetProjectPermissionResults]);
diff --git a/packages/client/src/pages/projects/NewProject.tsx b/packages/client/src/pages/projects/NewProject.tsx
index abe14f94..7158e448 100644
--- a/packages/client/src/pages/projects/NewProject.tsx
+++ b/packages/client/src/pages/projects/NewProject.tsx
@@ -6,6 +6,7 @@ import { JsonForms } from '@jsonforms/react';
import { useCreateProjectMutation, useProjectExistsLazyQuery } from '../../graphql/project/project';
import { ErrorObject } from 'ajv';
import { useTranslation } from 'react-i18next';
+import { useSnackbar } from '../../context/Snackbar.context';
const initialData = {
name: '',
@@ -21,6 +22,7 @@ export const NewProject: React.FC = () => {
const [projectExistsQuery, projectExistsResults] = useProjectExistsLazyQuery();
const [additionalErrors, setAdditionalErrors] = useState([]);
const { t } = useTranslation();
+ const { pushSnackbarMessage } = useSnackbar();
const schema = {
type: 'object',
@@ -84,7 +86,8 @@ export const NewProject: React.FC = () => {
useEffect(() => {
if (error) {
- //handle server side error here. For now a simple text is displayed
+ pushSnackbarMessage(t('errors.projectCreate'), 'error');
+ console.error(error);
}
}, [error]);
diff --git a/packages/client/src/pages/projects/ProjectControl.tsx b/packages/client/src/pages/projects/ProjectControl.tsx
index 894a84b2..2d0c3aa9 100644
--- a/packages/client/src/pages/projects/ProjectControl.tsx
+++ b/packages/client/src/pages/projects/ProjectControl.tsx
@@ -8,6 +8,7 @@ import { useDeleteProjectMutation } from '../../graphql/project/project';
import { useConfirmation } from '../../context/Confirmation.context';
import { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
+import { useSnackbar } from '../../context/Snackbar.context';
const ProjectControl: React.FC = () => {
const { projects, updateProjectList } = useProject();
@@ -15,6 +16,7 @@ const ProjectControl: React.FC = () => {
const [deleteProjectMutation, deleteProjectResults] = useDeleteProjectMutation();
const confirmation = useConfirmation();
const { t } = useTranslation();
+ const { pushSnackbarMessage } = useSnackbar();
const handleDelete = async (id: GridRowId) => {
// Execute delete mutation
@@ -32,8 +34,11 @@ const ProjectControl: React.FC = () => {
useEffect(() => {
if (deleteProjectResults.called && deleteProjectResults.data) {
updateProjectList();
+ } else if (deleteProjectResults.error) {
+ pushSnackbarMessage(t('errors.projectDelete'), 'error');
+ console.error(deleteProjectResults.error);
}
- }, [deleteProjectResults.data, deleteProjectResults.called]);
+ }, [deleteProjectResults.data, deleteProjectResults.called, deleteProjectResults.error]);
const columns: GridColDef[] = [
{
diff --git a/packages/client/src/pages/projects/ProjectUserPermissions.tsx b/packages/client/src/pages/projects/ProjectUserPermissions.tsx
index 1b2307a1..dd50985b 100644
--- a/packages/client/src/pages/projects/ProjectUserPermissions.tsx
+++ b/packages/client/src/pages/projects/ProjectUserPermissions.tsx
@@ -7,6 +7,7 @@ import { useGetProjectPermissionsQuery } from '../../graphql/permission/permissi
import { DecodedToken, useAuth } from '../../context/Auth.context';
import { useGrantProjectPermissionsMutation } from '../../graphql/permission/permission';
import { useTranslation } from 'react-i18next';
+import { useSnackbar } from '../../context/Snackbar.context';
export const ProjectUserPermissions: React.FC = () => {
const { project } = useProject();
@@ -29,6 +30,8 @@ interface EditAdminSwitchProps {
const EditAdminSwitch: React.FC = (props) => {
const [grantProjectPermissions, grantProjectPermissionsResults] = useGrantProjectPermissionsMutation();
+ const { t } = useTranslation();
+ const { pushSnackbarMessage } = useSnackbar();
const handleChange = (event: ChangeEvent) => {
grantProjectPermissions({
@@ -43,6 +46,9 @@ const EditAdminSwitch: React.FC = (props) => {
useEffect(() => {
if (grantProjectPermissionsResults.data) {
props.refetch();
+ } else if (grantProjectPermissionsResults.error) {
+ pushSnackbarMessage(t('errors.projectAdminUpdate'), 'error');
+ console.error(grantProjectPermissionsResults.error);
}
}, [grantProjectPermissionsResults]);
@@ -56,7 +62,7 @@ const EditAdminSwitch: React.FC = (props) => {
};
const UserPermissionTable: React.FC<{ project: Project }> = ({ project }) => {
- const { data, refetch } = useGetProjectPermissionsQuery({
+ const { data, refetch, error } = useGetProjectPermissionsQuery({
variables: {
project: project._id
}
@@ -65,12 +71,16 @@ const UserPermissionTable: React.FC<{ project: Project }> = ({ project }) => {
const [rows, setRows] = useState([]);
const { decodedToken } = useAuth();
const { t } = useTranslation();
+ const { pushSnackbarMessage } = useSnackbar();
useEffect(() => {
if (data?.getProjectPermissions) {
setRows(data.getProjectPermissions);
+ } else if (error) {
+ pushSnackbarMessage(t('errors.projectAdminUpdate'), 'error');
+ console.error(error);
}
- }, [data]);
+ }, [data, error]);
const columns: GridColDef[] = [
/* For now, only email is populated, this will change in the future
diff --git a/packages/client/src/pages/studies/EntryControls.tsx b/packages/client/src/pages/studies/EntryControls.tsx
index 428238c7..86e12338 100644
--- a/packages/client/src/pages/studies/EntryControls.tsx
+++ b/packages/client/src/pages/studies/EntryControls.tsx
@@ -7,6 +7,7 @@ import { useGetDatasetsByProjectQuery } from '../../graphql/dataset/dataset';
import { useProject } from '../../context/Project.context';
import ToggleEntryEnabled from '../../components/ToggleEntryEnabled.component';
import { useTranslation } from 'react-i18next';
+import { useSnackbar } from '../../context/Snackbar.context';
export const EntryControls: React.FC = () => {
const { project } = useProject();
@@ -17,12 +18,16 @@ export const EntryControls: React.FC = () => {
}
});
const { t } = useTranslation();
+ const { pushSnackbarMessage } = useSnackbar();
useEffect(() => {
if (getDatasetsByProjectResults.data) {
setDatasets(getDatasetsByProjectResults.data.getDatasetsByProject);
+ } else if (getDatasetsByProjectResults.error) {
+ pushSnackbarMessage(t('errors.datasetsForProject'), 'error');
+ console.error(getDatasetsByProjectResults.error);
}
- }, [getDatasetsByProjectResults.data]);
+ }, [getDatasetsByProjectResults]);
const additionalColumns: GridColDef[] = [
{
diff --git a/packages/client/src/pages/studies/NewStudy.tsx b/packages/client/src/pages/studies/NewStudy.tsx
index 24023038..febdc27f 100644
--- a/packages/client/src/pages/studies/NewStudy.tsx
+++ b/packages/client/src/pages/studies/NewStudy.tsx
@@ -19,6 +19,7 @@ import {
} from '../../graphql/tag/tag';
import { useTranslation } from 'react-i18next';
import { TagFieldFragmentSchema, TagField } from '../../components/tagbuilder/TagProvider';
+import { useSnackbar } from '../../context/Snackbar.context';
export const NewStudy: React.FC = () => {
const [activeStep, setActiveStep] = useState(0);
@@ -37,6 +38,7 @@ export const NewStudy: React.FC = () => {
const [tagSchemaFragments, setTagSchemaFragments] = useState<(TagFieldFragmentSchema | null)[]>([]);
const { t } = useTranslation();
+ const { pushSnackbarMessage } = useSnackbar();
// Handles mantaining which step the user is on and the step limit
useEffect(() => {
@@ -83,7 +85,8 @@ export const NewStudy: React.FC = () => {
});
if (result.errors || !result.data) {
- console.error('Failed to create study');
+ pushSnackbarMessage(t('errors.studyCreate'), 'error');
+ console.error(result.errors);
return;
}
diff --git a/packages/client/src/pages/studies/StudyControl.tsx b/packages/client/src/pages/studies/StudyControl.tsx
index bda2db98..8daa93f3 100644
--- a/packages/client/src/pages/studies/StudyControl.tsx
+++ b/packages/client/src/pages/studies/StudyControl.tsx
@@ -8,6 +8,7 @@ import { useDeleteStudyMutation } from '../../graphql/study/study';
import { useEffect } from 'react';
import { useConfirmation } from '../../context/Confirmation.context';
import { useTranslation } from 'react-i18next';
+import { useSnackbar } from '../../context/Snackbar.context';
export const StudyControl: React.FC = () => {
const { studies, updateStudies } = useStudy();
@@ -15,6 +16,7 @@ export const StudyControl: React.FC = () => {
const [deleteStudyMutation, deleteStudyResults] = useDeleteStudyMutation();
const confirmation = useConfirmation();
const { t } = useTranslation();
+ const { pushSnackbarMessage } = useSnackbar();
const handleDelete = async (id: GridRowId) => {
// Execute delete mutation
@@ -32,8 +34,11 @@ export const StudyControl: React.FC = () => {
useEffect(() => {
if (deleteStudyResults.called && deleteStudyResults.data) {
updateStudies();
+ } else if (deleteStudyResults.error) {
+ pushSnackbarMessage(t('errors.studyDelete'), 'error');
+ console.error(deleteStudyResults.error);
}
- }, [deleteStudyResults.called, deleteStudyResults.data]);
+ }, [deleteStudyResults.called, deleteStudyResults.data, deleteStudyResults.error]);
const columns: GridColDef[] = [
{
diff --git a/packages/client/src/pages/studies/TagTrainingView.tsx b/packages/client/src/pages/studies/TagTrainingView.tsx
index 3e0d920e..bf806617 100644
--- a/packages/client/src/pages/studies/TagTrainingView.tsx
+++ b/packages/client/src/pages/studies/TagTrainingView.tsx
@@ -5,6 +5,7 @@ import { useEffect, useState } from 'react';
import { TagGridView } from '../../components/tag/view/TagGridView.component';
import { Typography } from '@mui/material';
import { useTranslation } from 'react-i18next';
+import { useSnackbar } from '../../context/Snackbar.context';
export const TagTrainingView: React.FC = () => {
const state = useLocation().state;
@@ -12,12 +13,16 @@ export const TagTrainingView: React.FC = () => {
const study: Study = state.study;
const [tags, setTags] = useState([]);
const { t } = useTranslation();
+ const { pushSnackbarMessage } = useSnackbar();
const trainingTags = useGetTrainingTagsQuery({ variables: { study: study._id, user: user.uid } });
useEffect(() => {
if (trainingTags.data) {
setTags(trainingTags.data.getTrainingTags);
+ } else if (trainingTags.error) {
+ pushSnackbarMessage(t('errors.tagsQuery'), 'error');
+ console.error(trainingTags.error);
}
}, [trainingTags]);