diff --git a/src/frontend/src/components/ManageProject/EditTab/FormUpdateTab.tsx b/src/frontend/src/components/ManageProject/EditTab/FormUpdateTab.tsx index 467800de7e..6271f7d4ee 100644 --- a/src/frontend/src/components/ManageProject/EditTab/FormUpdateTab.tsx +++ b/src/frontend/src/components/ManageProject/EditTab/FormUpdateTab.tsx @@ -110,7 +110,7 @@ const FormUpdateTab = ({ projectId }) => { multiple={false} data={uploadForm || []} filterKey="url" - onUploadFile={(updatedFiles) => { + onUploadFile={(updatedFiles: FileType[]) => { dispatch(CreateProjectActions.SetCustomFileValidity(false)); setUploadForm(updatedFiles); }} diff --git a/src/frontend/src/components/common/BarChart.tsx b/src/frontend/src/components/common/BarChart.tsx index a087a5a3d6..ce76270d1d 100644 --- a/src/frontend/src/components/common/BarChart.tsx +++ b/src/frontend/src/components/common/BarChart.tsx @@ -1,7 +1,15 @@ import React, { useState } from 'react'; import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts'; -const CustomBarChart = ({ data, xLabel, yLabel, dataKey, nameKey }) => { +type customBarChartType = { + data: Record[]; + xLabel: string; + yLabel: string; + dataKey: string; + nameKey: string; +}; + +const CustomBarChart = ({ data, xLabel, yLabel, dataKey, nameKey }: customBarChartType) => { const [size, setSize] = useState({ width: 0, height: 0 }); return ( diff --git a/src/frontend/src/components/common/BottomSheet.tsx b/src/frontend/src/components/common/BottomSheet.tsx index ceb5156b51..997730cd0d 100644 --- a/src/frontend/src/components/common/BottomSheet.tsx +++ b/src/frontend/src/components/common/BottomSheet.tsx @@ -1,7 +1,12 @@ import React, { useEffect, useRef, useState } from 'react'; import FmtmLogo from '@/assets/images/hotLog.png'; -const BottomSheet = ({ body, onClose }) => { +type bottomSheetType = { + body: React.ReactElement; + onClose: () => void; +}; + +const BottomSheet = ({ body, onClose }: bottomSheetType) => { const sheetContentRef: any = useRef(null); const bottomSheetRef: any = useRef(null); const logoRef: any = useRef(null); @@ -19,7 +24,7 @@ const BottomSheet = ({ body, onClose }) => { updateSheetHeight(50); }, []); - const updateSheetHeight = (height) => { + const updateSheetHeight = (height: number) => { if (sheetContentRef.current) { sheetContentRef.current.style.height = `${height}vh`; const top = sheetContentRef.current.getBoundingClientRect().top; diff --git a/src/frontend/src/components/common/Checkbox.tsx b/src/frontend/src/components/common/Checkbox.tsx index 646cf4f6c0..f8f117a939 100644 --- a/src/frontend/src/components/common/Checkbox.tsx +++ b/src/frontend/src/components/common/Checkbox.tsx @@ -52,7 +52,13 @@ export const CustomCheckbox = ({ return (
- +

{ +type chipsType = { + data: string[]; + clearChip: (i: number) => void; +}; + +const Chips = ({ data, clearChip }: chipsType) => { return (

- {data.map((item, i) => ( + {data.map((item: string, i: number) => (
{ const [imageURL, setImageURL] = useState(''); const [imageDropdownOpen, setImageDropdownOpen] = useState(false); - const isEditorActive = (editorItem) => { + const isEditorActive = (editorItem: string) => { if (editor?.isActive(editorItem)) { return 'fmtm-text-primaryRed fmtm-bg-red-100'; } diff --git a/src/frontend/src/components/common/FileInputComponent.tsx b/src/frontend/src/components/common/FileInputComponent.tsx index e7865637c4..7e6a965175 100644 --- a/src/frontend/src/components/common/FileInputComponent.tsx +++ b/src/frontend/src/components/common/FileInputComponent.tsx @@ -1,6 +1,16 @@ import React, { useRef } from 'react'; import AssetModules from '@/shared/AssetModules.js'; +type fileInputComponentType = { + accept: string; + customFile: any; + onChange: (e: React.ChangeEvent) => void; + onResetFile: () => void; + btnText: string; + fileDescription: string; + errorMsg: string; +}; + const FileInputComponent = ({ accept = '.geojson, .json', customFile, @@ -9,7 +19,7 @@ const FileInputComponent = ({ btnText = 'Select File', fileDescription = '*The supported file formats are zipped shapefile, geojson or kml files.', errorMsg, -}) => { +}: fileInputComponentType) => { const customFileRef = useRef(null); return (
diff --git a/src/frontend/src/components/common/KebabMenu.tsx b/src/frontend/src/components/common/KebabMenu.tsx index 08ccf2d142..49cc32b43e 100644 --- a/src/frontend/src/components/common/KebabMenu.tsx +++ b/src/frontend/src/components/common/KebabMenu.tsx @@ -3,17 +3,19 @@ import AssetModules from '../../shared/AssetModules.js'; type optionType = { id: number | string; icon: React.ReactNode; label: string; onClick: any }; +type directionType = 'left-top' | 'left-bottom' | 'right-bottom' | 'right-top' | 'top-left' | 'top-right'; + type kebabMenuType = { options: optionType[]; stopPropagation: boolean; - direction?: 'left-top' | 'left-bottom' | 'right-bottom' | 'right-top' | 'top-left' | 'top-right'; + direction?: directionType; data: {}; pid: string | number; openedModalId: string | number; onDropdownOpen: () => void; }; -function getPosition(direction) { +function getPosition(direction: directionType) { switch (direction) { case 'left-top': return 'fmtm-top-[2px] fmtm-right-[40px]'; diff --git a/src/frontend/src/components/common/LineChart.tsx b/src/frontend/src/components/common/LineChart.tsx index 137a8142f5..475c561a87 100644 --- a/src/frontend/src/components/common/LineChart.tsx +++ b/src/frontend/src/components/common/LineChart.tsx @@ -1,7 +1,16 @@ import React, { useState } from 'react'; import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'; -const CustomLineChart = ({ data, xAxisDataKey, lineOneKey, lineTwoKey, xLabel, yLabel }) => { +type customLineChartType = { + data: Record[]; + xAxisDataKey: string; + lineOneKey: string; + lineTwoKey: string; + xLabel?: string; + yLabel?: string; +}; + +const CustomLineChart = ({ data, xAxisDataKey, lineOneKey, lineTwoKey, xLabel, yLabel }: customLineChartType) => { const [size, setSize] = useState({ width: 0, height: 0 }); return ( diff --git a/src/frontend/src/components/common/PieChart.tsx b/src/frontend/src/components/common/PieChart.tsx index 36a208355a..06b0e2d03e 100644 --- a/src/frontend/src/components/common/PieChart.tsx +++ b/src/frontend/src/components/common/PieChart.tsx @@ -1,6 +1,12 @@ import React, { useState } from 'react'; import { PieChart, Pie, Cell, ResponsiveContainer, Tooltip, Legend } from 'recharts'; +type customPieChartType = { + data: Record[]; + dataKey: string; + nameKey: string; +}; + const COLORS = ['#F19C3C', '#D73F3F', '#FFB74D', '#EC407A']; const RADIAN = Math.PI / 180; @@ -17,7 +23,7 @@ const renderCustomizedLabel = ({ cx, cy, midAngle, innerRadius, outerRadius, per ); }; -const renderColorfulLegendText = (value, entry) => ( +const renderColorfulLegendText = (value: string, entry: any) => ( {value} ); @@ -45,7 +51,7 @@ const CustomLegend = ({ payload }) => (
); -const CustomPieChart = ({ data, dataKey, nameKey }) => { +const CustomPieChart = ({ data, dataKey, nameKey }: customPieChartType) => { const [size, setSize] = useState({ width: 0, height: 0 }); return ( @@ -79,7 +85,7 @@ const CustomPieChart = ({ data, dataKey, nameKey }) => { verticalAlign="bottom" iconSize={10} formatter={renderColorfulLegendText} - content={ COLORS[index % COLORS.length])} />} + content={ COLORS[index % COLORS.length])} />} /> diff --git a/src/frontend/src/components/common/StepSwitcher.tsx b/src/frontend/src/components/common/StepSwitcher.tsx index c16cdcf866..47bcf627ba 100644 --- a/src/frontend/src/components/common/StepSwitcher.tsx +++ b/src/frontend/src/components/common/StepSwitcher.tsx @@ -3,15 +3,22 @@ import AssetModules from '@/shared/AssetModules.js'; import { CommonActions } from '@/store/slices/CommonSlice'; import CoreModules from '@/shared/CoreModules.js'; import { useNavigate } from 'react-router-dom'; +import { ICreateProjectSteps } from '@/constants/StepFormConstants'; -const StepSwitcher = ({ data, flag, switchSteps }) => { - interface IIndividualStep { - url: string; - step: number; - label: string; - name: string; - } +type stepSwitcherPropType = { + data: ICreateProjectSteps[]; + flag: string; + switchSteps: boolean; +}; + +interface IIndividualStep { + url: string; + step: number; + label: string; + name: string; +} +const StepSwitcher = ({ data, flag, switchSteps }: stepSwitcherPropType) => { const dispatch = CoreModules.useAppDispatch(); const navigate = useNavigate(); const currentStep = CoreModules.useAppSelector((state) => state.common.currentStepFormStep[flag]); diff --git a/src/frontend/src/components/common/UploadArea.tsx b/src/frontend/src/components/common/UploadArea.tsx index e24c565b8f..2c6649966f 100644 --- a/src/frontend/src/components/common/UploadArea.tsx +++ b/src/frontend/src/components/common/UploadArea.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useRef, useState } from 'react'; import { useDispatch } from 'react-redux'; -import { CommonActions } from '../../store/slices/CommonSlice'; -import AssetModules from '../../shared/AssetModules.js'; +import { CommonActions } from '@/store/slices/CommonSlice'; +import AssetModules from '@/shared/AssetModules'; import { v4 as uuidv4 } from 'uuid'; type FileType = { @@ -11,7 +11,17 @@ type FileType = { isDeleted: boolean; }; -const UploadArea = ({ title, label, acceptedInput, data, onUploadFile, multiple, filterKey }) => { +type uploadAreaPropType = { + title: string; + label: string; + multiple: boolean; + data: FileType[]; + filterKey: string; + onUploadFile: (updatedFiles: FileType[]) => void; + acceptedInput: string; +}; + +const UploadArea = ({ title, label, acceptedInput, data, onUploadFile, multiple, filterKey }: uploadAreaPropType) => { const fileInputRef = useRef(null); const dispatch = useDispatch(); const [selectedFiles, setSelectedFiles] = useState([]); @@ -83,7 +93,7 @@ const UploadArea = ({ title, label, acceptedInput, data, onUploadFile, multiple, const id = uuidv4(); return fileList.push({ id, name, [filterKey]: file, isDeleted }); } - if (acceptedInput.includes(fileType)) { + if (fileType && acceptedInput.includes(fileType)) { const id = uuidv4(); const isDeleted = false; return fileList.push({ id, name, [filterKey]: file, isDeleted }); @@ -102,7 +112,7 @@ const UploadArea = ({ title, label, acceptedInput, data, onUploadFile, multiple, if (multiple) { onUploadFile([...fileList, ...data]); } else { - onUploadFile([fileList.at(fileList.length - 1)]); + onUploadFile([fileList.at(fileList.length - 1) as FileType]); } } else { onUploadFile(data); diff --git a/src/frontend/src/components/createnewproject/DataExtract.tsx b/src/frontend/src/components/createnewproject/DataExtract.tsx index 8bfda464dc..4efe9ad4ea 100644 --- a/src/frontend/src/components/createnewproject/DataExtract.tsx +++ b/src/frontend/src/components/createnewproject/DataExtract.tsx @@ -226,13 +226,11 @@ const DataExtract = ({ flag, customDataExtractUpload, setCustomDataExtractUpload
Map Features

- - You may either choose to use OSM data, or upload your own data for the mapping project. - + You may either choose to use OSM data, or upload your own data for the mapping project. The relevant map features that exist on OSM are imported based on the select map area.{' '} - You can use these map features to use the 'select from map' functionality from ODK that allows you - to select the feature to collect data for. + You can use these map features to use the 'select from map' functionality from ODK that allows you to select + the feature to collect data for. {' '}

diff --git a/src/frontend/src/components/home/ProjectListMap.tsx b/src/frontend/src/components/home/ProjectListMap.tsx index 638a2c48ac..7c432a5b0f 100644 --- a/src/frontend/src/components/home/ProjectListMap.tsx +++ b/src/frontend/src/components/home/ProjectListMap.tsx @@ -4,24 +4,13 @@ import { MapContainer as MapComponent } from '@/components/MapComponent/OpenLaye import LayerSwitcherControl from '@/components/MapComponent/OpenLayersComponent/LayerSwitcher/index.js'; import { ClusterLayer } from '@/components/MapComponent/OpenLayersComponent/Layers'; import CoreModules from '@/shared/CoreModules'; -import { geojsonObjectModel } from '@/constants/geojsonObjectModal'; -import { defaultStyles, getStyles } from '@/components/MapComponent/OpenLayersComponent/helpers/styleUtils'; +import { geojsonObjectModel, geojsonObjectModelType } from '@/constants/geojsonObjectModal'; +import { defaultStyles } from '@/components/MapComponent/OpenLayersComponent/helpers/styleUtils'; import MarkerIcon from '@/assets/images/red_marker.png'; import { useNavigate } from 'react-router-dom'; import { Style, Text, Icon, Fill } from 'ol/style'; import { projectType } from '@/models/home/homeModel'; -type HomeProjectSummaryType = { - features: { geometry: any; properties: any; type: any }[]; - type: string; - SRID: { - type: string; - properties: { - name: string; - }; - }; -}; - const getIndividualStyle = (featureProperty) => { const style = new Style({ image: new Icon({ @@ -43,7 +32,7 @@ const getIndividualStyle = (featureProperty) => { const ProjectListMap = () => { const navigate = useNavigate(); - const [projectGeojson, setProjectGeojson] = useState(null); + const [projectGeojson, setProjectGeojson] = useState(null); const { mapRef, map } = useOLMap({ // center: fromLonLat([85.3, 27.7]), center: [0, 0], @@ -54,7 +43,7 @@ const ProjectListMap = () => { const homeProjectSummary: projectType[] = CoreModules.useAppSelector((state) => state.home.homeProjectSummary); useEffect(() => { if (homeProjectSummary?.length === 0) return; - const convertedHomeProjectSummaryGeojson: HomeProjectSummaryType = { + const convertedHomeProjectSummaryGeojson: geojsonObjectModelType = { ...geojsonObjectModel, features: homeProjectSummary.map((project) => ({ type: 'Feature', diff --git a/src/frontend/src/components/organisation/OrganisationGridCard.tsx b/src/frontend/src/components/organisation/OrganisationGridCard.tsx index 1181d06207..7dd4a05655 100644 --- a/src/frontend/src/components/organisation/OrganisationGridCard.tsx +++ b/src/frontend/src/components/organisation/OrganisationGridCard.tsx @@ -3,8 +3,14 @@ import CoreModules from '@/shared/CoreModules'; import CustomizedImage from '@/utilities/CustomizedImage'; import { useNavigate } from 'react-router-dom'; import { user_roles } from '@/types/enums'; +import { GetOrganisationDataModel } from '@/models/organisation/organisationModel'; -const OrganisationGridCard = ({ filteredData, allDataLength }) => { +type organizationGridCardType = { + filteredData: GetOrganisationDataModel[]; + allDataLength: number; +}; + +const OrganisationGridCard = ({ filteredData, allDataLength }: organizationGridCardType) => { const navigate = useNavigate(); const authDetails = CoreModules.useAppSelector((state) => state.login.authDetails); const cardStyle = { diff --git a/src/frontend/src/constants/StepFormConstants.ts b/src/frontend/src/constants/StepFormConstants.ts index 658fb82d58..d15513bd4f 100644 --- a/src/frontend/src/constants/StepFormConstants.ts +++ b/src/frontend/src/constants/StepFormConstants.ts @@ -1,4 +1,4 @@ -interface ICreateProjectSteps { +export interface ICreateProjectSteps { url: string; step: number; label: string; diff --git a/src/frontend/src/constants/geojsonObjectModal.ts b/src/frontend/src/constants/geojsonObjectModal.ts index 89d8b06cbf..a3e28bf1ce 100644 --- a/src/frontend/src/constants/geojsonObjectModal.ts +++ b/src/frontend/src/constants/geojsonObjectModal.ts @@ -1,4 +1,15 @@ -export const geojsonObjectModel = { +export type geojsonObjectModelType = { + features: { geometry: any; properties: any; type: any }[]; + type: string; + SRID: { + type: string; + properties: { + name: string; + }; + }; +}; + +export const geojsonObjectModel: geojsonObjectModelType = { type: 'FeatureCollection', SRID: { type: 'name', diff --git a/src/frontend/src/models/geojsonObjectModel.js b/src/frontend/src/models/geojsonObjectModel.js deleted file mode 100755 index 89d8b06cbf..0000000000 --- a/src/frontend/src/models/geojsonObjectModel.js +++ /dev/null @@ -1,10 +0,0 @@ -export const geojsonObjectModel = { - type: 'FeatureCollection', - SRID: { - type: 'name', - properties: { - name: 'EPSG:3857', - }, - }, - features: [], -}; diff --git a/src/frontend/src/routes.jsx b/src/frontend/src/routes.jsx index e7c415f5a5..b010f0066a 100755 --- a/src/frontend/src/routes.jsx +++ b/src/frontend/src/routes.jsx @@ -1,7 +1,6 @@ import React, { Suspense } from 'react'; import { createBrowserRouter } from 'react-router-dom'; import Home from '@/views/Home'; -import Tabbed from '@/views/Tabbed'; import MainView from '@/views/MainView'; import ProtectedRoute from '@/utilities/ProtectedRoute'; import NotFoundPage from '@/views/NotFound404'; @@ -17,9 +16,6 @@ import ProjectDetailsV2 from '@/views/ProjectDetailsV2'; import ProjectSubmissions from '@/views/ProjectSubmissions'; import ManageProject from '@/views/ManageProject'; -const Submissions = React.lazy(() => import('./views/Submissions')); -const Tasks = React.lazy(() => import('./views/Tasks')); - const routes = createBrowserRouter([ { element: , @@ -71,12 +67,6 @@ const routes = createBrowserRouter([ ), - path: '/tabbed', - element: ( - - - - ), }, { path: '/project-submissions/:projectId', @@ -90,19 +80,6 @@ const routes = createBrowserRouter([ ), }, - - { - path: '/project/:projectId/tasks/:taskId', - element: ( - -
}> - - - - - - ), - }, { path: '/project/:projectId/tasks/:taskId/submission/:instanceId', element: ( @@ -115,18 +92,6 @@ const routes = createBrowserRouter([ ), }, - { - path: '/submissions/:id', - element: ( - -
}> - - - - - - ), - }, { path: '/project/:id', element: ( diff --git a/src/frontend/src/utilfunctions/checkWGS84Projection.js b/src/frontend/src/utilfunctions/checkWGS84Projection.ts similarity index 81% rename from src/frontend/src/utilfunctions/checkWGS84Projection.js rename to src/frontend/src/utilfunctions/checkWGS84Projection.ts index 638126b19c..e2998691b3 100644 --- a/src/frontend/src/utilfunctions/checkWGS84Projection.js +++ b/src/frontend/src/utilfunctions/checkWGS84Projection.ts @@ -1,8 +1,9 @@ import OLVectorLayer from 'ol/layer/Vector'; import GeoJSON from 'ol/format/GeoJSON'; import { Vector as VectorSource } from 'ol/source'; +import { DrawnGeojsonTypes } from '@/store/types/ICreateProject'; -function checkWGS84Projection(drawnGeojson) { +function checkWGS84Projection(drawnGeojson: DrawnGeojsonTypes | null) { const vectorLyr = new OLVectorLayer({ source: new VectorSource({ features: new GeoJSON().readFeatures(drawnGeojson), @@ -13,7 +14,7 @@ function checkWGS84Projection(drawnGeojson) { const extent = vectorLyr.getSource()?.getExtent(); try { - if (extent?.length > 0) { + if (extent && extent?.length > 0) { const longitude = extent[0]; const latitude = extent[1]; if ( diff --git a/src/frontend/src/utilfunctions/commonUtils.ts b/src/frontend/src/utilfunctions/commonUtils.ts index 3df243017b..2ebf3d7f69 100644 --- a/src/frontend/src/utilfunctions/commonUtils.ts +++ b/src/frontend/src/utilfunctions/commonUtils.ts @@ -10,7 +10,7 @@ export const camelToFlat = (word: string): string => ( (word = word.replace(/[A-Z]/g, ' $&')), word[0].toUpperCase() + word.slice(1) ); -export const isStatusSuccess = (status: number) => { +export const isStatusSuccess = (status: number): boolean => { if (status < 300) { return true; } @@ -18,12 +18,12 @@ export const isStatusSuccess = (status: number) => { }; // get date N days ago -export const dateNDaysAgo = (NDays: number) => { +export const dateNDaysAgo = (NDays: number): string => { return new Date(new Date().getTime() - NDays * 24 * 60 * 60 * 1000).toISOString(); }; // extract month & day in MM/DD format for chart date labels -export const getMonthDate = (date: string) => { +export const getMonthDate = (date: string): string => { const splittedDate = date?.split('T')[0]?.split('-'); return `${splittedDate[1]}/${splittedDate[2]}`; }; diff --git a/src/frontend/src/utilfunctions/compareUtils.js b/src/frontend/src/utilfunctions/compareUtils.ts similarity index 60% rename from src/frontend/src/utilfunctions/compareUtils.js rename to src/frontend/src/utilfunctions/compareUtils.ts index ba6d7e1bf4..a484a8fa43 100755 --- a/src/frontend/src/utilfunctions/compareUtils.js +++ b/src/frontend/src/utilfunctions/compareUtils.ts @@ -1,4 +1,4 @@ -function diffObject(firstObject, secondObject) { +const diffObject = (firstObject: Record, secondObject: Record): Record => { const diffObj = Object.keys(secondObject).reduce((diff, key) => { if (firstObject[key] === secondObject[key]) return diff; return { @@ -7,9 +7,10 @@ function diffObject(firstObject, secondObject) { }; }, {}); return diffObj; -} -function diffArray(array1, array2) { +}; + +const diffArray = (array1: Record[], array2: Record[]): Record[] => { return array1.filter((object1) => !array2.some((object2) => object1.id === object2.id)); -} +}; export { diffArray, diffObject }; diff --git a/src/frontend/src/utilfunctions/filterParams.ts b/src/frontend/src/utilfunctions/filterParams.ts index cba95024e9..93b9c3c798 100644 --- a/src/frontend/src/utilfunctions/filterParams.ts +++ b/src/frontend/src/utilfunctions/filterParams.ts @@ -1,4 +1,4 @@ -function filterParams(params: {}): {} { +const filterParams = (params: Record): Record => { const filteredParams = {}; Object.keys(params).forEach((key: string) => { if (params[key] !== null && params[key] !== '') { @@ -6,6 +6,6 @@ function filterParams(params: {}): {} { } }); return filteredParams; -} +}; export default filterParams; diff --git a/src/frontend/src/utilfunctions/getTaskStatusStyle.js b/src/frontend/src/utilfunctions/getTaskStatusStyle.ts similarity index 91% rename from src/frontend/src/utilfunctions/getTaskStatusStyle.js rename to src/frontend/src/utilfunctions/getTaskStatusStyle.ts index 94a5cb8fda..ccab75f1d8 100644 --- a/src/frontend/src/utilfunctions/getTaskStatusStyle.js +++ b/src/frontend/src/utilfunctions/getTaskStatusStyle.ts @@ -3,8 +3,9 @@ import { getCenter } from 'ol/extent'; import { Point } from 'ol/geom'; import AssetModules from '@/shared/AssetModules'; import { task_status } from '@/types/enums'; +import { EntityOsmMap } from '@/store/types/IProject'; -function createPolygonStyle(fillColor, strokeColor) { +function createPolygonStyle(fillColor: string, strokeColor: string) { return new Style({ stroke: new Stroke({ color: strokeColor, @@ -16,7 +17,8 @@ function createPolygonStyle(fillColor, strokeColor) { zIndex: 10, }); } -function createIconStyle(iconSrc) { + +function createIconStyle(iconSrc: string) { return new Style({ image: new Icon({ anchor: [0.5, 1], @@ -35,7 +37,7 @@ function createIconStyle(iconSrc) { const strokeColor = 'rgb(0,0,0,0.3)'; const secondaryStrokeColor = 'rgb(0,0,0,1)'; -const getTaskStatusStyle = (feature, mapTheme, taskLockedByUser) => { +const getTaskStatusStyle = (feature: Record, mapTheme: Record, taskLockedByUser: boolean) => { let id = feature.getId().toString().replace('_', ','); const status = id.split(',')[1]; @@ -115,9 +117,10 @@ const getTaskStatusStyle = (feature, mapTheme, taskLockedByUser) => { return geojsonStyles[status]; }; -export const getFeatureStatusStyle = (osmId, mapTheme, entityOsmMap) => { - const entity = entityOsmMap?.find((entity) => entity?.osm_id === osmId); - const status = task_status[entity?.status]; +export const getFeatureStatusStyle = (osmId: string, mapTheme: Record, entityOsmMap: EntityOsmMap[]) => { + const entity = entityOsmMap?.find((entity) => entity?.osm_id === osmId) as EntityOsmMap; + let status = task_status[entity?.status]; + const borderStrokeColor = '#FF0000'; const lockedPolygonStyle = createPolygonStyle( diff --git a/src/frontend/src/utilities/AppLoader.jsx b/src/frontend/src/utilities/AppLoader.tsx similarity index 69% rename from src/frontend/src/utilities/AppLoader.jsx rename to src/frontend/src/utilities/AppLoader.tsx index b4da0ebf9f..758d6c4f77 100644 --- a/src/frontend/src/utilities/AppLoader.jsx +++ b/src/frontend/src/utilities/AppLoader.tsx @@ -1,16 +1,5 @@ import React from 'react'; -import { useState, CSSProperties } from 'react'; -import ClipLoader from 'react-spinners/ClipLoader'; -import { - SyncLoader, - PropagateLoader, - ClockLoader, - RotateLoader, - MoonLoader, - PulseLoader, - ScaleLoader, - DotLoader, -} from 'react-spinners'; +import { DotLoader } from 'react-spinners'; import CoreModules from '@/shared/CoreModules'; const override = { @@ -18,6 +7,7 @@ const override = { margin: '2 auto', borderColor: 'red', }; + const Loader = () => { const appLoading = CoreModules.useAppSelector((state) => state.common.loading); const defaultTheme = CoreModules.useAppSelector((state) => state.theme.hotTheme); diff --git a/src/frontend/src/utilities/CustomizedImage.tsx b/src/frontend/src/utilities/CustomizedImage.tsx index 155d52e5cc..ddbec7da3a 100755 --- a/src/frontend/src/utilities/CustomizedImage.tsx +++ b/src/frontend/src/utilities/CustomizedImage.tsx @@ -5,13 +5,13 @@ import { LazyLoadImage } from 'react-lazy-load-image-component'; type switcherType = { status: 'card' | 'logo'; - width: number; - height: number; + width: string | number; + height?: string | number; }; type CustomizedImageType = { status: 'card' | 'logo'; - style: { width: number; height: number }; + style: { width: string | number; height?: string | number }; }; const Switcher = ({ status, width, height }: switcherType) => { diff --git a/src/frontend/src/utilities/CustomizedModal.tsx b/src/frontend/src/utilities/CustomizedModal.tsx index 8bf149a42b..caeb05ddf4 100644 --- a/src/frontend/src/utilities/CustomizedModal.tsx +++ b/src/frontend/src/utilities/CustomizedModal.tsx @@ -3,7 +3,14 @@ import clsx from 'clsx'; import { styled, Box, Theme } from '@mui/system'; import { Modal } from '@mui/base/Modal'; -export default function CustomizedModal({ style = defaultStyle, children, isOpen, toggleOpen }) { +type customizeModal = { + style: Record; + children: React.ReactNode; + isOpen: boolean; + toggleOpen: (flag: boolean) => void; +}; + +export default function CustomizedModal({ style = defaultStyle, children, isOpen, toggleOpen }: customizeModal) { const handleClose = () => toggleOpen(false); return ( diff --git a/src/frontend/src/views/Submissions.tsx b/src/frontend/src/views/Submissions.tsx deleted file mode 100755 index b8fa478d95..0000000000 --- a/src/frontend/src/views/Submissions.tsx +++ /dev/null @@ -1,134 +0,0 @@ -// TODO should this be deleted?? - -import React, { useEffect } from 'react'; -// import '../styles/home.css' -import CoreModules from '@/shared/CoreModules'; -// import { useLocation, useNavigate } from 'react-router-dom'; -import Avatar from '@/assets/images/avatar.png'; -// import SubmissionMap from '@/components/SubmissionMap/SubmissionMap'; -import { ProjectActions } from '@/store/slices/ProjectSlice'; -import { ProjectById } from '@/api/Project'; - -const Submissions = () => { - const dispatch = CoreModules.useAppDispatch(); - const state = CoreModules.useAppSelector((state) => state.project); - const projectInfo = CoreModules.useAppSelector((state) => state.home.selectedProject); - const projectSubmissionState = CoreModules.useAppSelector((state) => state.project.projectSubmission); - const projectState = CoreModules.useAppSelector((state) => state.project.project); - // const projectTaskBoundries = CoreModules.useAppSelector((state) => state.project.projectTaskBoundries); - // const projectBuildingGeojson = CoreModules.useAppSelector((state) => state.project.projectBuildingGeojson); - const params = CoreModules.useParams(); - const projectId = params.id; - // const theme = CoreModules.useAppSelector(state => state.theme.hotTheme) - useEffect(() => { - dispatch(ProjectSubmissionService(`${import.meta.env.VITE_API_URL}/submission/?project_id=${projectId}`)); - // dispatch(ProjectDataExtractService(`${import.meta.env.VITE_API_URL}/projects/${projectId}/features`)); - //creating a manual thunk that will make an API call then autamatically perform state mutation whenever we navigate to home page - }, []); - - // Requesting Task Boundaries on Page Load - useEffect(() => { - if (state.projectTaskBoundries.findIndex((project) => project.id == projectId) == -1) { - dispatch(ProjectById(projectId)); - } else { - dispatch(ProjectActions.SetProjectTaskBoundries([])); - dispatch(ProjectById(projectId)); - } - if (Object.keys(state.projectInfo).length == 0) { - dispatch(ProjectActions.SetProjectInfo(projectInfo)); - } else { - if (state.projectInfo.id != projectId) { - dispatch(ProjectActions.SetProjectInfo(projectInfo)); - } - } - }, [params.id]); - return ( - - - - - {/* Project Details SideBar Button for Creating Project */} - - Monitoring - - - {/* END */} - - {/* Upload Area SideBar Button for uploading Area page */} - - Convert - - - - Download CSV - - - {/* END */} - - - {projectSubmissionState?.map((submission) => { - const date = new Date(submission.createdAt); - - const dateOptions = { - minute: 'numeric', - hour: 'numeric', - day: 'numeric', - weekday: 'long', - year: 'numeric', - month: 'long', - }; - - const formattedDate = date.toLocaleDateString('en-US', dateOptions); - return ( - - - {' '} - - - - {submission.submitted_by} - - - Submitted {projectState?.project} at {formattedDate} - - - - ); - })} - - - - {/* */} - - - - ); -}; - -export default Submissions; diff --git a/src/frontend/src/views/Tabbed.tsx b/src/frontend/src/views/Tabbed.tsx deleted file mode 100755 index 150b69f48b..0000000000 --- a/src/frontend/src/views/Tabbed.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import * as React from 'react'; -import { styled } from '@mui/system'; -import { Tabs as TabsUnstyled } from '@mui/base/Tabs'; -import { TabsList as TabsListUnstyled } from '@mui/base/TabsList'; -import { TabPanel as TabPanelUnstyled } from '@mui/base/TabPanel'; -import { buttonClasses as buttonUnstyledClasses } from '@mui/base/Button'; -import { Tab as TabUnstyled, tabClasses as tabUnstyledClasses } from '@mui/base/Tab'; - -const blue = { - 50: '#F0F7FF', - 100: '#C2E0FF', - 200: '#80BFFF', - 300: '#66B2FF', - 400: '#3399FF', - 500: '#d73f3f', - 600: '#0072E5', - 700: '#0059B2', - 800: '#004C99', - 900: '#003A75', -}; - -const grey = { - 50: '#f6f8fa', - 100: '#eaeef2', - 200: '#d0d7de', - 300: '#afb8c1', - 400: '#8c959f', - 500: '#6e7781', - 600: '#57606a', - 700: '#424a53', - 800: '#32383f', - 900: '#24292f', -}; - -const Tab = styled(TabUnstyled)` - font-family: - IBM Plex Sans, - sans-serif; - color: #fff; - cursor: pointer; - font-size: 0.875rem; - font-weight: 600; - background-color: transparent; - width: 100%; - padding: 10px 12px; - margin: 6px 6px; - border: none; - border-radius: 7px; - display: flex; - justify-content: center; - - &:hover { - background-color: ${blue[400]}; - } - - &:focus { - color: #fff; - outline: 3px solid ${blue[200]}; - } - - &.${tabUnstyledClasses.selected} { - background-color: #fff; - color: ${blue[600]}; - } - - &.${buttonUnstyledClasses.disabled} { - opacity: 0.5; - cursor: not-allowed; - } -`; - -const TabPanel = styled(TabPanelUnstyled)( - ({ theme }) => ` - width: 100%; - font-family: IBM Plex Sans, sans-serif; - font-size: 0.875rem; - padding: 20px 12px; - background: ${theme.palette.mode === 'dark' ? grey[900] : '#fff'}; - border: 1px solid ${theme.palette.mode === 'dark' ? grey[700] : grey[200]}; - border-radius: 12px; - opacity: 0.6; - `, -); - -const TabsList = styled(TabsListUnstyled)( - ({ theme }) => ` - min-width: 400px; - background-color: ${blue[500]}; - border-radius: 12px; - margin-bottom: 16px; - display: flex; - align-items: center; - justify-content: center; - align-content: space-between; - box-shadow: 0px 4px 30px ${theme.palette.mode === 'dark' ? grey[900] : grey[200]}; - `, -); - -export default function Tabbed() { - return ( - - - My Contributions - Explore Projects - Learn - - My contributions - Explore Projects - Learn - - ); -} diff --git a/src/frontend/src/views/Tasks.tsx b/src/frontend/src/views/Tasks.tsx deleted file mode 100644 index 1d239e3add..0000000000 --- a/src/frontend/src/views/Tasks.tsx +++ /dev/null @@ -1,275 +0,0 @@ -// TODO should this be deleted?? - -import React, { useEffect, useState } from 'react'; -// import '../styles/home.css' -import CoreModules from '@/shared/CoreModules'; -import AssetModules from '@/shared/AssetModules'; -// import { useLocation, useNavigate } from 'react-router-dom'; -// import { styled, alpha } from '@mui/material'; - -import Avatar from '@/assets/images/avatar.png'; -import { ProjectSubmissionService } from '@/api/SubmissionService'; -import { ProjectActions } from '@/store/slices/ProjectSlice'; -import { ProjectById } from '@/api/Project'; -import { getDownloadProjectSubmission } from '@/api/task'; -import { downloadProjectFormLoadingType } from '@/models/project/projectModel'; -const basicGeojsonTemplate = { - type: 'FeatureCollection', - features: [], -}; - -const TasksSubmission = () => { - const dispatch = CoreModules.useAppDispatch(); - const state = CoreModules.useAppSelector((state) => state.project); - const projectInfo = CoreModules.useAppSelector((state) => state.home.selectedProject); - const projectSubmissionState = CoreModules.useAppSelector((state) => state.project.projectSubmission); - const projectState = CoreModules.useAppSelector((state) => state.project.project); - // const projectTaskBoundries = CoreModules.useAppSelector((state) => state.project.projectTaskBoundries); - // const projectBuildingGeojson = CoreModules.useAppSelector((state) => state.project.projectBuildingGeojson); - const params = CoreModules.useParams(); - const projectId = params.projectId; - const taskId = params.taskId; - // const theme = CoreModules.useAppSelector(state => state.theme.hotTheme) - useEffect(() => { - dispatch( - ProjectSubmissionService(`${import.meta.env.VITE_API_URL}/submission/?project_id=${projectId}&task_id=${taskId}`), - ); - // dispatch( - // ProjectDataExtractService( - // `${import.meta.env.VITE_API_URL}/projects/${projectId}/features?task_id=${taskId}`, - // ), - // ); - //creating a manual thunk that will make an API call then autamatically perform state mutation whenever we navigate to home page - }, []); - //Fetch project for the first time - useEffect(() => { - if (state.projectTaskBoundries.findIndex((project) => project.id == projectId) == -1) { - dispatch(ProjectById(projectId)); - // dispatch( - // ProjectDataExtractService( - // `${import.meta.env.VITE_API_URL}/projects/${projectId}/features`, - // ), - // ); - } else { - dispatch(ProjectActions.SetProjectTaskBoundries([])); - dispatch(ProjectById(projectId)); - } - if (Object.keys(state.projectInfo).length == 0) { - dispatch(ProjectActions.SetProjectInfo(projectInfo)); - } else { - if (state.projectInfo.id != projectId) { - dispatch(ProjectActions.SetProjectInfo(projectInfo)); - } - } - }, [params.id]); - const projectTaskBoundries = CoreModules.useAppSelector((state) => state.project.projectTaskBoundries); - const projectBuildingGeojson = CoreModules.useAppSelector((state) => state.project.projectBuildingGeojson); - const [projectBoundaries, setProjectBoundaries] = useState(null); - const [buildingBoundaries, setBuildingBoundaries] = useState(null); - - if (projectTaskBoundries?.length > 0 && projectBoundaries === null) { - const taskGeojsonFeatureCollection = { - ...basicGeojsonTemplate, - features: [ - ...projectTaskBoundries?.[0]?.taskBoundries - ?.filter((task) => task.id == taskId) - .map((task) => ({ - ...task.outline_geojson, - id: task.outline_geojson.properties.uid, - })), - ], - }; - setProjectBoundaries(taskGeojsonFeatureCollection); - } - if (projectBuildingGeojson?.length > 0 && buildingBoundaries === null) { - const buildingGeojsonFeatureCollection = { - ...basicGeojsonTemplate, - features: [ - ...projectBuildingGeojson - ?.filter((task) => task.task_id == taskId) - .map((task) => ({ ...task.geometry, id: task.id })), - ], - // features: projectBuildingGeojson.map((feature) => ({ ...feature.geometry, id: feature.id })) - }; - setBuildingBoundaries(buildingGeojsonFeatureCollection); - } - - const StyledMenu = AssetModules.styled((props) => ( - - ))(({ theme }) => ({ - '& .MuiPaper-root': { - borderRadius: 6, - marginTop: theme.spacing(1), - minWidth: 180, - color: theme.palette.mode === 'light' ? 'rgb(55, 65, 81)' : theme.palette.grey[300], - boxShadow: - 'rgb(255, 255, 255) 0px 0px 0px 0px, rgba(0, 0, 0, 0.05) 0px 0px 0px 1px, rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.05) 0px 4px 6px -2px', - '& .MuiMenu-list': { - padding: '4px 0', - }, - '& .MuiMenuItem-root': { - '& .MuiSvgIcon-root': { - fontSize: 18, - color: theme.palette.text.secondary, - marginRight: theme.spacing(1.5), - }, - '&:active': { - backgroundColor: AssetModules.alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity), - }, - }, - }, - })); - - const handleDownload = (downloadType) => { - if (downloadType === 'csv') { - dispatch( - getDownloadProjectSubmission( - `${ - import.meta.env.VITE_API_URL - }/submission/download?project_id=${projectId}&task_id=${taskId}&export_json=false`, - ), - ); - } else if (downloadType === 'json') { - dispatch( - getDownloadProjectSubmission( - `${ - import.meta.env.VITE_API_URL - }/submission/download?project_id=${projectId}&task_id=${taskId}&export_json=true`, - ), - ); - } - }; - - const downloadSubmissionLoading: downloadProjectFormLoadingType = CoreModules.useAppSelector( - (state) => state.task.downloadSubmissionLoading, - ); - - return ( - - - - - {/* Project Details SideBar Button for Creating Project */} - - Monitoring - - - {/* END */} - - {/* Upload Area SideBar Button for uploading Area page */} - - Convert - - handleDownload('csv')} - sx={{ width: 'unset' }} - loading={downloadSubmissionLoading.type === 'csv' && downloadSubmissionLoading.loading} - loadingPosition="end" - endIcon={} - variant="contained" - color="error" - > - CSV - - - handleDownload('json')} - sx={{ width: 'unset' }} - loading={downloadSubmissionLoading.type === 'json' && downloadSubmissionLoading.loading} - loadingPosition="end" - endIcon={} - variant="contained" - color="error" - > - JSON - - - {/* END */} - - - {projectSubmissionState?.map((submission) => { - const date = new Date(submission.createdAt); - - const dateOptions = { - minute: 'numeric', - hour: 'numeric', - day: 'numeric', - weekday: 'long', - year: 'numeric', - month: 'long', - }; - - const formattedDate = date.toLocaleDateString('en-US', dateOptions); - return ( - - - - {' '} - - - - {submission.submitted_by} - - - Submitted {projectState?.project} at {formattedDate} - - - - - ); - })} - - - - {/* */} - - - - ); -}; - -export default TasksSubmission;