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

Bounds Search #765

Merged
merged 6 commits into from
Oct 31, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
22 changes: 18 additions & 4 deletions app/services/stakeholder-best-service.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ record has been approved, it will be the most recent version (i.e., have
If you make changes to the database structure, be sure to update these
methods as well as the corresponding methods in the stakeholder-service.js.

You can search by max/min lat, lng bounds or by a center and radius(distance),
with bounds taking precedence.

*/

const booleanEitherClause = (columnName, value) => {
Expand All @@ -27,13 +30,16 @@ const search = async ({
latitude,
longitude,
distance,
maxLat,
maxLng,
minLat,
minLng,
isInactive,
verificationStatusId,
tenantId,
}) => {
const locationClause = buildLocationClause(latitude, longitude);
const categoryClause = buildCTEClause(categoryIds, "");

const sql = `${categoryClause}
select s.id, s.name, s.address_1, s.address_2, s.city, s.state, s.zip,
s.phone, s.latitude, s.longitude, s.website, s.notes,
Expand Down Expand Up @@ -69,9 +75,11 @@ const search = async ({
${buildLoginSelectsClause()}
from stakeholder_set as s
${buildLoginJoinsClause()}
where s.tenant_id = ${tenantId}
where s.tenant_id = ${tenantId}
${
Number(distance) && locationClause
maxLat && maxLng && minLat && minLng
? buildBounds({ maxLat, maxLng, minLat, minLng })
: Number(distance) && locationClause
? `AND ${locationClause} < ${distance}`
: ""
}
Expand All @@ -83,7 +91,6 @@ const search = async ({
}
order by distance
`;
// console.log(sql);
let stakeholders = [];
let categoriesResults = [];
var stakeholderResult, stakeholder_ids;
Expand Down Expand Up @@ -349,6 +356,13 @@ const buildLocationClause = (latitude, longitude) => {
return locationClause;
};

const buildBounds = ({ maxLat, maxLng, minLat, minLng }) => {
return `
AND s.latitude BETWEEN ${minLat} AND ${maxLat}
AND s.longitude BETWEEN ${minLng} AND ${maxLng}
`;
};

const buildLoginJoinsClause = () => {
return `
left join login L1 on s.created_login_id = L1.id
Expand Down
13 changes: 7 additions & 6 deletions client/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { makeStyles, ThemeProvider } from "@material-ui/core/styles";
import { Grid } from "@material-ui/core";
import theme from "theme/materialUI";
import { logout } from "services/account-service";
import { tenantId, originCoordinates } from "helpers/Configuration";
import { tenantId, defaultCoordinates } from "helpers/Configuration";

// Components
import { UserContext } from "components/user-context";
Expand Down Expand Up @@ -75,8 +75,8 @@ function App() {
const [toast, setToast] = useState({ message: "" });
const [bgImg, setBgImg] = useState("");
const [origin, setOrigin] = useState({
latitude: originCoordinates.lat,
longitude: originCoordinates.lon,
latitude: defaultCoordinates.lat,
longitude: defaultCoordinates.lon,
});

useEffect(() => {
Expand Down Expand Up @@ -127,8 +127,8 @@ function App() {
(error) => {
console.log(`Getting browser location failed: ${error.message}`);
const userCoordinates = {
latitude: originCoordinates.lat,
longitude: originCoordinates.lon,
latitude: defaultCoordinates.lat,
longitude: defaultCoordinates.lon,
};
setUserCoordinates(userCoordinates);
}
Expand Down Expand Up @@ -176,7 +176,8 @@ function App() {
<Route path="/organizations">
<Results
userCoordinates={userCoordinates}
userSearch={origin}
origin={origin}
setOrigin={setOrigin}
setToast={setToast}
/>
</Route>
Expand Down
137 changes: 30 additions & 107 deletions client/src/components/Results/ResultsContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Grid } from "@material-ui/core";
import { useOrganizationBests } from "hooks/useOrganizationBests";
import useCategoryIds from "hooks/useCategoryIds";
import { isMobile } from "helpers";
import { originCoordinates } from "helpers/Configuration";
import { defaultCoordinates } from "helpers/Configuration";
import { DEFAULT_CATEGORIES } from "constants/stakeholder";

import Filters from "./ResultsFilters";
Expand All @@ -25,11 +25,11 @@ const useStyles = makeStyles((theme) => ({

export default function ResultsContainer({
userCoordinates,
userSearch,
origin,
setOrigin,
setToast,
}) {
// Component state
const storage = window.sessionStorage;
const { data, search } = useOrganizationBests();
const [sortedData, setSortedData] = useState([]);
const classes = useStyles();
Expand All @@ -38,77 +38,34 @@ export default function ResultsContainer({
const [isMapView, setIsMapView] = useState(true);
const mobileView = isMobile();

const doSelectStakeholder = useCallback((stakeholder) => {
if (stakeholder && !mobileView) {
setViewport({
...viewport,
latitude: stakeholder.latitude,
longitude: stakeholder.longitude,
});
}
onSelectStakeholder(stakeholder);
const { categoryIds, toggleCategory } = useCategoryIds([]);
const [isVerifiedSelected, selectVerified] = useState(false);
const [viewport, setViewport] = useState({
zoom: defaultCoordinates.zoom,
latitude: origin.latitude,
longitude: origin.longitude,
logoPosition: "top-left",
});

const doSelectStakeholder = useCallback(
(stakeholder) => {
if (stakeholder && !isMobile) {
setViewport({
...viewport,
latitude: stakeholder.latitude,
longitude: stakeholder.longitude,
});
}
onSelectStakeholder(stakeholder);
},
[viewport, setViewport]
);

const switchResultsView = () => {
doSelectStakeholder();
setIsMapView(!isMapView);
};

const initialCategories = storage.categoryIds
? JSON.parse(storage.categoryIds)
: [];
const { categoryIds, toggleCategory } = useCategoryIds(initialCategories);

const initialCoords = {
locationName: userSearch
? userSearch.locationName
: storage.origin
? JSON.parse(storage.origin).locationName
: "",
latitude: userSearch
? userSearch.latitude
: storage.origin
? JSON.parse(storage.origin).latitude
: userCoordinates
? userCoordinates.latitude
: originCoordinates.lat,
longitude: userSearch
? userSearch.longitude
: storage.origin
? JSON.parse(storage.origin).longitude
: userCoordinates
? userCoordinates.longitude
: originCoordinates.lon,
};

const [radius, setRadius] = useState(
storage?.radius ? JSON.parse(storage.radius) : 5
);
const [origin, setOrigin] = useState(initialCoords);
const [isVerifiedSelected, selectVerified] = useState(
storage?.verified ? JSON.parse(storage.verified) : false
);

const viewPortHash = {
0: 4,
1: 13.5,
2: 12.5,
3: 12,
5: 11,
10: 10,
20: 9,
50: 8,
100: 7,
500: 4.5,
};

const [viewport, setViewport] = useState({
zoom: viewPortHash[radius || 0],
latitude: origin.latitude || JSON.parse(storage.origin).latitude,
longitude: origin.longitude || JSON.parse(storage.origin).longitude,
logoPosition: "top-left",
});

// Component effects

useEffect(() => {
Expand All @@ -135,74 +92,46 @@ export default function ResultsContainer({
setSortedData(data.sort(sortOrganizations));
}, [data]);

useEffect(() => {
return () => {
sessionStorage.clear();
};
}, []);

const handleSearch = useCallback(
(e, center) => {
(e, center, bounds) => {
if (e) e.preventDefault();
search({
latitude:
(center && center.lat) ||
origin.latitude ||
userCoordinates.latitude ||
JSON.parse(storage.origin).latitude,
(center && center.lat) || origin.latitude || userCoordinates.latitude,
longitude:
(center && center.lng) ||
origin.longitude ||
userCoordinates.longitude ||
JSON.parse(storage.origin).longitude,
radius,
userCoordinates.longitude,
categoryIds: categoryIds.length ? categoryIds : DEFAULT_CATEGORIES,
isInactive: "either",
verificationStatusId: 0,
bounds,
radius: defaultCoordinates.radius,
});
if (origin.locationName && origin.latitude && origin.longitude)
storage.origin = JSON.stringify({
locationName: origin.locationName,
latitude: origin.latitude,
longitude: origin.longitude,
});

storage.categoryIds = JSON.stringify(categoryIds);
storage.radius = JSON.stringify(radius);
storage.verified = JSON.stringify(isVerifiedSelected);
if (!center)
setViewport({
zoom: viewPortHash[radius || 0],
zoom: defaultCoordinates.zoom,
latitude: origin.latitude,
longitude: origin.longitude,
});
doSelectStakeholder(null);
},
[
search,
origin.locationName,
origin.latitude,
origin.longitude,
userCoordinates.latitude,
userCoordinates.longitude,
radius,
categoryIds,
isVerifiedSelected,
setViewport,
doSelectStakeholder,
viewPortHash,
storage.categoryIds,
storage.radius,
storage.verified,
storage.origin,
]
);

return (
<>
<Filters
radius={radius}
setRadius={setRadius}
origin={origin}
setOrigin={setOrigin}
toggleCategory={toggleCategory}
Expand All @@ -211,9 +140,6 @@ export default function ResultsContainer({
selectVerified={selectVerified}
userCoordinates={userCoordinates}
handleSearch={handleSearch}
viewport={viewport}
setViewport={setViewport}
viewPortHash={viewPortHash}
isMapView={isMapView}
switchResultsView={switchResultsView}
/>
Expand All @@ -229,16 +155,13 @@ export default function ResultsContainer({
{(!mobileView || (mobileView && isMapView)) && (
<Map
handleSearch={handleSearch}
selectedLatitude={initialCoords.latitude}
selectedLongitude={initialCoords.longitude}
viewport={viewport}
setViewport={setViewport}
stakeholders={data}
doSelectStakeholder={doSelectStakeholder}
selectedStakeholder={selectedStakeholder}
categoryIds={categoryIds}
setToast={setToast}
search={search}
/>
)}
</Grid>
Expand Down
Loading