diff --git a/src/frontend/src/components/CreateEditOrganization/ConsentDetailsForm.tsx b/src/frontend/src/components/CreateEditOrganization/ConsentDetailsForm.tsx index cebc2f0f1c..a83b200db2 100644 --- a/src/frontend/src/components/CreateEditOrganization/ConsentDetailsForm.tsx +++ b/src/frontend/src/components/CreateEditOrganization/ConsentDetailsForm.tsx @@ -10,8 +10,10 @@ import { useDispatch } from 'react-redux'; import { OrganisationAction } from '@/store/slices/organisationSlice'; import InstructionsSidebar from '@/components/CreateEditOrganization/InstructionsSidebar'; import { useAppSelector } from '@/types/reduxTypes'; +import useDocumentTitle from '@/utilfunctions/useDocumentTitle'; const ConsentDetailsForm = () => { + useDocumentTitle('Consent Details Form'); const navigate = useNavigate(); const dispatch = useDispatch(); diff --git a/src/frontend/src/components/CreateEditOrganization/CreateEditOrganizationForm.tsx b/src/frontend/src/components/CreateEditOrganization/CreateEditOrganizationForm.tsx index 059d6847e3..9cb889eaf1 100644 --- a/src/frontend/src/components/CreateEditOrganization/CreateEditOrganizationForm.tsx +++ b/src/frontend/src/components/CreateEditOrganization/CreateEditOrganizationForm.tsx @@ -113,6 +113,14 @@ const CreateEditOrganizationForm = ({ organizationId }: { organizationId: string handleCustomChange('fillODKCredentials', false); }, []); + useEffect(() => { + if (organizationId) { + document.title = 'Edit Organization - Field Mapping Tasking Manager'; + } else { + document.title = 'Add Organization - Field Mapping Tasking Manager'; + } + }, []); + return (
{ + useDocumentTitle('Manage Project: Delete Project'); return (
diff --git a/src/frontend/src/components/ManageProject/EditTab/FormUpdateTab.tsx b/src/frontend/src/components/ManageProject/EditTab/FormUpdateTab.tsx index a1bf553802..24c263cacd 100644 --- a/src/frontend/src/components/ManageProject/EditTab/FormUpdateTab.tsx +++ b/src/frontend/src/components/ManageProject/EditTab/FormUpdateTab.tsx @@ -9,6 +9,7 @@ import { PostFormUpdate } from '@/api/CreateProjectService'; import { CreateProjectActions } from '@/store/slices/CreateProjectSlice'; import { CommonActions } from '@/store/slices/CommonSlice'; import { Loader2 } from 'lucide-react'; +import useDocumentTitle from '@/utilfunctions/useDocumentTitle'; type FileType = { id: string; @@ -18,6 +19,7 @@ type FileType = { }; const FormUpdateTab = ({ projectId }) => { + useDocumentTitle('Manage Project: Form Update'); const dispatch = CoreModules.useAppDispatch(); const [uploadForm, setUploadForm] = useState(null); diff --git a/src/frontend/src/components/ManageProject/EditTab/ProjectDescriptionTab.tsx b/src/frontend/src/components/ManageProject/EditTab/ProjectDescriptionTab.tsx index 43aff0e73a..17aa257d62 100644 --- a/src/frontend/src/components/ManageProject/EditTab/ProjectDescriptionTab.tsx +++ b/src/frontend/src/components/ManageProject/EditTab/ProjectDescriptionTab.tsx @@ -10,8 +10,10 @@ import useForm from '@/hooks/useForm'; import CoreModules from '@/shared/CoreModules'; import { CommonActions } from '@/store/slices/CommonSlice'; import RichTextEditor from '@/components/common/Editor/Editor'; +import useDocumentTitle from '@/utilfunctions/useDocumentTitle'; const ProjectDescriptionTab = ({ projectId }) => { + useDocumentTitle('Manage Project: Project Description'); const dispatch = CoreModules.useAppDispatch(); const editProjectDetails: any = CoreModules.useAppSelector((state) => state.createproject.editProjectDetails); const editProjectDetailsLoading: boolean = CoreModules.useAppSelector( diff --git a/src/frontend/src/components/ManageProject/UserTab/AssignTab.tsx b/src/frontend/src/components/ManageProject/UserTab/AssignTab.tsx index 64d4348222..508bbbc432 100644 --- a/src/frontend/src/components/ManageProject/UserTab/AssignTab.tsx +++ b/src/frontend/src/components/ManageProject/UserTab/AssignTab.tsx @@ -4,6 +4,7 @@ import AssetModules from '../../../shared/AssetModules.js'; import Chips from '../../common/Chips'; import { CustomSelect } from '../../common/Select'; import Button from '../..//common/Button'; +import useDocumentTitle from '@/utilfunctions/useDocumentTitle'; const roleList = [ { label: 'Project Manger', value: 'project_manager' }, @@ -11,6 +12,7 @@ const roleList = [ { label: 'Supervisor', value: 'supervisor' }, ]; const AssignTab = () => { + useDocumentTitle('Manage Project: Assign User'); const [user, setUser] = useState(''); const [assignUser, setAssignUser] = useState([]); const [assignedRole, setAssignedRole] = useState(''); diff --git a/src/frontend/src/components/ManageProject/UserTab/InviteTab.tsx b/src/frontend/src/components/ManageProject/UserTab/InviteTab.tsx index c798b8c2d7..dc90a361cc 100644 --- a/src/frontend/src/components/ManageProject/UserTab/InviteTab.tsx +++ b/src/frontend/src/components/ManageProject/UserTab/InviteTab.tsx @@ -4,6 +4,7 @@ import AssetModules from '../../../shared/AssetModules.js'; import Chips from '../../common/Chips'; import { CustomSelect } from '../../common/Select'; import Button from '../..//common/Button'; +import useDocumentTitle from '@/utilfunctions/useDocumentTitle'; const roleList = [ { label: 'Project Manger', value: 'project_manager' }, @@ -11,6 +12,7 @@ const roleList = [ { label: 'Supervisor', value: 'supervisor' }, ]; const InviteTab = () => { + useDocumentTitle('Manage Project: Invite User'); const [user, setUser] = useState(''); const [inviteUser, setInviteUser] = useState([]); const [assignedRole, setAssignedRole] = useState(''); diff --git a/src/frontend/src/components/ProjectSubmissions/SubmissionsInfographics.tsx b/src/frontend/src/components/ProjectSubmissions/SubmissionsInfographics.tsx index decd2f2ebd..b574089a52 100644 --- a/src/frontend/src/components/ProjectSubmissions/SubmissionsInfographics.tsx +++ b/src/frontend/src/components/ProjectSubmissions/SubmissionsInfographics.tsx @@ -17,6 +17,7 @@ import { taskDataTypes, validatedVsMappedInfographicsTypes, } from '@/models/submission/submissionModel'; +import useDocumentTitle from '@/utilfunctions/useDocumentTitle'; const lineKeyData = [ { @@ -88,6 +89,7 @@ const lineKeyData = [ ]; const SubmissionsInfographics = ({ toggleView }) => { + useDocumentTitle('Submission Infographics'); const formSubmissionRef = useRef(null); const projectProgressRef = useRef(null); const totalContributorsRef = useRef(null); diff --git a/src/frontend/src/components/ProjectSubmissions/SubmissionsTable.tsx b/src/frontend/src/components/ProjectSubmissions/SubmissionsTable.tsx index a70e19ec68..a83749be4b 100644 --- a/src/frontend/src/components/ProjectSubmissions/SubmissionsTable.tsx +++ b/src/frontend/src/components/ProjectSubmissions/SubmissionsTable.tsx @@ -21,6 +21,7 @@ import UpdateReviewStatusModal from '@/components/ProjectSubmissions/UpdateRevie import { projectInfoType } from '@/models/project/projectModel'; import { useAppSelector } from '@/types/reduxTypes'; import { camelToFlat } from '@/utilfunctions/commonUtils'; +import useDocumentTitle from '@/utilfunctions/useDocumentTitle'; type filterType = { task_id: string | null; @@ -30,6 +31,7 @@ type filterType = { }; const SubmissionsTable = ({ toggleView }) => { + useDocumentTitle('Submission Table'); const [searchParams, setSearchParams] = useSearchParams(); const initialFilterState: filterType = { diff --git a/src/frontend/src/components/createnewproject/DataExtract.tsx b/src/frontend/src/components/createnewproject/DataExtract.tsx index 49a7f3e75b..dca42365a2 100644 --- a/src/frontend/src/components/createnewproject/DataExtract.tsx +++ b/src/frontend/src/components/createnewproject/DataExtract.tsx @@ -13,6 +13,7 @@ import { FormCategoryService } from '@/api/CreateProjectService'; import FileInputComponent from '@/components/common/FileInputComponent'; import DataExtractValidation from '@/components/createnewproject/validation/DataExtractValidation'; import NewDefineAreaMap from '@/views/NewDefineAreaMap'; +import useDocumentTitle from '@/utilfunctions/useDocumentTitle'; const dataExtractOptions = [ { name: 'data_extract', value: 'osm_data_extract', label: 'Use OSM data extract' }, @@ -20,9 +21,9 @@ const dataExtractOptions = [ ]; const DataExtract = ({ flag, customDataExtractUpload, setCustomDataExtractUpload }) => { + useDocumentTitle('Create Project: Data Extract'); const dispatch = useDispatch(); const navigate = useNavigate(); - console.log(customDataExtractUpload, 'customDataExtractUpload'); const [extractWays, setExtractWays] = useState(''); const projectDetails: any = useAppSelector((state) => state.createproject.projectDetails); const projectAoiGeojson = useAppSelector((state) => state.createproject.drawnGeojson); diff --git a/src/frontend/src/components/createnewproject/ProjectDetailsForm.tsx b/src/frontend/src/components/createnewproject/ProjectDetailsForm.tsx index 1fd60d0a11..da93e1ca82 100644 --- a/src/frontend/src/components/createnewproject/ProjectDetailsForm.tsx +++ b/src/frontend/src/components/createnewproject/ProjectDetailsForm.tsx @@ -14,8 +14,10 @@ import { OrganisationService } from '@/api/CreateProjectService'; import { CustomCheckbox } from '@/components/common/Checkbox'; import { organizationDropdownType } from '@/models/createproject/createProjectModel'; import RichTextEditor from '@/components/common/Editor/Editor'; +import useDocumentTitle from '@/utilfunctions/useDocumentTitle'; const ProjectDetailsForm = ({ flag }) => { + useDocumentTitle('Create Project: Project Details'); const dispatch = useDispatch(); const navigate = useNavigate(); diff --git a/src/frontend/src/components/createnewproject/SelectForm.tsx b/src/frontend/src/components/createnewproject/SelectForm.tsx index 586657d7a0..323de6911e 100644 --- a/src/frontend/src/components/createnewproject/SelectForm.tsx +++ b/src/frontend/src/components/createnewproject/SelectForm.tsx @@ -13,8 +13,10 @@ import SelectFormValidation from '@/components/createnewproject/validation/Selec import { FormCategoryService, ValidateCustomForm } from '@/api/CreateProjectService'; import NewDefineAreaMap from '@/views/NewDefineAreaMap'; import { CustomCheckbox } from '../common/Checkbox'; +import useDocumentTitle from '@/utilfunctions/useDocumentTitle'; const SelectForm = ({ flag, geojsonFile, customFormFile, setCustomFormFile }) => { + useDocumentTitle('Create Project: Select Category'); const dispatch = useDispatch(); const navigate = useNavigate(); diff --git a/src/frontend/src/components/createnewproject/SplitTasks.tsx b/src/frontend/src/components/createnewproject/SplitTasks.tsx index fc22ae03e7..ec172e131a 100644 --- a/src/frontend/src/components/createnewproject/SplitTasks.tsx +++ b/src/frontend/src/components/createnewproject/SplitTasks.tsx @@ -20,6 +20,7 @@ import { import { Modal } from '@/components/common/Modal'; import ProgressBar from '@/components/common/ProgressBar'; import { task_split_type } from '@/types/enums'; +import useDocumentTitle from '@/utilfunctions/useDocumentTitle'; const alogrithmList = [ { name: 'define_tasks', value: task_split_type['divide_on_square'].toString(), label: 'Divide on square' }, @@ -33,6 +34,7 @@ const alogrithmList = [ let generateProjectLogIntervalCb: any = null; const SplitTasks = ({ flag, geojsonFile, setGeojsonFile, customDataExtractUpload, customFormFile }) => { + useDocumentTitle('Create Project: Split Tasks'); const dispatch = useDispatch(); const navigate = useNavigate(); diff --git a/src/frontend/src/components/createnewproject/UploadArea.tsx b/src/frontend/src/components/createnewproject/UploadArea.tsx index 3596a54d48..1a550055cf 100644 --- a/src/frontend/src/components/createnewproject/UploadArea.tsx +++ b/src/frontend/src/components/createnewproject/UploadArea.tsx @@ -15,6 +15,7 @@ import NewDefineAreaMap from '@/views/NewDefineAreaMap'; import { checkWGS84Projection } from '@/utilfunctions/checkWGS84Projection.js'; import { valid } from 'geojson-validation'; import { DivideSquareIcon } from 'lucide-react'; +import useDocumentTitle from '@/utilfunctions/useDocumentTitle'; const uploadAreaOptions = [ { @@ -32,6 +33,7 @@ const uploadAreaOptions = [ ]; const UploadArea = ({ flag, geojsonFile, setGeojsonFile, setCustomDataExtractUpload }) => { + useDocumentTitle('Create Project: Upload Area'); const dispatch = useDispatch(); const navigate = useNavigate(); // const [uploadAreaFile, setUploadAreaFile] = useState(null); diff --git a/src/frontend/src/utilfunctions/useDocumentTitle.ts b/src/frontend/src/utilfunctions/useDocumentTitle.ts new file mode 100644 index 0000000000..40e82b2a03 --- /dev/null +++ b/src/frontend/src/utilfunctions/useDocumentTitle.ts @@ -0,0 +1,20 @@ +import { useRef, useEffect } from 'react'; + +function useDocumentTitle(titleSuffix: string, prevailOnUnmount: boolean = false) { + const defaultTitle = useRef(document.title); + + useEffect(() => { + document.title = `${titleSuffix} - HOT Field Mapping Tasking Manager`; + }, [titleSuffix]); + + useEffect( + () => () => { + if (!prevailOnUnmount) { + document.title = defaultTitle.current; + } + }, + [], + ); +} + +export default useDocumentTitle; diff --git a/src/frontend/src/views/ApproveOrganization.tsx b/src/frontend/src/views/ApproveOrganization.tsx index 02887ab142..a55fc47dc0 100644 --- a/src/frontend/src/views/ApproveOrganization.tsx +++ b/src/frontend/src/views/ApproveOrganization.tsx @@ -1,8 +1,10 @@ import React from 'react'; import ApproveOrganizationHeader from '@/components/ApproveOrganization/ApproveOrganizationHeader'; import OrganizationForm from '@/components/ApproveOrganization/OrganizationForm'; +import useDocumentTitle from '@/utilfunctions/useDocumentTitle'; const ApproveOrganization = () => { + useDocumentTitle('Approve Organization'); return (
diff --git a/src/frontend/src/views/Home.tsx b/src/frontend/src/views/Home.tsx index cf38388a32..84fffc4ed0 100755 --- a/src/frontend/src/views/Home.tsx +++ b/src/frontend/src/views/Home.tsx @@ -9,8 +9,10 @@ import CoreModules from '@/shared/CoreModules'; import ProjectListMap from '@/components/home/ProjectListMap'; import { projectType } from '@/models/home/homeModel'; import { useAppSelector } from '@/types/reduxTypes'; +import useDocumentTitle from '@/utilfunctions/useDocumentTitle'; const Home = () => { + useDocumentTitle('Explore Projects'); const dispatch = CoreModules.useAppDispatch(); const { type } = windowDimention(); diff --git a/src/frontend/src/views/Organisation.tsx b/src/frontend/src/views/Organisation.tsx index f93b23accd..5fd1bcdf75 100644 --- a/src/frontend/src/views/Organisation.tsx +++ b/src/frontend/src/views/Organisation.tsx @@ -8,8 +8,10 @@ import OrganisationGridCard from '@/components/organisation/OrganisationGridCard import OrganisationCardSkeleton from '@/components/organisation/OrganizationCardSkeleton'; import windowDimention from '@/hooks/WindowDimension'; import { useAppSelector } from '@/types/reduxTypes'; +import useDocumentTitle from '@/utilfunctions/useDocumentTitle'; const Organisation = () => { + useDocumentTitle('Organizations'); const dispatch = CoreModules.useAppDispatch(); //dispatch function to perform redux state mutation diff --git a/src/frontend/src/views/ProjectDetailsV2.tsx b/src/frontend/src/views/ProjectDetailsV2.tsx index 1d86f91a19..b918efa818 100644 --- a/src/frontend/src/views/ProjectDetailsV2.tsx +++ b/src/frontend/src/views/ProjectDetailsV2.tsx @@ -43,8 +43,10 @@ import Instructions from '@/components/ProjectDetailsV2/Instructions'; import { readFileFromOPFS } from '@/api/Files'; import DebugConsole from '@/utilities/DebugConsole'; import { CustomCheckbox } from '@/components/common/Checkbox'; +import useDocumentTitle from '@/utilfunctions/useDocumentTitle'; const Home = () => { + useDocumentTitle('Project Details'); const dispatch = CoreModules.useAppDispatch(); const params = CoreModules.useParams(); const navigate = useNavigate(); @@ -78,6 +80,14 @@ const Home = () => { const taskModalStatus = CoreModules.useAppSelector((state) => state.project.taskModalStatus); const projectOpfsBasemapPath = useAppSelector((state) => state?.project?.projectOpfsBasemapPath); + useEffect(() => { + if (state.projectInfo.title) { + document.title = `${state.projectInfo.title} - HOT Field Mapping Tasking Manager`; + } else { + document.title = 'HOT Field Mapping Tasking Manager'; + } + }, [state.projectInfo.title]); + //snackbar handle close funtion const handleClose = (event, reason) => { if (reason === 'clickaway') { diff --git a/src/frontend/src/views/SubmissionDetails.tsx b/src/frontend/src/views/SubmissionDetails.tsx index 6abd07dee1..d7a4ce8e62 100644 --- a/src/frontend/src/views/SubmissionDetails.tsx +++ b/src/frontend/src/views/SubmissionDetails.tsx @@ -8,8 +8,10 @@ import { SubmissionActions } from '@/store/slices/SubmissionSlice'; import UpdateReviewStatusModal from '@/components/ProjectSubmissions/UpdateReviewStatusModal'; import { useAppSelector } from '@/types/reduxTypes'; import { useNavigate } from 'react-router-dom'; +import useDocumentTitle from '@/utilfunctions/useDocumentTitle'; const SubmissionDetails = () => { + useDocumentTitle('Submission Instance'); const dispatch = CoreModules.useAppDispatch(); const params = CoreModules.useParams(); const navigate = useNavigate();