Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhancement/projects more filter #81

Merged
merged 22 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
036167b
made the main page static and enabled scrolling in the filters component
mtalhabaig3 Jun 21, 2023
88441ea
Solved the height issue of filters menu
mtalhabaig3 Jun 22, 2023
b18a98e
Merge branch 'hotosm:develop' into feature/5844/menu/height
mtalhabaig3 Jun 22, 2023
fde0541
minor changes
mtalhabaig3 Jun 22, 2023
7625f96
added dependency array
mtalhabaig3 Jun 23, 2023
f211ea0
remove the css for hiding scroll bar
mtalhabaig3 Jun 28, 2023
a68367f
Merge branch 'hotosm:develop' into feature/5844/menu/height
mtalhabaig3 Jun 28, 2023
66073a6
Merge branch 'hotosm:develop' into feature/5844/menu/height
mtalhabaig3 Jul 10, 2023
41d270c
Made dropdowns fixed and hide scroll bar
mtalhabaig3 Jul 10, 2023
e2b332a
removed comments
mtalhabaig3 Jul 11, 2023
585d461
Merge branch 'hotosm:develop' into feature/5844/menu/height
mtalhabaig3 Jul 11, 2023
c120198
Merge branch 'hotosm:develop' into feature/5844/menu/height
mtalhabaig3 Aug 17, 2023
8611239
solved the front end test error
mtalhabaig3 Aug 17, 2023
5dc659c
removed comments
mtalhabaig3 Aug 23, 2023
0ff9686
Merge branch 'develop' of github.com:hotosm/tasking-manager into enha…
spnayan Apr 10, 2024
67eee80
Prevent api call before filter apply in `Explore Projects` page
spnayan Apr 10, 2024
85dd23a
Fix z-index issue between select dropdown and toggle button in more f…
spnayan Apr 15, 2024
2309994
Increase padding in more filters footer button in more filter
spnayan Apr 15, 2024
d6e009a
Change More Filter to popover layout in laptop screen
spnayan Apr 15, 2024
39744bb
Add overlay on More Filter popover
spnayan Apr 15, 2024
aa3aea4
Close More Filter popover on outside click
spnayan Apr 15, 2024
982528b
Fix test case for More Filters
spnayan Apr 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion frontend/src/api/projects.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { remapParamsToAPI } from '../utils/remapParamsToAPI';
import api from './apiClient';
import { UNDERPASS_URL } from '../config';

export const useProjectsQuery = (fullProjectsQuery, action) => {
export const useProjectsQuery = (fullProjectsQuery, action, queryOptions) => {
const token = useSelector((state) => state.auth.token);
const locale = useSelector((state) => state.preferences['locale']);

Expand Down Expand Up @@ -35,6 +35,7 @@ export const useProjectsQuery = (fullProjectsQuery, action) => {
queryKey: ['projects', fullProjectsQuery, action],
queryFn: ({ signal, queryKey }) => fetchProjects(signal, queryKey),
keepPreviousData: true,
...queryOptions,
});
};

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/header/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export const Header = () => {
) : null;

return (
<header className="w-100 bb b--grey-light">
<header id="top-header" className="w-100 bb b--grey-light">
<UpdateDialog />
{checkUserEmail()}
{showOrgBar && (
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/projects/moreFiltersForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export const MoreFiltersForm = (props) => {
/>
</fieldset>
)}
<div className="tr w-100 mt3">
<div className="tr w-100 mt3 pb3 ph2">
<Link to="/explore">
<Button className="bg-white blue-dark mr1 f6 pv2">
<FormattedMessage {...messages.clear} />
Expand Down
7 changes: 4 additions & 3 deletions frontend/src/components/projects/projectNav.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,12 +90,12 @@ export const ProjectNav = (props) => {
setQuery(
{
...fullProjectsQuery,
omitMapResults:!isMapShown
omitMapResults: !isMapShown,
},
'pushIn',
);
// eslint-disable-next-line react-hooks/exhaustive-deps
},[isMapShown])
}, [isMapShown]);
const linkCombo = 'link ph3 f6 pv2 ba b--tan br1 ph3 fw5';

const moreFiltersAnyActive =
Expand All @@ -115,7 +115,7 @@ export const ProjectNav = (props) => {
// onSelectedItemChange={(changes) => console.log(changes)}
return (
/* mb1 mb2-ns (removed for map, but now small gap for more-filters) */
<header className="bt bb b--tan w-100 ">
<header id="explore-nav" className="bt bb b--tan w-100 ">
<div className="mt2 mb1 ph3 dib lh-copy w-100 cf">
<div className="w-80-l w-90-m w-100 fl dib">
<div className="dib">
Expand All @@ -125,6 +125,7 @@ export const ProjectNav = (props) => {
<ProjectsActionFilter setQuery={setQuery} fullProjectsQuery={fullProjectsQuery} />
<Link
to={filterRouteToggled}
id="more-filter-id"
className={`dn mr3 dib-l lh-title f6 ${linkCombo} ${moreFiltersCurrentActiveStyle} blue-dark`}
>
<FormattedMessage {...messages.moreFilters} />
Expand Down
100 changes: 94 additions & 6 deletions frontend/src/views/project.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { Suspense, useEffect } from 'react';
import React, { Suspense, useEffect, useState, useLayoutEffect, useRef } from 'react';
import { useSelector } from 'react-redux';
import ReactPlaceholder from 'react-placeholder';
import { Outlet, useLocation, useNavigate, useParams } from 'react-router-dom';
Expand All @@ -16,6 +16,10 @@ import { useSetTitleTag } from '../hooks/UseMetaTags';
import { NotFound } from './notFound';
import { ProjectDetailPlaceholder } from '../components/projectDetail/projectDetailPlaceholder';
import { useProjectsQuery, useProjectQuery } from '../api/projects';
import { useWindowSize } from '../hooks/UseWindowSize';
import { useOnClickOutside } from '../hooks/UseOnClickOutside';

const smallScreenSize = 960;

const ProjectCreate = React.lazy(() => import('../components/projectCreate/index'));

Expand All @@ -29,12 +33,20 @@ export const CreateProject = () => {

export const ProjectsPage = () => {
useSetTitleTag('Explore projects');
const { pathname } = useLocation();
const action = useSelector((state) => state.preferences['action']);
const [fullProjectsQuery, setProjectQuery] = useExploreProjectsQueryParams();
const isMapShown = useSelector((state) => state.preferences['mapShown']);
const searchResultWidth = isMapShown ? 'two-column' : 'one-column';

const { data: projects, status, refetch } = useProjectsQuery(fullProjectsQuery, action);
const {
data: projects,
status,
refetch,
} = useProjectsQuery(fullProjectsQuery, action, {
// prevent api call until the filters are applied
enabled: !pathname.includes('/explore/filters/'),
});

return (
<div className="pull-center">
Expand Down Expand Up @@ -139,22 +151,98 @@ export const ProjectsPageIndex = (props) => {
};

export const MoreFilters = () => {
const [position, setPosition] = useState({ top: 0, left: 0, height: 0, width: 0 });
const navigate = useNavigate();
const [fullProjectsQuery] = useExploreProjectsQueryParams();
const [componentHeight, setComponentHeight] = useState(`${window.innerHeight}px`);
const filterElement = document?.getElementById('more-filter-id');
const [width] = useWindowSize();

useEffect(() => {
document.body.style.overflow = 'hidden';
return () => {
document.body.style.overflow = 'auto';
};
}, []);

// calculate position of more filter button for layout
useLayoutEffect(() => {
if (!filterElement) return;
const { top, left, height, width } = filterElement.getBoundingClientRect();
setPosition({ top, left, height, width });
}, [filterElement, width]);

useEffect(() => {
const contentHeight =
document.getElementById('explore-nav').offsetHeight +
document.getElementById('top-header').offsetHeight;

const handleResize = () => {
setComponentHeight(window.innerHeight - contentHeight);
};

handleResize();

window.addEventListener('resize', handleResize);

return () => {
window.removeEventListener('resize', handleResize);
};
}, []);

const currentUrl = `/explore${
stringify(fullProjectsQuery) ? ['?', stringify(fullProjectsQuery)].join('') : ''
}`;
const moreFilterRef = useRef(null);

useOnClickOutside(moreFilterRef, (e) => {
if (e.target.id === 'more-filter-id') return;
navigate(currentUrl);
});

const isSmallScreen = width < smallScreenSize;

return (
<>
<div className="absolute left-0 z-4 mt1 w-40-l w-100 h-100 bg-white h4 ph1 ph5-l">
<MoreFiltersForm currentUrl={currentUrl} />
<div
ref={moreFilterRef}
className={`absolute z-4 bg-white ${
// compare screen size for two different design in small screen and large screen of filter section
isSmallScreen ? ' left-0 mt1 w-40-l w-100 h4 ph1 ph5-l' : 'pa2 ba b--light-gray'
}`}
style={
isSmallScreen
? { height: `${componentHeight}px` }
: {
// 250 is half the width of filter component to place filter exactly center of more-filter button
left: position.left - 250 + position.width / 2,
top: position.top + position.height + 10,
width: '31.25em',
boxShadow: '2px 1px 23px -1px rgba(143,130,130,0.75)',
}
}
>
<div
className={`${
isSmallScreen ? 'scrollable-container h-100 overflow-x-hidden overflow-y-auto' : ''
}`}
>
<MoreFiltersForm currentUrl={currentUrl} />
</div>
</div>
{!isSmallScreen && (
<div
style={{
left: `${position.left + position.width / 2}px`,
top: position.top + position.height + 2,
}}
className={`absolute w1 h1 bg-white bl bt b--grey-light rotate-45 z-5`}
/>
)}

<div
onClick={() => navigate(currentUrl)}
role="button"
className="absolute right-0 z-4 br w-60-l w-0 h-100 bg-blue-dark o-70 h6"
className="absolute right-0 z-2 br w-100-l w-0 h-100 bg-blue-dark o-70 h6"
/>
</>
);
Expand Down
10 changes: 10 additions & 0 deletions frontend/src/views/tests/project.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,16 @@ describe('UserProjectsPage Component', () => {
});

test('More Filters should close the more filters container when clicked outside the container', async () => {
jest.spyOn(document, 'getElementById').mockReturnValue({
offsetHeight: 100,
getBoundingClientRect: () => ({
top: 0,
left: 0,
height: 100,
width: 100,
}),
});

const { user, router } = createComponentWithMemoryRouter(
<QueryParamProvider adapter={ReactRouter6Adapter}>
<ReduxIntlProviders>
Expand Down
Loading