falling-fruit / falling-fruit-web Goto Github PK
View Code? Open in Web Editor NEWMobile-friendly website for Falling Fruit
Home Page: https://beta.fallingfruit.org
License: GNU General Public License v3.0
Mobile-friendly website for Falling Fruit
Home Page: https://beta.fallingfruit.org
License: GNU General Public License v3.0
Describe the bug
A clear and concise description of what the bug is.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
A clear and concise description of what you expected to happen.
Screenshots
If applicable, add screenshots to help explain your problem.
Describe the the feature request
Moving around the map should store the current bounds of the map into the URL's query params. When loading that URL, it should repopulate the bounds.
This needs to be closely integrated with the Redux store.
It'll be very useful to take a look at how Google Maps implements this.
Important info is @40.117881,-88.2468951,15z
.
Branch name: map-state-url
Add location search, with suggestions populated by Google Places Autocomplete.
Suggested branch name: location-search
Refs #22
use-places-autocomplete
: https://github.com/wellyshen/use-places-autocomplete@reach/combobox
: https://reach.tech/comboboxPlease, thoroughly read through the front pages of both pieces of documentation.
components/search/Search.js
, start building the location searchbox.as
prop of ComboboxInput
and the as
and children
props of ComboboxOption
to reuse styling from our Input
and ListEntry
. (hint: pass as={Input}
to ComboboxInput
)react-router-dom
's query params (history.push, useParams, and useEffect (to update the map when the params change))@reach/combobox
source code, as a reference: https://github.com/reach/reach-ui/blob/main/packages/combobox/src/index.tsxWraps <select>
.
Styled similarly to Input
.
Branch name: form-select
Describe the bug
The Google Map React Library increments longitudinal bounds by 360 degrees for every revolution ("roll around") by the user from the left or the right. This causes the API to return empty data instead of clusters and locations during roll arounds of 360 degrees or more as the API does not recognize the scaled longitudes. Roll arounds to the left decrement by 360 each time and increment by 360 each time for roll arounds to the right.
To Reproduce
Steps to reproduce the behavior:
Screenshots
First screenshot: map with longitudinal bounds that are in scope of API
Second screenshot: map after around to right with longitude bound incremented by 360
Third screenshot: map after roll around to left with longitude bound decremented by 360
Style and wrap @reach/slider to make a slider component:
Note that this doesn't including styling the labels, just the sliders themselves.
All of the styling can be done via styled components and selectors.
Branch name: form-slider
ui/Slider.js
.Create progress bar showing the steps in the form:
ui/ProgressBar.js
Branch name: form-progress
The reviews feature is composed of two parts -- (a) the review display on the location details page and (b) the review form. The review form allows a user to submit a review for a particular location. Reviews contain information about a visit to a location, including the various qualitative factors (fruiting, yield, etc), as well as a quick description. Please check Figmas for most recently updated user flows + designs (and the feature specification doc for any other information).
Adds list view.
Mobile:
Desktop:
Epic: #54
Once finished with mobile, start thinking about component design for desktop
Redirect to map page with modal for non-existent routes
react-toastify
!The location information view displays all the information about a particular location. This includes information on the location itself, as well as the type of edible, and the particular edible (whether or not it is ripe, etc). Locations can be reviewed, edited, and reported. Locations also have an option to "teleport" to their address.
To interface with Ethan's API, we'll need an API wrapper containing functions that will make the actual request to the backend. This includes requests for getting a list of clusters in a specific region, getting a list of locations in a region, getting a list of types, etc. It also includes POST requests, like adding reviews and locations.
This feature is incredibly important! You'll be setting the standard for how the rest of our developers access the backend.
It's totally possible to create a series of functions that takes parameters in the exact same format as the REST endpoints do. It's also often best for those functions to be relatively "thin" wrappers. However, as library designers, we also have to consider "how can we create an interface that easy-to-use and intuitive for the developers who use our library?"
src/utils/api.js
that will cover all the functionality in v0.2 of the Falling Fruit APIIf you're unsure, it's best to keep the API wrappers "thin," i.e. not too different from the REST endpoints.
Search results primary text color is not right
Add resizable pane to desktop layout. This will contain the search bar, filters, explore, options, etc.
Add labels to the locations on the map.
Relevant component: components/map/Location.js
Branch name: map-labels
ui/
. This should be modeled off of SearchContext
showLabels
field in the objectReports are used to flag locations that may not be valid. An admin can then review and edit/delete the given location. In the desktop version, this is a small popup, so this can be more minimal / less invasive.
Please check Figmas for most recently updated user flows + designs (and the feature specification doc for any other information).
Describe the bug
A clear and concise description of what the bug is.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
A clear and concise description of what you expected to happen.
Screenshots
If applicable, add screenshots to help explain your problem.
Wrap ListEntry, use CircleIcon, Input, IconButton
Component: ui/CaptionInput.js
Branch name: form-caption-input
The location form allows users to submit a new location to pin on the map. Please check Figmas for most recently updated user flows + designs, as well as the Feature Spec Doc for a detailed user flow and field explanations.
The main parts of the user flow include:
Describe the bug
The react-dropdown-tree-select library that we use for type filtering uses an infinite scroll component internally. This is supposed to limit the tree to 100 items initially, and should load more as you scroll to the bottom. Currently, all data is fetched, however additional types are not loaded into the tree selector if you scroll to the bottom.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
Additional type options should be loaded into the tree selector as you scroll towards the bottom.
Many users prefer OpenStreetMap as a basemap because it is much more detailed than Google Maps in some regions. See https://github.com/falling-fruit/falling-fruit/blob/master/app/assets/javascripts/mapcommon.js#L134 for implementation details.
Hook up the Google Maps wrapper component (Map
) to Ethan's API (via utils/api
). This is done in pages/MapPage
.
Refs #21
async
/await
!getClusters
from utils/api
. Try mousing over getClusters
in VS Code to see what params it takes.muni: 1
to getClusters
and getLocations
.Describe the the feature request
A clear and concise description of the feature.
Add a dropdown select in the user account panel allowing users to choose the default language to use when they are logged in to the website and their is no locale specified in the url.
The main map view of the app is where users will first land and is likely where they will spend most of their time. This map view displays all of the locations in a given area that are available for foraging.
Falling Fruit comes with a huge number of location types. The filters should help the user narrow down what sorts of locations they'd like to explore.
Add location and seasonality to entry details:
Full entry details page for context:
Closes #47
setView(fitContainerBounds(getGeolocationBounds({ bounds of the location })
<Location>
if location.id === selectedLocation
Use react-google-maps to create a new component, Map
, that is able to render locations and clusters on a Google Maps view. This component will wrap react-google-maps
.
This component will not interface with the API. This is important because we'd like to separate out the API calls into the page component that will pass which clusters or locations to render to your Map
component.
These points are a rough guideline. Please feel free to discuss with me and other devs about the best way to design this component!
components
directory in src
Map
componentonClusterSelect
callback that is called when a "cluster" is selected. Called with cluster id as the argumentonLocationSelect
callback that is called when a "location" is selected. Called with location id as the argumentonDeselect
callback that is called when the map is clicked, "deselecting" location or cluster. Maybe combine with onClusterSelect
and onLocationSelect
? Maybe combine all 3 together? Up to you.clusters
Array of objects {id: xxx, lat: xxx, lng: xxx, radius: xxx, text: xxx}
displayed as colored circle on the maplocations
Array of objects {id: xxx, lat: xxx, lng: xxx}
displayed as pins on the mapcenter
, zoom
, bounds
. We want to make these fields controlled. In other words, the true center
and zoom
depend on the values of these props, not on internal state, and when these properties update (when a user zooms in, etc), call onCenterChanged
or onBoundsChanged
to let the parent component know. Review what a controlled component is here.Add list of reviews to the entry details page:
Full entry details page (for context):
Refactor the existing tree select component to handle displaying the currently selected types, and so that it's not tied to context (tied to props). Then, there will be two instances of the tree select: one in filter, one in the new location form. Take a prop that shows whether or not to display tags.
Branch name: form-type-selection
Add global styles and themes, along with a few example components that use Reach UI. We are using Reach UI to ensure accessibility in this project.
Describe the the feature request
A clear and concise description of the feature.
Pretty self-explanatory. Users should be able to search and travel to new addresses.
Add an entry details page that gets triggered when the user clicks a location on the screen.
Suggested branch name: entry-details
Refs #24
styled-components
MapPage
, call history.push
(react-router) with /entry/{locationId}
when a location is clicked.EntryDetails
page with all the information from a getLocation
request, with the given ID in the route.IconButton
UI component that wraps HTML button
. Two versions:EntryNav
component, which is the top bar here:EntryNav
work as expected by calling history.goBack
EntryDetails
for the desktop. Put this in the desktop
folder. Same thing with the back button as in the mobile EntryNav
.SidePane
to make the desktop EntryDetails
appear. You can follow my example in MobileLayout
.This is it. The big finale to FF's MVP: Type Filtering.
As the user scrolls around on the map, they would like to filter by one or more types. The types that are available to filter directly reflects the types that are currently visible on the map. This means that you can filter in cluster view or location view. It also means that you should GET /types.json
each time the map scrolls, and provide the NE/SW lat/lng of the viewport as well; the API will handle giving you the types that have at least one location inside the viewport, as well as their respective counts.
Currently on fallingfruit.org, the website only supports filtering by at most one type. Our app will offer filtering by any number of types. Note that the backend already supports this by taking an array of types; it's just that the current website does not, because UI is tricky.
We have decided to solve this problem with a hierarchal tree select, using this library: react-dropdown-tree-select.
Additionally, types are represented in a hierarchal format. For now, Ethan has chosen to limit the depth of the hierarchy to 1, so assume that for now:
The API data gives this tree by specifying a parent_id
for each type in GET /types/{id}.json
. You will have to build this tree in order to show the hierarchy, because the tree select library expects data in the form of nested objects. (CS 225, anyone?)
Right now, it seems that rebuilding the tree after the map scrolls would be slow because parent_id
is currently not included in GET /types.json
, which means you'd have to GET /types/{id}.json
for each type, which fallingfruit.org definitely does not do. @ezwelty, does the current app get the type hierarchy from somewhere? How would we do that as well? See bottom of issue for more details.
Another difference we'll have is the type counts. On fallingfruit.org, the count of the parent type is not the sum of the counts of the child types:
Notice how 0 != 2 + 12
. It's this way because the count on the parent actually represents the number of locations that are categorized as just "Maple", and not a specific kind of maple. (Let's call them uncategorized maples.) When you click on it, however, it seems that the website does explicitly select the parent and its children (all maples). You'll see that the count also updates to the sum 14.
This is unintuitive, and will also not conceptually work with our tree select, since it's implied that clicking on the parent type will select all the child types. We've decided to solve this by moving the uncategorized maples to a child category "Other" under the general type Maple (see designs below). That "Other" will own the uncategorized count, and the parent type will then have the sum of its children's counts.
Filtering is implemented by sending an array of type IDs to the backend in requests such as GET /locations.json
and GET /types.json
. We currently have a React context called SearchContext
that conveys the viewport of selected search results to MapPage
, so it can pan to the searched location. You can take advantage of that context to sync the list of currently filtered type IDs to MapPage
as well, so it can include those in its GET /locations.json
requests.
We also use React context for sharing the current viewport of the map across components. That's in MapContext
's view
.
There are tons of types in FF, so it's critical that the user can search for them while filtering. Luckily, the library we're using provides searching built-in. Note these options:
keepTreeOnSearch: By default the tree gets flattened when you're searching, but we want the tree to stay.
Unlike Reach UI, the library we're using doesn't have as
props to specify what components to use for checkboxes, inputs, etc. So we will likely have to replicate styles from our existing UI components, without being able to use the components themselves.
Make sure to reference react-dropdown-tree-select's styling tips, specifically the default class names so that you can select them while styling the outer component.
Suggested branch name: type-filtering
Suggested PR title (as would probably be suggested by @code-arman): <some relevant emoji> Add type filtering
Refs #23
IconButton
Search
component so it doesn't get too longMapContext
SearchContext
useContext
hooks anywhere we need it.parent_id
in GET /types.json
so we don't have to make additional GET requests for each type. Rebuilding the actual tree will probably be very fast compared to the overhead of making the network request, so this should work fine for now.The library we're using now supports virtualization out of the box, which means that DOM elements are only rendered as they scroll into view. Definitely great to have.
A complement to the map view, the list view will display locations in a list format, making it easier to easily skim and find types. This is especially important for accessibility reasons, and the desktop version does not currently have a list view.
Please check Figmas for most recently updated user flows + designs (and the feature specification doc for any other information).
Create three new presentational components in components/ui
:
ListEntry
ListCategory
MapTooltip
children
prop in Reactstyled-components
Please follow the existing UI components in components/ui
as examples.
@reach/tooltip
first)
PageTabs
as an example of how to wrap Reach UI!PropTypes.oneOfType([ PropTypes.arrayOf(PropTypes.node), PropTypes.node ])
Describe the the feature request
A clear and concise description of the feature.
Allow selecting current location as an option in the search bar/suggestions
These points are a rough guideline. Please feel free to discuss with others on the team about the best way to design this component!
In particular thinking about how the new useReducer calls would integrate with the contexts we use.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.