Skip to content

Commit

Permalink
Fix project details map (#910)
Browse files Browse the repository at this point in the history
* feat (projectDetails): map - for small screen, full screen map visible(only map visible)

* feat (projectDetails): map - footer added to the map

* fix (MobileFooter) - border top added

* feat (bottomSheet): bottomSheet component made for mobile device

* feat (projectDetails): activities - bottomSheet made for activities

* feat (projectDetails): project info - added bottom sheet for project information for small screen

* feat (projectDetails) - fmtm logo and back button added for small screen

* fix (Accordion): interface added to props

* feat/fix (projectDetails): projectDetails component projectOption section  splitted to projectOption component. projectOptions added for others bottomSheet

* fix (projectDetails): bottomSheet - converted css to tailwind css, converted dom manipulation to react states

* fix (projectDetails): map - mapcontrols button gap reduced for small screens

* fix (bottomSheet): fmtm logo move bottom sheet expand/contract

* fix (projectDetails): margins/paddings updated for mobile view

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
NSUWAL123 and pre-commit-ci[bot] authored Oct 16, 2023
1 parent ba9c2e5 commit d14062a
Show file tree
Hide file tree
Showing 15 changed files with 640 additions and 257 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Right now, we are in the process of building the prototype. We warmly welcome yo
Create pull requests (PRs) for changes that you think are needed. We would really appreciate your help!

Skills with the following would be beneficial:

- Python
- FastAPI
- Javascript
Expand Down
1 change: 1 addition & 0 deletions src/frontend/src/api/Project.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const ProjectById = (url, existingProjectList, projectId) => {
title: resp.project_info?.[0]?.name,
location_str: resp.location_str,
description: resp.project_info[0]?.description,
short_description: resp.project_info[0]?.short_description,
num_contributors: resp.num_contributors,
total_tasks: resp.total_tasks,
tasks_mapped: resp.tasks_mapped,
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/src/components/ActivitiesPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ const ActivitiesPanel = ({ defaultTheme, state, params, map, view, mapDivPostion
}, [taskDisplay, state, searchText]);

return (
<CoreModules.Stack p={2.5} width={'100%'} spacing={2}>
<CoreModules.Stack width={'100%'} spacing={2} className="sm:fmtm-p-4">
<CoreModules.Typography
variant="h1"
fontSize={defaultTheme.typography.htmlFontSize}
Expand Down
18 changes: 14 additions & 4 deletions src/frontend/src/components/OpenLayersMap.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import Button from './common/Button';
import { ProjectActions } from '../store/slices/ProjectSlice';
import TaskSectionModal from './ProjectDetails/TaskSectionPopup';
import VectorLayer from 'ol/layer/Vector';
import WindowDimension from '../hooks/WindowDimension';

let currentLocationLayer = null;
const OpenLayersMap = ({
defaultTheme,
Expand All @@ -40,6 +42,8 @@ const OpenLayersMap = ({
const [currentLocLayer, setCurrentLocLayer] = useState(null);
const dispatch = CoreModules.useAppDispatch();
const taskModalStatus = CoreModules.useAppSelector((state) => state.project.taskModalStatus);
const { windowSize } = WindowDimension();

function elastic(t) {
return Math.pow(2, -10 * t) * Math.sin(((t - 0.075) * (2 * Math.PI)) / 0.3) + 1;
}
Expand Down Expand Up @@ -177,7 +181,9 @@ const OpenLayersMap = ({
btnDiv.className = 'ol-unselectable ol-control';
index == 0
? (btnDiv.style.top = `${(btnsPosition = btnsPosition + 2)}%`)
: (btnDiv.style.top = `${(btnsPosition = btnsPosition + 9)}%`);
: windowSize.width >= 640
? (btnDiv.style.top = `${(btnsPosition = btnsPosition + 9)}%`)
: (btnDiv.style.top = `${(btnsPosition = btnsPosition + 6)}%`);
btnDiv.appendChild(btn);
var control = new Control({
element: btnDiv,
Expand Down Expand Up @@ -322,13 +328,17 @@ const OpenLayersMap = ({
}, [map, currentLocLayer]);

return (
<CoreModules.Stack spacing={1} direction={'column'} className="fmtm-px-0 sm:fmtm-px-[1rem] fmtm-py-[1rem]">
<CoreModules.Stack spacing={1} direction={'column'} className="fmtm-px-0 sm:fmtm-px-[1rem] sm:fmtm-py-[1rem]">
<CoreModules.Stack
id="project-details-map"
// style={{ border: `4px solid ${defaultTheme.palette.error.main}` }}
justifyContent={'center'}
height={608}
className="fmtm-border-y-[4px] sm:fmtm-border-x-[4px] fmtm-border-primaryRed"
// height={608}
className={`${
windowSize.width <= 640
? 'fmtm-h-[100vh]'
: 'fmtm-border-y-[4px] sm:fmtm-border-x-[4px] fmtm-border-primaryRed fmtm-h-[608px]'
}`}
>
<div ref={mapElement} id="map_container"></div>
{/* <div id="popup" className="ol-popup">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';
import ActivitiesPanel from '../ActivitiesPanel';
import CoreModules from '../../shared/CoreModules';

const MobileActivitiesContents = ({ map, mainView, mapDivPostion }) => {
const params = CoreModules.useParams();
const state = CoreModules.useAppSelector((state) => state.project);
const defaultTheme = CoreModules.useAppSelector((state) => state.theme.hotTheme);

return (
<div className="fmtm-w-full fmtm-bg-white fmtm-mb-[10vh]">
<CoreModules.Stack sx={{ display: 'flex', flexDirection: 'row', justifyContent: 'center' }}>
<ActivitiesPanel
params={params}
state={state.projectTaskBoundries}
defaultTheme={defaultTheme}
map={map}
view={mainView}
mapDivPostion={mapDivPostion}
states={state}
/>
</CoreModules.Stack>
</div>
);
};

export default MobileActivitiesContents;
91 changes: 91 additions & 0 deletions src/frontend/src/components/ProjectDetails/MobileFooter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import React from 'react';
import AssetModules from '../../shared/AssetModules.js';
import CoreModules from '../../shared/CoreModules';
import { ProjectActions } from '../../store/slices/ProjectSlice';

const MobileFooter = () => {
const dispatch = CoreModules.useAppDispatch();
const mobileFooterSelection = CoreModules.useAppSelector((state) => state.project.mobileFooterSelection);

console.log(mobileFooterSelection, 'mobileFooterSelection');

const footerItem = [
{
id: 'explore',
title: 'Explore',
icon: (
<AssetModules.LocationOnIcon
className={`${
mobileFooterSelection === 'explore' ? 'fmtm-text-primaryRed' : 'fmtm-text-gray-500'
} fmtm-duration-300`}
/>
),
},
{
id: 'projectInfo',
title: 'Project Info',
icon: (
<AssetModules.InfoIcon
className={`${
mobileFooterSelection === 'projectInfo' ? 'fmtm-text-primaryRed' : 'fmtm-text-gray-500'
} fmtm-duration-300`}
/>
),
},
{
id: 'activities',
title: 'Activities',
icon: (
<AssetModules.TaskIcon
className={`${
mobileFooterSelection === 'activities' ? 'fmtm-text-primaryRed' : 'fmtm-text-gray-500'
} fmtm-duration-300`}
/>
),
},
{
id: 'others',
title: 'Others',
icon: (
<AssetModules.MoreVertIcon
className={`${
mobileFooterSelection === 'others' ? 'fmtm-text-primaryRed' : 'fmtm-text-gray-500'
} fmtm-duration-300`}
/>
),
},
];

return (
<div className="fmtm-absolute fmtm-bottom-0 sm:fmtm-hidden fmtm-w-full fmtm-border-t-[1px]">
<div className="fmtm-w-full fmtm-grid fmtm-grid-cols-4 fmtm-bg-white fmtm-pb-4 fmtm-pt-2 fmtm-gap-5 fmtm-px-2">
{footerItem.map((item) => (
<div
key={item.id}
onClick={() => dispatch(ProjectActions.SetMobileFooterSelection(item.id))}
className="fmtm-group fmtm-cursor-pointer"
>
<div
className={`fmtm-w-full fmtm-flex fmtm-justify-center fmtm-py-1 fmtm-rounded-3xl fmtm-mb-1 fmtm-duration-300 ${
mobileFooterSelection === item.id ? 'fmtm-bg-red-100' : 'group-hover:fmtm-bg-gray-200'
}`}
>
<div>{item.icon}</div>
</div>
<div className="fmtm-flex fmtm-justify-center">
<p
className={`${
mobileFooterSelection === item.id ? 'fmtm-text-primaryRed' : 'fmtm-text-gray-500'
} fmtm-duration-300 fmtm-text-sm`}
>
{item.title}
</p>
</div>
</div>
))}
</div>
</div>
);
};

export default MobileFooter;
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';
import AssetModules from '../../shared/AssetModules';

const MobileProjectInfoContent = ({ projectInfo }) => {
console.log('projectInfo', projectInfo);
return (
<div className="fmtm-flex fmtm-flex-col fmtm-gap-3 fmtm-mb-[10vh]">
<div className="fmtm-flex fmtm-gap-3 fmtm-border-b-[1px] fmtm-pb-2">
<AssetModules.InfoIcon className=" fmtm-text-primaryRed" sx={{ fontSize: '35px' }} />
<p className="fmtm-text-2xl">Project Information</p>
</div>
<div className="fmtm-flex fmtm-gap-3">
<p className="fmtm-text-2xl fmtm-text-primaryRed">#{projectInfo?.id}</p>
</div>
<div className="fmtm-flex fmtm-gap-3">
<p className="fmtm-text-xl">Name: </p>
<p className="fmtm-text-xl">{projectInfo?.title}</p>
</div>
<div className="fmtm-flex fmtm-flex-col">
<p className="fmtm-text-xl">Short Description:</p>
<p className="fmtm-text-lg fmtm-text-grey-700">{projectInfo?.short_description}</p>
</div>
<div className="fmtm-flex fmtm-flex-col">
<p className="fmtm-text-xl">Description:</p>
<p className="fmtm-text-lg fmtm-text-grey-700">{projectInfo?.description}</p>
</div>
</div>
);
};

export default MobileProjectInfoContent;
161 changes: 161 additions & 0 deletions src/frontend/src/components/ProjectDetails/ProjectOptions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import Accordion from '../../components/common/Accordion';
import React, { useState } from 'react';
import CoreModules from '../../shared/CoreModules';
import AssetModules from '../../shared/AssetModules';
import environment from '../../environment';
import { DownloadDataExtract, DownloadProjectForm } from '../../api/Project';
import MapLegends from '../../components/MapLegends';

const ProjectOptions = ({ setToggleGenerateModal }) => {
const dispatch = CoreModules.useAppDispatch();
const params = CoreModules.useParams();

const [toggleAction, setToggleAction] = useState(false);
const downloadProjectFormLoading = CoreModules.useAppSelector((state) => state.project.downloadProjectFormLoading);
const downloadDataExtractLoading = CoreModules.useAppSelector((state) => state.project.downloadDataExtractLoading);
const defaultTheme = CoreModules.useAppSelector((state) => state.theme.hotTheme);

const encodedId = params.id;
const decodedId = environment.decode(encodedId);

const handleDownload = (downloadType) => {
if (downloadType === 'form') {
dispatch(
DownloadProjectForm(`${import.meta.env.VITE_API_URL}/projects/download_form/${decodedId}/`, downloadType),
);
} else if (downloadType === 'geojson') {
dispatch(
DownloadProjectForm(`${import.meta.env.VITE_API_URL}/projects/${decodedId}/download_tasks`, downloadType),
);
}
};
const onDataExtractDownload = () => {
dispatch(
DownloadDataExtract(`${import.meta.env.VITE_API_URL}/projects/features/download/?project_id=${decodedId}`),
);
};
return (
<div className="fmtm-mt-4">
<div>
<div
className={`fmtm-flex fmtm-gap-5 fmtm-py-4 sm:fmtm-hidden fmtm-justify-between fmtm-items-center fmtm-mx-4 sm:fmtm-mx-7 fmtm-mb-2 ${
toggleAction ? 'fmtm-border-b-[#929DB3] fmtm-border-b-[1px]' : ''
}`}
>
<p className="fmtm-text-xl fmtm-italic">Project Options</p>
<div
className={
'fmtm-rounded-full fmtm-shadow-gray-400 fmtm-w-8 fmtm-h-8 fmtm-flex fmtm-justify-center fmtm-items-center fmtm-shadow-lg fmtm-cursor-pointer'
}
onClick={() => setToggleAction(!toggleAction)}
>
<AssetModules.ArrowRightIcon
color=""
style={{ fontSize: 32 }}
className={`${toggleAction ? 'fmtm-rotate-90' : ''}`}
/>
</div>
</div>
</div>
<div
className={`fmtm-flex fmtm-flex-col lg:fmtm-flex-row fmtm-gap-6 lg:fmtm-gap-0 fmtm-px-3 sm:fmtm-px-0 ${
toggleAction ? '' : 'fmtm-hidden sm:fmtm-flex'
}`}
>
<div className="fmtm-w-full fmtm-flex fmtm-flex-col fmtm-items-start sm:fmtm-flex-row sm:fmtm-justify-center lg:fmtm-justify-start sm:fmtm-items-center fmtm-gap-6 fmtm-ml-2 sm:fmtm-ml-4">
<CoreModules.LoadingButton
onClick={() => handleDownload('form')}
sx={{ width: 'unset' }}
loading={downloadProjectFormLoading.type === 'form' && downloadProjectFormLoading.loading}
loadingPosition="end"
endIcon={<AssetModules.FileDownloadIcon />}
variant="contained"
color="error"
>
Form
</CoreModules.LoadingButton>
<CoreModules.LoadingButton
onClick={() => handleDownload('geojson')}
sx={{ width: 'unset' }}
loading={downloadProjectFormLoading.type === 'geojson' && downloadProjectFormLoading.loading}
loadingPosition="end"
endIcon={<AssetModules.FileDownloadIcon />}
variant="contained"
color="error"
>
Tasks
</CoreModules.LoadingButton>
<CoreModules.LoadingButton
onClick={() => onDataExtractDownload()}
sx={{ width: 'unset' }}
loading={downloadDataExtractLoading}
loadingPosition="end"
endIcon={<AssetModules.FileDownloadIcon />}
variant="contained"
color="error"
className="fmtm-truncate"
>
Data Extract
</CoreModules.LoadingButton>
</div>
<div className="fmtm-flex fmtm-flex-col sm:fmtm-flex-row sm:fmtm-justify-center lg:fmtm-justify-end fmtm-w-full fmtm-ml-2 sm:fmtm-ml-4 fmtm-gap-6">
<CoreModules.Link
to={`/projectInfo/${encodedId}`}
style={{
display: 'flex',
justifyContent: 'flex-end',
alignItems: 'flex-end',
textDecoration: 'none',
marginRight: '15px',
}}
className="fmtm-w-fit"
>
<CoreModules.Button variant="contained" color="error">
ProjectInfo
</CoreModules.Button>
</CoreModules.Link>
<CoreModules.Button
onClick={() => setToggleGenerateModal(true)}
variant="contained"
color="error"
sx={{ width: '200px', mr: '15px' }}
endIcon={<AssetModules.BoltIcon />}
className="fmtm-truncate"
>
Generate MbTiles
</CoreModules.Button>
<CoreModules.Link
to={`/edit-project/project-details/${encodedId}`}
style={{
display: 'flex',
justifyContent: 'flex-end',
alignItems: 'flex-end',
textDecoration: 'none',
marginRight: '15px',
}}
className="fmtm-w-fit"
>
<CoreModules.Button variant="outlined" color="error" className="fmtm-truncate">
Edit Project
</CoreModules.Button>
</CoreModules.Link>
</div>
<div className="fmtm-px-1 sm:fmtm-hidden">
<Accordion
collapsed={true}
disableHeaderClickToggle
onToggle={() => {}}
header={<div className="fmtm-text-[#2C3038] fmtm-font-bold fmtm-text-xl">Map Legends</div>}
body={
<div className="fmtm-mt-4">
<MapLegends defaultTheme={defaultTheme} />
</div>
}
/>
</div>
</div>
</div>
);
};

export default ProjectOptions;
Loading

0 comments on commit d14062a

Please sign in to comment.